Skip to content

Mach II 1.6 Bootstrapper Enhancement

thofrey edited this page Apr 1, 2014 · 6 revisions

Table of Contents

  1. The Problem
  2. Exploring the Solutions
  3. The Solution
  4. Additional Information and Considerations
  5. In Closing

By Peter J. Farrell (peter@…)

The Problem

Integrating third-party (such as MachBlog) that use sessions require you to copy and paste onSessionStart / onSessionEnd specific code into your Application.cfc/cfm. While this may be simple to do, it becomes a tedious and error prone process when you want to upgrade your module to a new version.

This would also apply if another team of developers maintain the code to the module you integrate with your application. Module integrating should be as easy as drag-n-drop by adding the module configuration file to your base Mach-II XML configuration file. Currently, this is not possible when integrating modules.

Another problem is that Mach-II applications require users to manually call methods in the mach-ii.cfc boostrappers when using Applications. These could easily be streamlined for standard Mach-II applications, allowing developers to override default options by overriding the method in their Application.cfc.

Exploring the Solutions

In the mind of this developer, there are three solutions to this problem that all vary in their degree easiness integration. Since we are aiming for easy integration, I hope you agree in my conclusions.

  1. The current approach - documenting what code to copy and paste into the bootstrapper. This brings to a problem that documentation usually does not exist or is out dated. Also, a developer must watch for any changes to onSessionStart/End and copy them into their Application.cfc when newer versions of code are released. This approach is clumsy and error prone.

  2. A module could encapsulate onSessionStart/End code in a Mach-II property CFC. This keeps the required code within the module, however a developer still must place a line of code in their Application.cfc that calls this property and executes the desired onSessionStart/End code. This is a better approach than solution from ticket #1 (trac-wiki) "defect: Redirect Does Not Work on BlueDragon (closed: fixed)"), but it still requires the developer to copy a code.

  3. Add a construct in Mach-II for onSessionStart/End that registers itself with Mach-II. The Mach-II Application.cfc bootstrapper would automatically call any registered onSessionStart or onSessionEnd application events. This is the best approach as code remains encapsulated as part of the module (this even applies to base applications) and registration of the application event is automatic. No module integration is required other than registering the module config file in the base configuration file and potential override a few elements in the override XML.

The Solution

Implement the onSessionStart and onSessionEnd methods in the mach-ii.cfc bootstrapper for Application.cfc. If sessions are turned off in the Application.cfc, these methods are ignored by the ColdFusion engine anyways. In these application event methods, there is code that makes a call to AppManager to start or end a session. This calls any registered onSessionStart or onSessionEnd methods in any plugin points that define an onSessionStart and/or onSessionEnd method. This requires the addition of two new plugin points - onSessionStart and onSessionEnd. This solution is backwards compatible and does not require a developer use this integration unless they wish.

Proposed XML Syntax for onSessionStart and onSessionEnd Integration

    <cfcomponent
        displayname="SimplePlugin"
        extends="MachII.framework.Plugin"
        output="false"
        hint="A simple Plugin example.">

        <!---
        PROPERTIES
        --->

        <!---
        INITIALIZATION / CONFIGURATION
        --->
        <cffunction name="configure" access="public" returntype="void" output="false"
            hint="Configures the plugin.">
        </cffunction>

        <!---
        PUBLIC FUNCTIONS
        --->

        ... preProcess, preEvent, postEvent, preView, postView,
            postProcess and handleException plugin points ...

        <cffunction name="onSessionStart" access="public" returntype="void" output="false">
            ... code to run when a session starts ...
        </cffunction>

        <cffunction name="onSessionEnd" access="public" returntype="void" output="false">
            <cfargument name="sessionScope" type="struct" required="true"
                hint="Session scope is passed in as required by the onSessionEnd event in Application.cfc." />
                ... code to run when a session ends (must use the arguments.sessionScope
                    instead of accessing the session scope directly) ...
        </cffunction>

    </cfcomponent>

Additional Information and Considerations

  1. The onSessionStart and onSessionEnd plugin points will not have access to the event object as they are run before a Mach-II request starts or in the case of onSessionEnd after a user has left your website (e.g. no request is currently running).
  2. onSessionStart/End is run in the base application first followed by all registered modules. The order of execution in the modules is undefined.

Proposed Additions to mach-ii.cfc Boostrapper:

  1. onApplicationStart
  2. onRequestStart
  3. onSessionStart
  4. onSessionEnd

With sensible defaults, this would allow an basic Application.cfc to go from this:

    <cfcomponent
        displayname="Application"
        extends="MachII.mach-ii"
        output="false"
        hint="Performs Application.cfc functionality.">

        <!---
        PROPERTIES - APPLICTION.CFC SPECIFIC
        --->
        <cfset this.name = "m2harness" />
        <cfset this.applicationTimeout = CreateTimeSpan(30,0,0,0) />
        <cfset this.clientManagement = FALSE />
        <cfset this.sessionManagement = TRUE />
        <cfset this.sessionTimeout = CreateTimeSpan(0,0,30,0) />
        <cfset this.setClientCookies = FALSE />

        <!---
        PROPERTIES - MACH-II SPECIFIC
        --->
        <cfset MACHII_CONFIG_PATH = ExpandPath("/machiitest/config/mach-ii.xml") />
        <cfset MACHII_APP_KEY = this.name />
        <cfset MACHII_CONFIG_MODE = -1 />


        <!---
        PUBLIC FUNCTIONS
        --->
        <cffunction name="onApplicationStart" access="public" returntype="boolean" output="false">
            <cfsetting requestTimeout="#REQUEST_TIMEOUT#" />
            <cfset LoadFramework() />
            <cfreturn TRUE />
        </cffunction>

        <cffunction name="onRequestStart" access="public" returntype="void" output="true">
            <cfargument name="targetPage" type="string" required="true" />
            <cfif arguments.targetPage EQ "/index.cfm">
                <!--- Handle Mach-II request --->
                <cfset handleRequest() />
            </cfif>
        </cffunction>

    </cfcomponent>

To this:

    <cfcomponent
        displayname="Application"
        extends="MachII.mach-ii"
        output="false"
        hint="Performs Application.cfc functionality.">

        <!---
        PROPERTIES - APPLICTION.CFC SPECIFIC
        --->
        <cfset this.name = "m2harness" />
        <cfset this.applicationTimeout = CreateTimeSpan(30,0,0,0) />
        <cfset this.clientManagement = FALSE />
        <cfset this.sessionManagement = TRUE />
        <cfset this.sessionTimeout = CreateTimeSpan(0,0,30,0) />
        <cfset this.setClientCookies = FALSE />

        <!---
        PROPERTIES - MACH-II SPECIFIC
        --->
        <!--- Set the path to the application's mach-ii.xml file --->
        <cfset MACHII_CONFIG_PATH = ExpandPath("/m2harness/config/mach-ii.xml") />
        <cfset MACHII_APP_KEY = this.name />
        <cfset MACHII_CONFIG_MODE = -1 />
        <cfset MACHII_ONLOAD_REQUEST_TIMEOUT = 100 />

    </cfcomponent>

In Closing

The addition of onSessionStart / onSessionEnd integration would not change the backwards compatibility of the framework nor would it force developers to use this new feature. However, the addition of this enhancement would developers to integrate third-party modules into a base application with ease and/or to encapsulate session application events into Mach-II rather than maintaining application event code in their Application.cfc file.

Clone this wiki locally