Categories
Contact Doug!
Learn About Doug!
View Doug Boude's online resume
updated 11/18/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Web Hosting

<< April, 2012 >>
SMTWTFS
1234567
891011121314
15161718192021
22232425262728
2930
Search Blog

Recent Comments
Re: Disappearing IE Popup Window During Save/Open Dialog (by LZ at 4/20 7:58 AM)
Re: Create Dynamic WHERE Clauses in PHP (by pooja at 3/20 7:29 AM)
Re: Just What IS a 'Service Layer', Anyway? (by EugenK at 3/07 7:56 PM)
Re: Using Google as your CF Mail Server (by 5starwebteam.com at 2/25 1:27 AM)
Re: Why Provide for Service layer objects in CFWheels? (by Steven Benjamin at 1/25 11:43 AM)
Re: What is an 'Advanced' Coldfusion Developer? (by ColdFusion Developer at 12/24 5:14 AM)
Re: Equivalent of SQL "TOP X" in Oracle (by Ashenafi Desalegn at 12/06 5:29 AM)
Re: PHP Export to Excel Snippet (by serene at 12/05 1:44 AM)
Re: Just What Is 'Application Logic', Anyway? (by Arif at 11/13 8:06 AM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Aaron at 10/22 2:31 PM)
Re: PHP Export to Excel Snippet (by Jafar Shah at 10/10 4:28 AM)
Re: Viewing Option Text (in IE7) that's Wider than the Select List (by Chenelle S at 10/04 12:53 PM)
Re: PHP Export to Excel Snippet (by Kilo at 9/26 5:20 PM)
Re: Porting Coldfusion Code to Mura (by tariq at 9/03 9:51 AM)
Re: Just What IS a 'Service Layer', Anyway? (by James at 8/27 4:06 PM)
Re: Calculating Business Hours (by helen at 8/14 2:54 AM)
Re: What IS 'Business Logic', Anyway? (by dougboude at 8/06 11:30 AM)
Re: What IS 'Business Logic', Anyway? (by Adrianne at 8/06 10:29 AM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by dougboude at 8/04 4:39 PM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by Lola LB at 8/04 7:43 AM)
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

13 April 2012
Providing For Service Layer Objects in CFWheels
Post 2 of 3

In my previous post in this series, I made the case for why I believe that service layer objects are a common need in an application's architecture. I also pointed out the fact that CFWheels does not provide for such animals within its framework, and that I had overcome this obstacle using two different approaches. What follows are the details of my first approach and a simple yet complete working sample app for your dissection pleasure.

MANUALLY IMPLEMENTING SERVICE LAYER OBJECTS IN CFWHEELS

So, what we need to be able to do, ideally, is have and use CFCs in our controllers that are NOT directly associated with a database table. The CFWheels approach requires all models to extend the Model CFC. If we omit that extension, and then attempt to retrieve our service layer object using the "model()" method call, we receive an error. If we DO extend the Model CFC on a service layer object and attempt to retrieve it using the "model()" method call, we receive an error. What to do, what to do!

In a nutshell, we have to instantiate and retrieve our service layer objects ourselves. This could simply be done using a line in a controller that performs a "createObject" call, and that would give us our object. Ah, but one of the key elements that a CFWheels developer needs is still missing, because although I can indeed create an instance of a service layer object this way, my service layer object will be completely ignorant of the CFWheels environment. It won't be able to do one of the things it needs to, and that is to ITSELF utilize the CFWheels "model()" and "get()" calls! The remedy for this turned out to be simple, but took a LOT of digging to discover: include the appropriate files from the CFWheels framework in my service layer objects.

Personally, I opted not to show a demo of implementing SLOs (I'm gonna use this acronym from here out) the way described above, because it just wasn't beautiful nor did it provide for an easy way of re-use in multitple controllers. What I decided I wanted, then, was a method all my own that I could use within controllers in order to retrieve my SLOs. Since I retrieve models using 'model("somemodel")', I thought it appropriate to retrieve my SLOs using 'service("mySLO")'. Additionally, I didn't want my SLOs living in the same folder as my models, so I create a folder just for them called "services". This folder contains a core SLO base object, exactly the same way that the "models" folder contains a core Model object. All of my SLOs extend this core component, and thusly inherit the required CFWheels functionality they need to do their jobs.

Steps I took/Modifications I Made

1. Created a "services" folder off the root;
2. Created a core "Service.cfc" that all SLOs must extend;
3. Modified my core "Controller.cfc to include two new methods;

That's it! Let's peek at these items in more detail.

In step 2, it was convenient (and followed the same approach as the rest of CFWheels) to create a core component to be extended. The entire contents of this component is as follows:

<!---
 This CFC provides access to the wheels core functions needed by our service layer objects.
--->
<cfcomponent output="false">
 <cfinclude template="../wheels/global/functions.cfm">
</cfcomponent>

In step 3, I added two methods to my core Controller.cfc. One of these methods, you may have supposed, is called "service". The other provides a single place where the developer can declare and create all of their SLOs at once. That method is called "initServices", and it looks like this:

<cffunction name="initServices" returntype="void" hint="I initialize the services objects for this app">
 <!--- create readable alias keys that the dev will use to get these objects --->
 <cfset application.$_ServiceObjects = {
  importService = createObject("services.importUsers").init(
     dsn = get("DataSourceName")
     ),
  sessionStorage = createObject("component","services.wormhole").init()
 } />
</cffunction>

The "service" method looks like this:

<cffunction name="service" returntype="any" hint="I am the method used to access any service layer object from within any controller">
 <cfargument name="service" type="string" required="true" />
 
 <cfset var retval = "" />
 
 <cfif structkeyExists(application.$_ServiceObjects,arguments.service)>
  <cfset retval = application.$_ServiceObjects[arguments.service] />
 </cfif>
 
 <cfreturn retval />
</cffunction>

One more tiny little thing, within the Controller.cfc's Init method, I added a call to InitServices to kick it off:

<cfset initServices() />

 

 

 

 

That is IT. In this example, what I am able to do now that I could NOT do before in a CFWheels controller (without bloating my controller, anyway) is this:

<cffunction name="importUsers">
 <cfset var objImporter = service("importService") />
 <cfset result = objImporter.importData(params.dataIn) />
 <cfset flashInsert(msg=result) />
 <cfset redirectTo(action="index") />
</cffunction>

THAT, my friends, is how thin a controller method SHOULD be, WHENEVER possible!

Okay, I won't blab on about this approach. I think it's slick, it's fairly easy to maintain, and I think once you take the time to poke through and run the sample user data importer app linked in this post, that you'll agree that you really have been missing Service Layer Objects too, you just didn't call it by that name.

Doug out  :0)

Next up in the series: Implementing Service Layer Objects in CFWheels using the awesome DI framework WIREBOX and the plugin I wrote for it! :)

--------------------------------
Sample App Zip File (be sure to read the READMEDUDE.txt in the zip; you'll have to create one table and edit the datasource setting to get the app to work for you.)

Posted by dougboude at 7:39 PM | PRINT THIS POST! | Link | 4 comments