Is it ColdFusion or Groovy?

Here at Broadchoice we've been working on our new product for close to three months now. I've gotten a crash course in Groovy, Spring, and Hibernate, all of which are slightly familiar to me from my time with ColdSpring, Transfer, and Java. I'm really digging these new technologies, but of course, I'm a die hard ColdFusion user at heart. A few weeks backs I needed to work on a quick iPhone web application prototype. Joe set up the connection and all I had to do was write CFML (lucky me). Little did I know that along with setting up basic CFML compatibility on the server, Joe also added one of the slickest things I've seen ever in my life as a developer.

The application I'm working on is pretty simple, but I wanted to use Model-Glue 3 for it since - well - you never know when a simple prototype will turn into a large, complex application. The following code snippet comes from a controller used to load bookmarks:


<cffunction name="getBookmarks" output="false">
<cfargument name="event" />
<cfset var u = arguments.event.getValue("currentuser")>

<!--- In theory currentuser should always exist, but... --->
<cfif not isSimpleValue(u)>
<!--- space only? --->
<cfif arguments.event.valueExists("space")>
<cfset arguments.event.setValue("bookmarks", beans.contentService.findContentBySpace(arguments.event.getValue("space"),["Bookmark"]))>
<cfelse>
<cfset arguments.event.setValue("bookmarks", beans.contentService.findUsersContent(u,["Bookmark"]))>
</cfif>
</cfif>

</cffunction>
Nothing in the above code should be too odd or even that exciting really. I'm using a service (injected via the beans scope in Model-Glue 3) to retrieve my content. My controller begins with...


<cfcomponent output="false" hint="I am a Model-Glue controller." extends="ModelGlue.gesture.controller.Controller"
beans="contentService,config"
>

Note the beans value specifies which beans configured in ColdSpring should be passed to my controller. I love this new automation in Model-Glue 3. If you open up my ColdSpring.xml file, you will see my beans configured:


<bean id="config" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
<property name="config">
<map>
<entry key="profileimageroot"><value>/some url you dont need to know</value></entry>
<entry key="filesroot"><value>/something else you dont need to worry about</value></entry>
<entry key="perpage"><value>10</value></entry>
</map>
</property>
</bean>

Hmmm. Ok, there's my config bean, wheres my contentService bean? Oh yeah - here it is:


<bean id="contentService" class="com.broadchoice.bcp.services.ContentService">
<property name="dao" ref="contentDAO"/>
<property name="sessionFacade" ref="sessionFacade" />
<property name="sharedFileGateway" ref="sharedFileGateway" />
<property name="eventMessageDispatcher" ref="eventMessageDispatcherService" />
</bean>

You can find the above in our Spring file. Just in case the above didn't quite make get through, let me make it real nice and obvious:


<cfset arguments.event.setValue("bookmarks", beans.contentService.findContentBySpace(arguments.event.getValue("space"),["Bookmark"]))>

The above line of CFML is using a bean injected from Spring, not ColdSpring, and points to a Groovy file. This is the same Groovy code used to drive the AIR application. No createObject("java") here baby. I'm using the Groovy code just like it had come from a CFC. This is done using a ColdSpring/Spring adapter that Joe wrote. It lets ModelGlue get Java-based beans from Spring. (I'm simplifying it here a bit, but hopefully you get the significance of that!) Once that connection is done, you can easily get beans from the Spring file and inject them into your controller. So for example, when my UserController wanted do handle login, I added: beans="userService,config" and then simply ran a userService.validateAndLoad on the authentication information.

It's always been easy to use Java from CFML, but never has been so sexy! Now to be fair, I did have to use a JavaCast once or twice, but not nearly as much as I would have thought.

Better Living Through Transfer and ColdSpring

We have a live system with customer data and a new requirement comes along that a particular piece of customer data must be encrypted in the database from now on. We already encrypt some columns (using Triple DES - which you might have guessed given the recent posts on my blog and here about mimicking ColdFusion's encryption in Java/Groovy). What is the smallest possible code change to ensure that as any user updates their data in future, this item will automatically be encrypted - whilst still handling the case of legacy data being unencrypted?

We use Transfer for all our persistent business objects and almost all of our business objects have a decorator defined (for validation or some additional business logic). We also use Brian's TDOBeanInjectorObserver to automatically inject services into our business objects - just add a setter for a service and the bean injector takes care of the rest.

Here's the bean injector definition in our ColdSpring file:


<bean id="transferObjectInjector" class="coldspring.transfer.TDOBeanInjectorObserver">
    <constructor-arg name="transfer"><ref bean="transfer" /></constructor-arg>
    <constructor-arg name="suffixList"><value>service,datasource</value></constructor-arg>
    <constructor-arg name="debugMode"><value>true</value></constructor-arg>
</bean>
Normally you would declare it non-lazy but we already do other non-lazy initialization so in our ColdSpring factory initialization code, we do this:

<cfset bf.getBean("transferObjectInjector") />
to force the bean injector to be initialized which, in turn, registers itself as a Transfer event listener (so that it can intercept object creation). The suffixList specifies that any set*Service() method or set*Datasource() method on the business objects managed by Transfer should be matched to beans defined in ColdSpring and injected.

So how do we add the on-demand encryption to our business object's data?

[More]

BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002. Contact Blog Owner