The State Of The Glue

The State Of The Glue

This post is part of our periodic status updates on progress and upcoming work on the Model-Glue project. The last week has been very productive and we appreciate all the offers of help and support. We will be circling back to each and every one of you with opportunities where you can contribute to the framework you know and love.

Timeline

The current timeline is to have the public beta out by CF.Objective(). This means in the short span of 5 weeks we'll have a documented, backwards compatible framework ready for production (we think). We'll allow a bake-in period (We have an internal target of 1 month) with the drop-dead final release date of CFUnited.

Work Done Since Last Update

A number of folks have stepped up to the plate and helped out. We'd like to give a moment of thanks.

The fine folks at Alagad (Doug Hughes, Chris Peterson , Jeff Chastain in particular) are hard at work building us new infrastructure and helping to consolidate the myriad of Model-Glue web properties. Look for a new Trac instance soon.

Thanks go to Ezra Parker for being a trac expert and for also being clever enough to write scripts to convert our old MG:2 RoboHelp documentation into wiki based documentation.

Thanks also go to Bob Silverberg, Mark Mandel and Mark Drew for helping out with the scaffolding feature design and analysis.

Thanks also to Jim Priest for helping out with ANT and the Model Glue Application Template.

Thanks also to Ray Camden, Paul Marcotte for helping out with example applications.

Work Left To Do

MG:3 Documentation

I confess to not having used all the MG:3 features. SES Urls? I have no idea how that works and have never used any SES URLS on any site ever. Ideally, we'd get volunteers who HAVE worked with these features in a production scenario to write the initial documentation and provide a code sample. I'll post a list in a few days of the areas up for volunteering. When I do, if you like/use a particular feature, email me off list and I'll reserve it for you.

Scaffolding

I've been working with a few folks on the initial scheme for Scaffolding and it is coming along. I'm going to have some time away from work in the next few weeks to work on this so expect something working by the 3rd or 4th week of April. Meanwhile, if you have an application that uses scaffolding and you wouldn't mind helping me test this feature, please leave a comment on this post and you'll get an early preview.

Example Applications

This one is moving right along. The King of the Sample application, Ray Camden has volunteered to put some example applications together. His ideas are good ones and will be an asset to the project. Paul Marcotte is helping to design another example application that will showcase features of MG:3 specifically. This last application will tie in somehow with the MG:3 documentation and those who chip in a feature will get their name in lights!

My Availability

I'm happy to say that my Brother, Dave Wilson, is taking me on a Kayak/Camping trip deep in the Florida Everglades for my Batchelor party. I'm very very excited to go on this trip because I love my brother and want to get in some relaxing time before the wedding. Also, I'm taking a little time off from my client work to get personally organized and to knock out the remaining MG:3 tasks. As such, I might not return your emails for a few days. It doesn't mean I hate you, but I've yet to see a Palm Tree with WiFi, KnowWhatIMeanVern?

ModelGlue wants to hear from You!

Those of us who work in the labs of Model-Glue know a good idea when we see one. After taking the Transfer survey, we put together one of our own. We want to hear from you, Model-Glue user or not, on frameworks and what you find important.

Our Survey

The survey is really short, only a few questions, and we've thrown in a text area or two so you have room to give us a piece of your mind. The smart person you are, you can finish this survey in 10 minutes tops.

How we use the results

We'll use the information gained by this survey to drive development of the framework. As always, Model-Glue is by the people, for the people and of the people. Your input will be kept anonymous of course.

Wanna take it?

Take the Model-Glue Survey

New Model Glue 3 Feature: copyToScope()

We've just finished adding another feature to Model-Glue 3 called copyToScope(). This feature makes it easier to pull variables out of the event scope and place them into another scope. A big thanks to Paul Marcotte for suggesting this feature.

How does it work?

Say you want to pull 3 values from the event and use them in your view. Normally, you would run 3 separate commands:

<cfset foot = event.getValue("foot") />
<cfset hand = event.getValue("hand") />
<cfset xe.nested = event.getValue("xe.nested") />
the end result being that each value: foot,hand,xe.nested is now in the variables scope ready for use in your view.

Here in the labs of Model-Glue, we want to reduce developer excise when possible. The new copyToScope() method can be used to short cut the same process.

<cfset event.copyToScope(variables, "foot,hand,xe.nested") />

The end result is the exact same as above, except only 1 line of code is needed to pull several values from the event at once.

What about default values?

As event.getValue() takes an optional argument to set default values, our new friend event.copyToScope() will take an optional array of default values. The position of the list elements pertain to the position of the value in the array. This means the 1st value in the list gets the 1st position in the array, the 2nd gets the 2nd and so on. Let's look at an example where I want to provide defaults to 2 items in the list:

<cfset defaultArray = ["DefaultForFoot", "DefaultForHand"] />
<cfset event.copyToScope(variables, "foot,hand,xe.nested", defaultArray) />

Once the function executes, the value of variables.foot is DefaultForFoot and the value for variables.hand is DefaultForHand. If no value existed in the event for xe.nested, it will be set to an empty string as per normal when a value is requested from the event that has not been set yet.

Does it only work with the variables scope?

Nope. It will work with any scope you see fit. Session, Server, Application, even a plain ole struct, though I expect the variables scope will be most often used.

Where can I get the code?

You can update from SVN at http://svn.firemoss.com/modelglue and try the feature out. Several bugs have also been fixed including a bug with Railo compatibility submitted by Denny Valliant. Thanks to Denny for his contribution.

New MG3 Feature: Dynamic viewMappings

Some of the new features in MG3, such as its revised core, focus on work being done in the more "enterprise" arena. A specific case that I'm working hard to support is the case where many customers are running "their own instance" of a common code base and how to support per-customer modification.

Realizing the use case, let's imagine that you host a blog platform. Customers can sign up and immediately have their own blog deployed. Each blog is running the exact same code base, all hosted on the same server/cluster.

Inevitably, a customer will offer to pony up cash to have a view things change. On the service / controller side, MG3 has you covered by allowing ColdSpring-based definition of services and controllers, allowing you to use ColdSpring "overriding" to one-off services and controllers.

For views, however, things were tricky. To support this case, the concept of "dynamic viewMappings" is implemented.

Model-Glue crawls an array of "view mappings" looking for your application's views: it's defined in your app's Coldspring.xml file.

With dynamic viewMappings added, you can manipulate this list at runtime.

Let's solve our blog engine case, pretending that customer "acmeCorp" needs a suite of custom views, overriding the default views only when a custom is defined. All we have to do is update the viewMappings inside a listener function whenever the user is from acmeCorp:

<cfset var customViewMappings = user.getCompany().getCustomViewMapping() />

<cfif len(customViewMappings)>
    <cfset event.setValue("viewMappingAdvice", viewMappings) />    
</cfif>

Et voila.

See http://docs.model-glue.com/wiki/HowTos/HowToUseDynamicViewMappings for more information

Update on ModelGlue:3 Gesture

Version 3 of the Model-Glue framework is under development right now. Here is an update on where we stand...

Issue Tracker

Reporting bugs/enhancement requests for Model-Glue just got easier. We now have a fully licensed JIRA issue tracker. This will help us stay on top of bugs, features and such. A special thanks to the fine folks at Atlassian for making licenses available to the Model-Glue project at no charge.

Load Testing

I've been load testing a MG:3 application pretty heavily for the last couple of weeks. The framework holds up extremely well to load and shows no memory leakage or other misbehavior.

Fixed Bugs

The bug count has been reduced by 50%. Keep logging and reporting issues!

Want to try Model-Glue:3?

The framework still has an Alpha label for now and while we have a pretty active group of folks using the MG:3 alpha, others are still welcome. Download the latest framework code from http://svn.firemoss.com/modelglue/trunk/ModelGlue and tell us what you think.

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!

© 2017 Joe Rinehart
BlogCFC was created by Raymond Camden. This blog is running version 5.9.3.006.