I'm trying to create Application specific mappings to a parent folder. For some reason, this works on my local dev environment, I get the error
invalid component definition, can't find component [cfc.udf]
Directory structure:
--- website1
------- application.cfc
--- cfc
------ udf.cfc
Code on application.cfc:
<cfcomponent>
<cfset This.name = "Website1">
<cfset This.Sessionmanagement=true>
<cfset This.Sessiontimeout="#createtimespan(0,0,30,0)#">
<cfset this.mappings["/cfc"] = expandPath('../cfc') />
<cffunction name="onApplicationStart">
<cfset Application.udf = createObject("cfc.udf")>
</cffunction>
</cfcomponent>
I'm using Lucee 1.5
When I output the application, like so:
<cfset app = CreateObject("component", "application") />
<cfdump var="#app#">
I get
MAPPINGS
Struct
cfc string D:\WebSites\parent-directory\cfc
I'm a bit lost
UPDATE:
in response to #leigh:
--- parent-directory
--- website1
--- application.cfc
--- cfc
--- udf.cfc
Turns out it had nothing to do with Coldfusion or Lucee.
The problem was how we had the sites set up on IIS. We had to switch from IP + : + port to using a subdomain for this environment. So, tomkat was looking in the wrong context... Or at least that's what I was told. This is a bit outside the layer of abstraction that I'm most comfortable with.
Related
Anyone know a way to create dynamic subdomains in coldfusion 11 without having to add them to a dns server?
I want to be able to redirect each of my clients in a personalized subdomain every time they log in to my system.
ex: client1.example.com client2.example.com
This works if your site is hosted in a Windows IIS server.
If you are using IIS then the following can help you. Use loops and conditions as your requirements.
<!--- Provide you IIS SiteName --->
<cfset siteName = "Your IIS Site Name">
<!--- Your new domain address --->
<cfset newSiteBinding = "client2.example.com">
<!--- your port address --->
<cfset newSitePort = 80>
<cfset fileID = createUUID()>
<cfsavecontent variable="ex"><cfoutput>cd %windir%\system32\inetsrv
%windir%\system32\inetsrv\APPCMD set site /site.name: #siteName# /+bindings.[protocol='http',bindingInformation='*:#newSitePort#:#newSiteBinding#']</cfoutput>
</cfsavecontent>
<cffile action = "write"
file = "E:\#fileID#.bat"
output = "#ex#"
/>
<cfexecute name="E:\#fileID#.bat"
arguments="/c set"
variable="data"
timeout="10"
/>
<cffile action = "delete"
file = "E:\#fileID#.bat"
>
What we are basically doing is that we are creating a .bat file and executing it using cfexecute. Please note that you need to be careful with the paths because the Directory structure might be different in your server.
.BAT file content Example
cd %windir%\system32\inetsrv
%windir%\system32\inetsrv\APPCMD set site /site.name: example /+bindings.[protocol='http',bindingInformation='client2.example.com:80:*']
How the command works. Notice the + at /+bindings?
That means adding a new binding and /-bindings tries to remove an existing binding.
I'm in the process of switching over from using Application.cfm to Application.cfc and I'm using Ben Nadel's method for extending my application into a sub folder using an application proxy. (link to article)
The problem I'm having is that when I load a page in a sub folder all cfinclude tags that are called in the root Application.cfc file bring up a "Could not find the included template..." error message. (The include is intentionally at the top of the component so I can set application specific variables)
Here are a few requirements:
The application has to be run without access to the ColdFusion administrator.
The application may or may not reside in a sub folder of another site (i.e. www.example.com/ or localhost/mysite/)
Here's the file structure:
/application.cfc
/include_me.cfm
/index.cfm
/sub/application.cfc
/sub/application_rootProxy.cfc
/sub/index.cfm
Root Application.cfm:
<cfcomponent
output="false"
hint="I define the application settings and event handlers.">
<!--- Define the application settings. --->
<cfset this.name = "TestApplication" />
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 10, 0 ) />
<!---
Store the path of the current template. We want to see if
this shows up as the root template or the sub template.
--->
<cfset this.ROOT_currentTemplatePath = getCurrentTemplatePath() />
<!--- Set a variable to indicate that the included file hasn't been run yet --->
<cfset this.includedFile = "no" />
<!--- include the file --->
<cfinclude template="include_me.cfm" />
<cffunction
name="onApplicationStart"
access="public"
returntype="boolean"
output="false"
hint="I initialize the application.">
<!--- Set some app variables for testing. --->
<cfset application.ROOT_onApplicationStart = true />
<!--- Return true so the page can process. --->
<cfreturn true />
</cffunction>
<cffunction
name="onRequestStart"
access="public"
returntype="boolean"
output="false"
hint="I initialize the request.">
<!--- Set some request variables for testing. --->
<cfset request.ROOT_onRequestStart = true />
<!--- Return true so the page can process. --->
<cfreturn true />
</cffunction>
<cffunction
name="onRequest"
access="public"
returntype="void"
output="true"
hint="I process the user's request.">
<!--- Define arguments. --->
<cfargument name="script"type="string" required="true"hint="I am the request script." />
<!--- Output the current THIS collection. --->
<cfdump var="#this#" label="THIS" />
<!--- Include (execute) requested script. --->
<cfinclude template="#arguments.script#" />
<!--- Return out. --->
<cfreturn />
</cffunction>
</cfcomponent>
Root Include_me.cfm:
<!--- update the value so we know the file was indeed included --->
<cfset this.includedFile = "yes" />
Sub Folder Application.cfc
<!--- extends the application so we can make changes when needed --->
<cfcomponent extends="application_rootProxy">
<cfset this.SUB_currentTemplatePath = getCurrentTemplatePath() />
</cfcomponent>
Sub Folder Root Proxy:
<cfinclude template="../application.cfc">
What is the correct way to allow cfinclude tags in the base application.cfc when you're accessing the application through a root proxy?
My initial instinct was to see if I could calculate the application root dynamically and luckily getCurrentTemplatePath() is able to differentiate between the sub application.cfc and the root application.cfc. However cfincludes don't work when you try and access them via a local file system link (e.g. d:\mysite\include_me.cfm). It looks like I need to somehow figure out the dynamic relative position of the included file based on the sub directory of the executing application.cfc. Any and all help is appreciated!
I may be on to something... and if this is the answer hopefully it will help someone else out who finds themselves in a similar predicament.
I noticed that the cfinclude within the OnRequest() method processes normally regardless of whether the template is being called from the root of the application or a sub directory. Therefore I theorized if I put my cfincludes within methods they might execute properly.
So instead of placing my cfincludes at the top of my root component:
<cfcomponent>
<cfinclude="include_me.cfm">
...
</cfcomponent>
I can put them in a separate method and then call that method within the component:
<cfcomponent>
<!--- call the method which includes the file --->
<cfset includeFile() />
<!--- new method for including the file --->
<cffunction name="includeFile">
<cfinclude="include_me.cfm">
</cffunction>
...
</cfcomponent>
The key to this seems to be not including anything in application.cfc unless it's contained within a method.
I'm not sure what's causing what you're seeing, but you do have an unorthodox way of proxying your Application.cfc
This doesn't solve your issue, but here is a demonstration of doing the proxying correctly, and this doesn't have the include pathing issue you're seeing.
All the code is here: https://gist.github.com/daccfml/3ed091c62d688595d66e
/Application.cfc
component {
writeOutput("#getCurrentTemplatePath()# called<br>");
include "inc.cfm";
}
/inc.cfm
<cfoutput>#getCurrentTemplatePath()# called<br></cfoutput>
/ApplicationProxy.cfc
component extends="Application" {
writeOutput("#getCurrentTemplatePath()# called<br>");
}
/sub/Application.cfc
component extends="ApplicationProxy" {
writeOutput("#getCurrentTemplatePath()# called<br>");
}
/sub/test.cfm
<cfoutput>#getCurrentTemplatePath()# called<br></cfoutput>
This outputs:
C:\wwwroot\Application.cfc called
C:\wwwroot\inc.cfm called
C:\wwwroot\ApplicationProxy.cfc called
C:\wwwroot\sub\Application.cfc called
C:\wwwroot\sub\test.cfm called
Which is what I'd expect.
Rearrange your code to do the proxying correctly, and hopefully your issue will disappear. If not, update your question and we can revisit.
I am running into a weird issue with my ColdFusion 10 code. I am new to ColdFusion, so go easy on me. The reason it is weird is because it does not seem to occur in older versions of this platform (i.e. MX 7).
A little info first:
I have two environments. A ColdFusion 10 and a ColdFusion MX 7 (IIS 7 and IIS 5, respectively). In the ColdFusion 10 environment, I have an Application.cfc file with the following statement...
<cfset CompanyLogoText = "Acme Company">
This Application.cfc file is in the web root (mydomain.com). I also have a CFM file in a sub folder of the web root at mydomain.com/pages/default.cfm. It contains the following markup...
<cfoutput><p>#CompanyLogoText#</p></cfoutput>
The issue
When I navigate to mydomain.com/pages/default.cfm, I get an error from coldfusion. The error is "Variable COMPANYLOGOTEXT is undefined."
The weird part
I am not getting this error in the ColdFusion MX 7. The only difference is that the CF MX 7 environment uses a Application.cfm file, but with the same exact line.
Question
How can I get the pages/default.cfm file to see my variable CompanyLogoText in the CF 10 environment?
Here is the full markup
Application.cfc
<cfcomponent>
<cfset This.name = "test_cf">
<cfset This.Sessionmanagement="yes">
<cfset This.Sessiontimeout="#createtimespan(0,0,10,0)#">
<cfset This.applicationtimeout="#createtimespan(5,0,0,0)#">
<cfset This.setclientcookies="no" >
<cfset This.clientmanagement="no">
<cffunction name="onApplicationStart">
<cfset CompanyLogoText = "Acme Company">
</cffunction>
<cffunction name="onRequestStart">
<cfargument name="requestname" required=true />
<cfset CompanyLogoText = "Acme Company">
</cffunction>
</cfcomponent>
Pages/Default.cfm
<cftry>
<cfoutput><p>#CompanyLogoText#</p></cfoutput>
<cfcatch>
<p>Could not read CompanyLogoText<br/><br/>
<cfoutput>
<br/>Message: #cfcatch.message#
<br/>Details: #cfcatch.detail#.
</cfoutput>
</cfcatch>
</cftry>
That's the difference between Application.cfm and Application.cfc
Use onRequest(), set the variables, then cfinclude the target file. That's the only way to share the variables scope.
https://wikidocs.adobe.com/wiki/display/coldfusionen/onRequest
e.g.
<cffunction name="onRequest" returnType="void">
<cfargument name="targetPage" type="String" required=true/>
<cfinclude template="globalVars.cfm">
<cfset variables.foo = "bar">
<cfinclude template="#Arguments.targetPage#">
</cffunction>
QUOTE: CF8: Migrating from Application.cfm to Application.cfc
Put in the onRequest method any code that sets Variables scope
variables and add a cfinclude tag that includes the page specified by
the method's Arguments.Targetpage variable.
As mentioned your application.cfc needs to be formatted correctly. Your best bet is to give this a read and format your .cfc accordingly.
http://www.bennadel.com/blog/726-ColdFusion-Application-cfc-Tutorial-And-Application-cfc-Reference.htm
Don't see an answer marked yet. If you have an application.cfm file in the sub-directory it will override the application.cfc in the root. Just a possibility ...
In my application I have a header and footer include. In my Application.cfc I've set up a function that names my application and sets mapping.
<cfcomponent output="no">
<cfset this.name = "thesitename">
<cfset this.datasource = "thesitedatasource">
<cfset this.rootDir = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings = structNew()>
<cfset this.mappings["/planning"] = "#this.rootDir#planning/" />
<cfset this.mappings["/images"] = "#this.rootDir#images/" />
<cfset this.mappings["/includes"] = "#this.rootDir#includes/" />
<cfset this.mappings["/js"] = "#this.rootDir#js/" />
<cfset this.mappings["/portfolio"] = "#this.rootDir#portfolio/" />
</cfcomponent>
If I have a page in a subdirectory like this: planning/index.cfm the <cfinclude> can't locate anything in the images folder when I use the following path: <li class="imagelink"><img src="/images/facebook.png"></li>
Pages in the root directory don't have a problem.
If I understand correctly, the problem has to do with the mapping doesn't take place prior to the include being called, or something like that... How do I get the mapped paths to work properly in my include?
ColdFusion mappings are completely separate from a web server 'alias' or 'virtual directory'. In order for your code to work, you will need to add a web server mapping, 'alias' in Apache or 'virtual directory' in IIS, named 'images' that points to the directory where you keep the images.
The 'images' ColdFusion mapping will only work in ColdFusion - for example, when creating an object, you could use createObject( "component", "images.image") (assuming of course that you had a CFC named Image in that diectory.
2 Questions -
In CF8 in the application.cfm I cold set a global variable
like so
<cfset DSN = "dej6_42">
I am now trying to adjust to the Application.cfc in CF10/Lucee and can not figure out how to set this same variable.
Here is my current Application.cfc
<cfcomponent output="false">
<cfset This.name = "My Application">
<cfset This.clientmanagement="True">
<cfset This.loginstorage="Session">
<cfset This.sessionmanagement="True">
<cfset This.sessiontimeout="#createtimespan(0,0,10,0)#">
<cfset This.applicationtimeout="#createtimespan(5,0,0,0)#">
<cfset DSN = "dej6_42">
</cfcomponent>
I have tried
<cfset This.DSN = "dej6_42">
Then tried to call in a separate page
<cfoutput>#Applicaton.DSN#</cfoutput>
I think from my research I will need to use both application.cfc and application.cfm to accomplish the above. *edit - I tried to add an include at the end of the application.cfc file to applciation.cfm and it did not work.
2 Question.
When I place any of the standard functions in the Application.cfc my site turns to a blank page
Here is that Application.cfc - I if I remove everything below the DSN set then it will display the site.
<cfcomponent output="false">
<cfset This.name = "My Application">
<cfset This.clientmanagement="True">
<cfset This.loginstorage="Session">
<cfset This.sessionmanagement="True">
<cfset This.sessiontimeout="#createtimespan(0,0,10,0)#">
<cfset This.applicationtimeout="#createtimespan(5,0,0,0)#">
<cfset DSN = "dej6_42">
<cffunction name="onApplicationStart">
</cffunction>
<cffunction name="onApplicationEnd">
</cffunction>
<cffunction name="onRequestStart">
</cffunction>
<cffunction name="onRequest">
</cffunction>
<cffunction name="onRequestEnd">
</cffunction>
<cffunction name="onSessionStart">
</cffunction>
<cffunction name="onSessionEnd">
</cffunction>
<cffunction name="onError">
</cffunction>
</cfcomponent>
Your example doesn't set a global variable. It sets a variable in the variables scope: it will not be accessible to any CFC-based code nor any custom tags used within the request. It'll only be available in the Application.cfm, the file requested, files it includes, and OnRequestEnd.cfm
Application.cfc is a CFC (to state the obvious), so variables-scoped variables set within it are only available within it. If you want to set an application-wide variable, you need to put it in the application scope. Application scope variables should be set in the onApplicationStart) handler which is run once when the application starts, but not on every request. By way of comparison Application.cfm (which is misnamed) is run on every request. It should be called OnRequestStart.cfm.
So to be clear, setting an application-scoped variable in onApplicationStart would be as thus:
function onApplicationStart() {
application.DSN = "dej6_42";
}
If you use an onRequest() interceptor, and within that include the originally requested file, then the request will be run in the context of the Application.cfc instance, and variables set within onRequest will be available to the rest of the mainline request code, much like the way you set your variable in Application.cfm. Semantically though, if you mean a variable to exist for the life of the application (like a DSN), then putting it in the application scope is the best bet.
It sounds to me from the inferences one can make from your question that your app architecture might be languishing in the 1990s. I think you should read up on using a framework (eg: FW/1 or ColdBox) to better organise your code in a maintainable and scalable way.
Also you should read up on Application.cfc (and method reference). And probably CFCs in general: Using ColdFusion components-Developing guide.
You also might want to think about modernising your approach to writing CFML and spare the tags for view code, and otherwise using script. It makes the code easier to follow for both you and other developers who might end up needing to maintain it if the whole app isn't cluttered up with tags.
You need to set it into the application scope
<cfcomponent output="false">
<cfset This.name = "My Application">
<cfset This.clientmanagement="True">
<cfset This.loginstorage="Session">
<cfset This.sessionmanagement="True">
<cfset This.sessiontimeout="#createtimespan(0,0,10,0)#">
<cfset This.applicationtimeout="#createtimespan(5,0,0,0)#">
<cfset application.DSN = 'dej6_42'>
</cfcomponent>