MG3: Application.cfc integration

Towards the end of last week, I finished adding Application.cfc integration into Model-Glue 3. I've taken a few passes at it, and finally hit upon a solution I'm happy with.

The short of it is that working with onSessionStart, onSessionEnd, and onApplicationStart within a Model-Glue 3 application is just like working with earlier Model-Glue application's onRequestStart or onRequestEnd broadcasts: just listen for it and do what you need to do!

For example, if you had a UserCountController that incremented and decremented the number of current sessions, you could subscibe its functions like so:

<controller name="UserCountController" type="com.myapp.controller.UserCountController>
<message-listener message="onApplicationStart" function="resetUserCount" />
<message-listener message="onSessionStart" function="incrementUserCount" />
<message-listener message="onSessionEnd function="decrementUserCount" />

</controller>

Caveat

When you listen for onSessionEnd, you obviously don't have a URL or FORM scope to populate into the event. Instead, the only defined event value is "sessionScope," which is (you guessed it) the session scope of the expiring session.

Enabling it

There's now an Application.cfc as part of the application template. If you'd like to use this in an upgraded application, I believe you can just replace your Application.cfm with the CFC from the new template, modifying the copy with your application's name, settings, etc.

What about "sub-applications?"

In a "sub-application" setup, you may have more than one Model-Glue application in a given application scope, using ModelGlue_APP_KEY to keep them separate. In another situation, you may have a non-Model-Glue application sharing an application scope with Model-Glue.

The implementation used accounts for both. As long as the Application.cfc from the new application template is used, it'll introspect the application scope (using the ModelGlueFrameworkLocator, inspired by ColdSpring's BeanFactoryUtils) to find all instances of Model-Glue, firing the appropriate onSessionStart/End/etc. events in all of your applications.

In other words, if you've got two Model-Glue apps sharing the same application scope and a session starts orends, both will have their onSessionStart/End mechanics fired.

MG3 Feature Sneak: Event Generation Video

Yesterday on YouTube, I posted a video of a new developer workflow coming in Model-Glue 3 called "Event Generation."

When in developer mode, hitting a nonexistent event-handler can be configured to generate a conventions-based Controller, listener function, controller, and view.

Basically, typing "index.cfm?event=order.list" gives you the following:

  1. An OrderController will be generated if it doesn't exist
  2. A listener function named "list" will be created in OrderController
  3. A message-listener subscribing OrderController.list() to "order.list" will be generated, along with a controller tag if one does not exist.
  4. A view in /order/list.cfm will be created.
  5. An event-handler tag wiring all of this together is created in the XML file of your choice, defaulting to your main ModelGlue.xml

Here's a video of it in action:

One of my favorite features coming in MG3 is purely for developer ease of use: hit an event that doesn't exist while in development mode, and it'll generate intelligently named controllers, listener functions, and views, wiring them all together with convention-based XML.

Here's a video of Event Generations (and a bit of SES features) in action:

Model-Glue 3 "Beans" Injection

One of my favorite features in Model-Glue, suggested and originally implemented by Sean Corfield, is autowiring. With autowiring, if you create a method named setSomeService() on a Controller, the framework will automatically search a ColdSpring bean factory for a bean named "someService" and set it into the controller.

It's super-cool, but it requires some explicit, repetitive code: writing nearly identical setters on your controller for the services it needs.

Model-Glue 3's code name is "Gesture," and it stands for declarative workflows and elimination of boilerplate. Clearly, something had to be done about all these setters that just serve as a marker for autowiring.

In Model-Glue 3, this "something" is a new attribute on the <controller /> tag called "beans":

<controller
   id="contactController"
   type="com.myapp.controller.ContactController"
   beans="contactService,authenticationService"
/>

Inside of each Model-Glue controller is a new scope called "beans" (really, it's just a struct in variables....). When the framework loads, it automagically sets any beans listed in the "beans" attribute of <controller /> into the "beans" scope, keyed by beanId, no setter required.

In other words, as soon as I reload the framework with the above <controller /> tag, I can do this in any listener function:

<cfset var contacts = beans.contactService.list() />

Fun stuff!

© 2008 Joe Rinehart
BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.