Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Moving to CF10, Need help with Application.cfc

Community Beginner ,
Apr 23, 2014 Apr 23, 2014

I've been googling about how to work with Application.cfc since last week but I still have some questions and I can't find the answers.

My application is under the root (in unix) and there are many subfolders underneath it. Each sub-folder is hosting a different web application.

From what I read, I can create 1 root Application.cfc and then on subsequent sub-folder, when I need to have another Application.cfc on that level, I can create ProxyApplication (see below) and then create a sub-folder level Applicatin.cfc

So, when I set an application.DSN on my root Application.cfc, using proxyApplication I don't have to reset this dsn again in my sub folder level Application.cfc

Since my loginform.cfm and loginaction.cfm is right under root directory too,  I also set OnsessionStart in the root Application.cfc to handle user login. Then this means, I don't have to reset session variable again anywhere because session.username, etc has been set on the highest level.

Is this correct?

In addition, Am I correct when I do the following:

1. Since I have root level and sub-folder level Application.cfc, I should set this.name with a different name, am I right?

    On the root Application.cfc I set this.name = "StudentServices" because this represent the global application

    On the sub-folder level's Application.cfc, I set this.name to "StudentServices_stdLoad" becaus this sub-folder only handle student load application.

2. On the root Application.cfc, I set the DSN to the application scope. So on the sub-folder level Application.cfc I can check if a particular db is working or not

    because as awhole, in the global sense, this web application uses more than one Databases. Each sub-folder may use a database that is dfferent than the other sub folder.

Am I doing the right thing? Please advice

Below is example of what I have, Thank you!

I created a root Application.cfc under the root directory: 

<CFCOMPONENT displayname="Application" output="true" hint="My Root Application component">

   <!--- Set up the application --->

   <cfset THIS.Name = "StudentServices" />

   <cfset THIS.ApplicationTimeout = CreateTimeSpan(0,0,30,0) />

   <cfset THIS.SessionManagement = true />

   <cfset THIS.SetClientCookies = false />

  

   <cffunction name="OnApplicationStart" access="public" returntype="boolean" output="false">

 

   <cfset application.MainDSN = "DSN1">

   <cfset application.ReportDSN = "DSN2">

   <cfreturn true/>

</cffunction>

<cffunction name="onApplicationEnd" output="false">

    <cfargument name="applicationScope" required="true">

</cffunction>

<cffunction name="onSessionEnd">

</CFCOMPONENT>

Then, in this root directory I also created a ProxyApplication:

<!--- it's empty and it Serves merely to create an alias for your root /Application.cfc --->

<cfcomponent name="ApplicationProxy" extends="AdvancementServices.Application">

</cfcomponent>

Then in the Sub-Directory, I can create a sub-folder level Application.cfc extending the root Application.cfc:

<CFCOMPONENT displayname="Application" extends="ApplicationProxy">

    <!--- Set up the sub-folder application --->

    <cfset THIS.Name = "StudentServices_stdLoad"/>

    <cfset THIS.ApplicationTimeout = CreateTimeSpan(0,0,30,0) />

    <cfset THIS.SessionManagement = true/>

    <cfset THIS.SetClientCookies = false/>

    <cffunction name="OnApplicationStart" access="public" returntype="boolean" output="false">

       <!--- ****** Testing whether the ADVUPGRD is accessible by selecting some data.****** --->

       <cftry>

       <cfquery name="TestMain_DSN" datasource="#application.MainDSN#" maxrows="2">

         SELECT Count(*)

        

FROM MyTable

       </

cfquery>

         <!--- If we get a database error, report an error to the user, log the error information, and do not start the application. --->

        <cfcatch type="database">

          <cflog file="#this.name#" type="error" text="Main DSN is not available. message: #cfcatch.message# Detail: #cfcatch.detail# Native Error: #cfcatch.NativeErrorCode#" >

         <cfthrow message="This application encountered an error when connecting to the Main Database. Please contact support." />

         <cfreturn false>

       </cfcatch>

     </cftry>

     <cflog file="#this.name#" type="Information" text="Application #this.name# Started">

     <cfreturn true/>

   </cffunction>

</CFCOMPONENT>

   <cfargument name = "SessionScope" required=true/>

   <cfargument name = "AppScope" required=true/>

</cffunction>

<cffunction name="OnSessionStart" access="public" returntype="void" output="false">

  <CFSET session.UserGroup = ""/>

  <CFSET session.UserName = ""/>

  <CFSET session.currentPage = ""/>

  <CFSET session.loggedin = "No"/>

  <CFSET session.userrights = ""/>

  <cfreturn/>

</cffunction>

TOPICS
Getting started
1.1K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 24, 2014 Apr 24, 2014

If each "subapplication" has a different name (e.g.: <cfset THIS.Name = "StudentServices_stdLoad"/> ), then they will each have their own sessions separate from any sessions created by the root-level Application.cfc.  So any session variables you set in OnSessionStart() in the root Application.cfc will not be seen from any pages within the "subapplication".  In order to share sessions, all "subapplications" must use the same name as the root-level Application.cfc.

Just as an aside, in the future please strip down the whitespace when you post code to review to reduce the amount of scrolling required.  It will make it easier for others to examine and offer help.

-Carl V.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Apr 25, 2014 Apr 25, 2014

Hi Carl, Thak you for your valuable advice.

Regarding the whitespace I did not create that. Once I submitted my entry those whitespaces were created. I may have to create my entry in Notepad then pasted there to avoid these whitespaces, especially for the codes (?).

Your explanation about This.Name. If every sub-application will not be able to see the session set in the root Application.cfc then what is the purpose of extending root Application in the sub-folder level? I'm even more confuse than ever now.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 25, 2014 Apr 25, 2014

@alecken,

Can't speak to the how the whitespace gets generated.  I guess once you submit a message, if you see a bunch of whitespace, you can go back and edit the message to remove it.  It's not a big deal if there is whitespace, it just makes it harder to read the code.

With regard to the root Application.cfc vs. sub-application Application.cfc and THIS.name, it can be a bit confusing.  It might be easier to think about it going from the top level down to the lowest level. 

An "application" has a unique name that defines it as separate from all other applications running on the same ColdFusion instance.  If your applications use sessions (and not all applications have to), each application will have it's own collection of sessions effectively walled-off from any other application's sessions.  If you change the THIS.name in Application.cfc (from here on out I'll refer to it as App.cfc for brevity) and hit a page in your application, it starts a new application on the ColdFusion instance, and will have a new session collection.  So, in your case, if your sub-application App.cfc defines a different THIS.name from the root App.cfc, you start a completely new application on that ColdFusion instance, and a new session collection.

It looks to me like what you really want is all sub-applications to share some common settings, but still operate independently from each other.  Can you confirm whether this is your goal? If it is, I can think of a different way to make this work that will allow each sub-application to operate as an independent application.

One other thing, and this may just be a copy/paste error - in your sub-application App.cfc, the <cfargument> tags following your onSessionStart() function should be inside the function and immediately after the <cffunction> tag.

-Carl V.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Apr 28, 2014 Apr 28, 2014

Hi Carl!

First of all I want to say thank you for your reponses and yes, pretty much that's my goal:

all sub-applications to be able to share some common settings, but still operate independently from each other

It's because our users are from 10 different institutions. When they access our web app, they only need to login once.

After their successful login, they should be able to access all of the sub-application securely.

When a few users form a different institutions accessing the same or different sub-application at the same time, there should not be any confusion among their session variables. Each institution should only be able to see their own data.

So, there should be a couple of application scope variables for DSNs. I'm using 2 different DBs in this web app., One for reports and one for everything else. This 2 DB is on a separate machine.

There are a few session variables being set after authenticaton. Such as session.username, session.loggedin, session.usergroup.

I don't have confident on how I can do this, so thank you for helping!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 28, 2014 Apr 28, 2014

OK.  It sounds to me like you really shouldn't be using a single root Application.cfc at all, if all you want to do is share some settings between your "sub-applications".  I would look at storing the common settings in an external file that all of the applications can read in.  The simplest way is to put the settings in a .CFM file somwhere outside of the web root (so it is not directly web accessible) and load it with <cfinclude> tag into the OnApplicationStart() method of each sub-application's App.cfc.  That .CFM file can be as simple as:

<cfset application.myCustomSetting = "blahblah">

<cfset application.myOtherSetting = "foo">

Alternatively, you can look at using a config file like this Ray Camden blog post suggests, and use the GetProfileSection(), GetProfileString(), and SetProfileString() functions as needed within OnApplicationStart().  You could even put ALL of your settings in

A third option is to store your settings in an XML file or in JSON format in a text file.  You could then write code to read in the XML file, and use something like xml2struct.cfc to convert the XML into a struct, then append the struct to your application scope.  If you go the JSON route, then just read in the JSON file and use DeserializeJSON() to convert it into a struct, and append it to the application scope.

What I think is probably the best approach is to use a community-supported MVC framework like FW/1 or ColdBox (maybe you already are, I don't think you've said so though).  One of the many advantages to doing so is that they have built-in "environment" support that can be used to configure common settings, depending on your environment (dev/qa/production).  You would handle reading in your external settings through the "environment" mechanism.

One other thing to think about: your login mechanism.  I think you want to use one set of login tools that is shared by all of the "sub-applications".  You can do this also by putting the login/authentication-related code somewhere outside the webroot of your applications, and then either set up a mapping to that location in CF Admin, or set an application-specific mapping in your various App.cfc files.  That way all the "sub-applications" share a common set of code for the login process.  I don't know how your login process works (do all users go to the same login page then get redirected into their relevant "sub-application", or does each "sub-application" have a discrete login page that utilizes common back-end processes to authenticate and redirect), so you'll have to judge how that is best accomplished.

Hopefully this gives you some useful ideas.

-Carl V.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Apr 29, 2014 Apr 29, 2014
LATEST

Hi Carl,

Thank you, please allow me to take a few days to digest what you wrote. I thought it wouldn't be so complicated because the app is currently written in CF8 by previous programmers and when I looked at their codes, they seems to be straight forward, simple, no ColdBox or anything like that. But of course they only use application.cfm and maybe because it is too simple it breaks once in awhile (?)

I thought converting it to CF10 and using App.cfc will also be straight forward.

Thanks again!

notes: My users only login once and tyeh they can access all the sub-applications withour having to login again.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources