The amazing adventures of Doug Hughes

This document was prepared by Joe Rinehart for Alagad, Inc.

Introduction

Building a CFML project with a Groovy model is a productive choice. In my experience, Groovy just “feels” better for modeling a domain, and its complimentary tooling (Hibernate, Spring) “just works.” It’s a complicated beast, however, and having a guide to setting it up is handy. I’ve spent a good deal of time, both on my own and at Broadchoice, learning both the concepts of JEE Web Applications and the ins and outs of setting up these hybrid projects. This document is intended to walk you through the concepts and tools used in such a setup. Actually setting up the environment is individual to your situation, and something we’ll work on together. A lot of this is still rough around the edges. Eventually, I’d like to document a “template” of two different models of Groovy+Spring+Hibernate+CFML applications. Any attempt to do so now, however, would be obsolete the moment the environment was complete: each time through is a learning experience!

Core Concepts

As you move from pure CFML to a Groovy/CFML environment, there’s some new ground to cover. At first glance, the just the terminology around JEE applications is intimidating. Terms like “descriptors,” “application contexts,” and “transaction demarcation” are foreign to ColdFusion developers. With a little bit of general knowledge and a smattering of core foundation code, it’s not hard to move past this into a productive state, even if the entire team doesn’t quite understand what’s going on under the hood. That’s the beauty of object oriented programming: not every coder needs to know how everything works! Let’s start off by walking through the general knowledge we’ll need to develop a hybrid application.

Concept 1: JEE applications vs. CFML applications

The largest shift in mentality is the shift away from the idea of a “ColdFusion” application. In the Java world, when you want to start a new Web project, you create a new JEE application. In the ColdFusion world, we use one JEE application (the CFML engine itself), writing multiple ColdFusion applications, each denoted with its own Application.cfc or Application.cfm file.

Why does this matter for a Groovy / CFML project?

It actually has nothing to do with Groovy, but with our underlying support frameworks. The easiest way to manage Spring and Hibernate in a Web environment is to use JEE application mechanics to load Spring and deal with a few quirks of Hibernate. It’s not an issue with the frameworks, it’s simply how they were designed: to take advantage of the most common way of writing Web applications in the pure Java world.

What can we do about it?

  1. Be Enterprisey

    If you’re working on a large application, it’s likely to be the only one running on its CFML server. In fact, it may be the only one running across a cluster of CFML servers. If you’ve got this luxury, using the built in utilities to manage Spring in a manner that automagically binds one “application context” (we’ll define that in a bit!) to a JEE Web application is the way to go.

  2. Manage things yourself

    If you need to run more than one application, life is more complicated. Through Application.cfc, it’d be possible to use onApplicationStart to create and configure the filesystem-based implementation of the Spring XMLApplicationContext, placing the Spring factory in the Application scope. This’d be just like creating your own ColdSpring factory.

    The second piece of the puzzle deals with Hibernate sessions. We’ll cover the “why” in a bit, but we need to hold what’s known as the “Hibernate session” open until the request ends. In a Spring Web application (Option 1), there’s a really simple servlet filter that can be used. In this setup, however, you don’t have that option. Instead, it should be possible to move the closure of the session into Application.cfc’s onRequestEnd method with the same result.

    I haven’t done this in practice, but it’s conceptually possible. Andrew Powell (UniversalMind) has demonstrated such a setup, so it’s definitely workable. One thing I’d like to research is a setup (using Model-Glue) that uses two Hibernate sessions: one in the listener method phase that is a normal read/write session, and one in the view phase that is read-only, using an optimized isolation level for increased performance (not to mention it’d stop anyone doing dao.save( instance ) from within a view!).

Concept 2: Stateful Persistence

In the ColdFusion world, we’re used to a really simple way of working with databases. In the Java mindset, there “is no database.” That pretty much blows what we know out of the water. Under the idea of stateful persistence, you’re not working with records in a database. Instead, you work with objects, changing their state (values of their properties). When you’re ready, you ask “something” to save this state, whether it’s a hand-rolled Data Access Object or a full-bore ORM. In our case, we’ll be working with an ORM (Hibernate), so we’ll be focusing on its concepts. The first concept of working with Hibernate to understand the the idea of the session. In Hibernate terms, a session (not ColdFusion session, but Hibernate session!) is a “unit of work” against the database. It’s not necessarily a single CRUD operation: it could be the saving of a batch of instances, the deletion of one, or a combination of the above. Either way, all work is done within a session. When you’re ready to roll, the session is committed as a transaction. Yep, it’s complicated. Hibernate tutorials teach you to get the current session, do work, then commit and close, all manually. It’s good to know how this all works, but nobody wants to deal with it constantly. Luckily, a real-world framework (Spring) wraps all this rigamarole into utility classes and convenience Abstract classes that let you concentrate on writing simple DAOs to use Hibernate w/o having to worry about the mechanics of using it. In other words, Spring lets you write your DAO’s save() or HQL-based list() containing just your logic, not Hibernate-management code.

Concept 3: Development Environment

Your development environment is going to change. You’re likely to end up with 3-4 Eclipse projects:

  1. A Java project. The Groovy plugin has issues compiling projects that have Java code that relies on Groovy code that relies on Java code (or any combination thereof). Basically, one has to compile before the other, which can make life….interesting. I typically run a separate Java project that contains some foundation code as well as any Java interfaces to which I’ll need to apply Spring AOP.
  2. A Groovy project. This is where most of my code lives. My model, services, and implementations of any interfaces declared in the Java project live here. It’s a lot more fun to write in Groovy than in Java.
  3. A CFEclipse project. A standard Model-Glue project living on my CFML server, with the exception that I don’t have a /model directory. Instead, I use a .jar export of the Java and Groovy projects into ColdFusion’s WEB-INF/lib.
  4. (Optional) A ColdFusion Web Application project. I’ve only done this with Railo, but it’s possible to create a JEE Web project within Eclipse that is your CFML server itself, mimicking a standard JEE application. This lets you start / stop and publish to the server from within Eclipse. It’d likely replace project #3 entirely, as your CFML source code would just be part of the JEE application itself.

This setup does have the issue of requiring you to publish a .jar to your CFML server and having you restart the server any time you make a change. I thought I’d hate it at first, but it really makes you separate your work nicely: if you’ve written good unit tests for your Java / Groovy projects, you shouldn’t be deploying to your CFML server until things are ready to roll in the first place! On the other hand, I’m often guilty of just “sne
aking in” one little change, compiling, restarting ColdFusion, then finding out my little change breaks the whole works – and if I had unit tested in the first place, I wouldn’t have just wasted the 32 seconds it takes to start JBoss on my MacBook Pro. Just a “test first!” side note.

Concept 4: The Spring BeanFactory

We’re going to use Spring to manage Groovy-based services. It’ll work like ColdSpring, allowing autowiring of these services to your controller. There’s nothing much to say here: it “just works.” Spring’s a big beast though, and it’s worth reading a book. There’s simply too much goodness in there to describe in this document: everything from really easy JMS implementation to customizable security applied via simplified AOP. Buy “Spring in Action,” second edition. Read the core concepts and persistence (Hibernate) chapters. Skim whatever else is applicable. That is all.

Concept 5: Overall System Architecture

“But what does it all look like put together?” I’m sure someone’s been asking this for a while, but we had to settle a few other issues. Let’s start from the ground up.

  1. A Spring ApplicationContext acts as a bean factory. It contains Groovy-defined services and other utility beans, such as Groovy-based DAOs. These Groovy-based DAOs implement Java-based interfaces, allowing you to use the Spring-based Hibernate conveniences that tell Hibernate when to start / commit a transaction. That’s because the conveniences rely on Spring AOP, which needs a true Java (not Groovy) interface. It sounds painful, but one single Java interface is all that’s really needed (defining a base DAO contact for all others to inherit).
  2. A ColdSpring bean factory “wraps” the Spring application context, using it as a parent bean factory. I’ve got the code for this, and setting it up isn’t hard: you just twiddle your Model-Glue’s application’s index.cfm a bit.
  3. You write tests for your domain objects (beans) in Groovy.
  4. You write your domain objects in Groovy and test them, using Hibernate or JPA annotations to guide Hibernate in their persistence.
  5. You write tests for your persistence layer in Groovy.
  6. You write your persistence layer’s interfaces in Java then implement them in Groovy.
  7. You write tests for your service layer in Groovy.
  8. You write your service layer, coordinating your domain objects and persistence layer, in Groovy.
  9. When all tests pass, you export the Groovy and Java projects to WEB-INF/lib and restart your CFML engine.
  10. You then write Model-Glue controllers that use the service layer, and business as usual begins.

Tools

Okay, we’ve covered the new foundation knowledge we’ll need. It’s time to meet the a few new characters in our hybrid project show that we haven’t yet talked about.

Groovy

Groovy is a dynamic language for the JVM. If you like Javascript or CFScript, you’re going to love Groovy. It’s like Java with all the extra crap taken out and ColdFusion’s ability to be dynamic added in (except much more strongly!).

Spring

I thought I knew what Spring was until I used it. It’s not just “everything ColdSpring does, but for Java.” It’s more like everything Java should come with in the first place. It’s a Swiss-army knife of helpful functionality, providing modules that provide bean factories, persistence helpers, testing helpers, an MVC framework, a security framework, JMS simplification, Flex integration, and a whole lot more. Buy “Spring in Action,” second edition. It is essential.

Hibernate

Industry-standard ORM framework for Java. You can use it and forget the database exists. However, it’s a complicated beast, but with good reason. “Java Persistence with Hibernate” is a book well worth the investment, as it covers both the concepts behind ORM (showing why Hibernate is as complicated as it is!) and how to use the thing in the first place.

TestNG

TestNG is my preferred unit testing framework for Groovy. It’s a lot like CFCUnit or MXUnit. Spring provides TestNG conveniences that will allow us to load our entire application context inside our unit tests. It also provides a “transactional” convenience base test class that’ll make any work we do against the database in our tests function as a transaction that gets rolled back when the test completes (or fails!), meaning that our tests won’t pollute our development databases. TestNG + Spring rocks.

Groovy Eclipse Plug-In

The Groovy Eclipse Plug-In allows you to add a Groovy project nature to any Java project. It mostly works, but can sometimes go nuts. Cleaning your project usually helps. Its code hinting is utterly useless, primarily due to Groovy’s dynamic nature. This is similar to why CFC method introspection in CFEclipse is something of a fool’s errand.

Comments on: "Building a Groovy / CFML Project: Core Concepts and Tools" (11)

  1. Really great article Doug! I myself have picked up the Grails platform lately and I am really enjoying the experience. It really does just “feel” right modeling your domains in Groovy and not to mention super easy! As I have stated before the entire J2EE stack is pretty confusing and when you can simplify down to this it makes it a heck of lot more appealing to me.

    Like

  2. Doug Hughes said:

    @Dan – Thanks. Just to be clear, this was written by Joe Rinehart for Alagad. So the credit goes to him.

    Like

  3. Joe Is indeed a brilliant guy! I can’t wait to see more on this, keep up the great work guys!

    Like

  4. Thomas Messier said:

    This is awesome. I saw Joe speak at Max and got very interested in the platform they run at Broadchoice. But it does seem complicated to wrap your head around it initially. Especially understanding how all of the different components (namely, CF and Java) interact. How do objects returned by Hibernate get sent to be used by Model Glue/CF. That kind of stuff. Looking foward to seeing what insights you can provide into all of this!

    Like

  5. Jaime Metcher said:

    Re your “2. Manage things yourself”. This is exactly what we do, although we get Spring to open the session so we can then use Spring’s transaction managers.

    You don’t actually need two sessions per request – one session with two transactions works better as you can return objects out of the listener phase and then use them in the view phase without them becoming detached (with the dreaded lazy-loading exceptions if you forget to re-attach them). It also keeps the first-level cache around as a bonus (for what it’s worth).

    Also, you *can* use the Spring interceptors for a multi-application setup. You just need ColdFusion Enterprise in multi-instance mode. On CF Standard, of course, you end up with the one Spring context for all CF applications, which may be acceptable for specific cases but in general is not.

    Like

  6. Jaime Metcher said:

    Oh, nearly forgot – cleaning up the session in onRequestEnd works well, but onRequestEnd is not invoked on a cflocation!!!!! So you need to explictly invoke your cleanup code before any cflocation. Neglecting to do so, in the worst case, may result in another request inheriting your open session along with its first level cache.

    Funnily enough, cflocation *will* close any open cftransaction, so it’s not as if CF isn’t aware that this is a situation that requires cleanup.

    Like

  7. Doug, how much more work is it to get this technology stack working within a Fusebox 5.5 application instead of MG?

    Like

  8. Matt Williams said:

    Have you considered/tried using Mark’s JavaLoader as alternative to putting the jars in the /lib folder and restarting CF?

    Like

  9. Doug Hughes said:

    @Matt – Let me be the first to say, of course!

    For what it’s worth, Joe is playing around with some extensions to Model-Glue which might make working with per-cfapplication CFML apps really easy when working with Groovy, Spring and Hibernate.

    The thing is, you make trade offs when you go down this road. I actually like the concept of writing and testing groovy and then deploying into a CF application where you use these groovy classes that you already know pretty much just work.

    Also keep in mind that the Java unit testing frameworks (especially TestNG when used with Spring) are light years ahead of what we have for CF.

    Like

  10. John Allen said:

    Ohhh My Goooosh! Thanks millions.
    Joe R rulz.

    Like

  11. John Allen said:

    Joe continues to make me like programming. Year after year after year. I am cooler cause of Joe.

    Like

Comments are closed.

Tag Cloud

%d bloggers like this: