Hello World with ColdFusion and Spring

Firstly, what is Spring? Spring is a Java based 'dependency injection' framework, which is a complicated name for something that simply 'helps objects to talk to each other' in a well designed way. Spring is the framework that was the basis for the popular ColdFusion dependency injection framework, ColdSpring.

Learn more about dependency injection in ColdFusion

Visit the ColdSpring site

Visit the Spring site

So why use Spring? Typically you would not need to, but using Spring in a ColdFusion application is only applicable when you want to develop larger aspects of your application in Java rather than CFML. This may be useful, for example, if you were to develop your business logic layer in Java and use CFML for your views.

Using CFEclipse

For this demo code I am using Eclipse/CFEclipse and have created a project called springdemo.

All of the directory and file references below are relative to the root of the project.

Preparing our project structure

Let's create a few directories to hold all of the files we'll need.

First create the directories for the Java code

  • /java - Root of our Java code
  • /java/src - Java source files
  • /java/build - Compiled java class files
  • /java/dist - Compiled java class files packaged into a 'jar' file

Then a directory for the CFML code

  • /web - CFML code goes here

For this example, the directory /web is the web root of the application. For example, you can set up a local URL http://springdemo.localhost/ which points to this folder.

And lastly, a directory to hold some java libraries that we will download

  • /lib - Java libraries go here

Download everything we need

Download Spring

Download the Latest GA Release, which at the time of this writing is spring-framework-2.5.6.SEC01.zip

http://www.springsource.com/download/community

Unzip the file and place the spring directory into the /lib folder.

/lib/spring-framework-2.5.6.SEC01

Download Commons Logging

The Commons Logging library is required by Spring.

Download the binary zip file, which at the time of this writing is commons-logging-1.1.1-bin.zip

http://commons.apache.org/downloads/download_logging.cgi

Unzip the file and place the commons logging directory into the /lib folder:

/lib/commons-logging-1.1.1

Download JavaLoader

We will use the JavaLoader to load the classes we need rather than needing to configure them in the ColdFusion administrator.

Download JavaLoader, which at the time of this writing is javaloader_v0.6.zip

http://javaloader.riaforge.org/

Unzip the javaloader zip file and place the javaloader directory into the /web directory:

/web/javaloader

Create a simple Java class

First, let's create a simple Java class that will provide our 'hello world' message. Create this GreetingService.java file in the directory:

/java/src/com/greeting/

package com.greeting;

public class GreetingService {

   // Private greeting variable
   private String greeting = "";

   // Constructor, similar to init() on CFCs
   public GreetingService(String greeting) {
      this.greeting = greeting;
   }

   // Returns the greeting
   public String sayGreeting() {
      return greeting;
   }

}

Compiling our Java class

There are a number of ways we can compile this code, but I am using Eclipse's built in Java and Ant scripting. I have created the a build.xml file in the project's root directory:

/build.xml

<project name="SpringDemo" default="dist" basedir=".">

   <description>
      Simple example of Spring and ColdFusion integration
   </description>

   <!-- set global properties for this build -->
   <property name="src" location="./java/src" />
   <property name="build" location="./java/build" />
   <property name="dist" location="./java/dist" />

   <target name="init">
      <!-- Create the build directory structure used by compile -->
      <mkdir dir="${build}"/>
   </target>

   <target name="compile" depends="init" description="Compile the source">
      <!-- Compile the java code from ${src} into ${build} -->
      <javac srcdir="${src}" destdir="${build}" />
   </target>

   <target name="dist" depends="compile" description="Generate the distribution">
      <!-- Create the distribution directory -->
      <mkdir dir="${dist}/lib"/>
      <!-- Put everything in ${build} into the greeting.jar file -->
      <jar jarfile="${dist}/lib/greeting.jar" basedir="${build}"/>
   </target>

   <target name="clean" description="clean up" >
      <!-- Delete the ${build} and ${dist} directory trees -->
      <delete dir="${build}"/>
      <delete dir="${dist}"/>
   </target>

</project>

To execute this script

  1. Right click on the build.xml file
  2. Select 'Run As'
  3. Select '1 Ant Build'

This should produce output in the Eclipse console similar to:

Buildfile: C:\DATA\workspace\springdemo\build.xml
init:
compile:
dist:
BUILD SUCCESSFUL
Total time: 265 milliseconds

This will have also:

1) Compiled the java code and placed the compiled files into the /java/build directory

2) Converted the compiled code into a 'jar' file and placed it in at /java/lib/greeting.jar

Creating the Spring configuration file

Spring uses an XML file to define all of the objects it manages. Let's create a simple /web/beans.xml file that defines our GreetingService object:

<?xml version="1.0" encoding="UTF-8"?>
<beans
   xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>


   <bean id="greetingService" class="com.greeting.GreetingService">
      <constructor-arg>
         <value>Hello World!</value>
      </constructor-arg>
   </bean>

</beans>

This file defines our single GreetingService object and passes the string 'Hello World!' to the constructor.

Bringing it all together

At this point we have:

  1. the Spring (and required Commons Logging) library available,
  2. the JavaLoader available,
  3. our custom GreetingService object,
  4. our Spring definition file.

Create a /web/index.cfm file to test our code in:

First, load our three 'jar' files using the JavaLoader. The JavaLoader only needs to be created once, so just create it the first time the code is run:

<cfif structKeyExists(url,"reload") or not structKeyExists(server,"javaloader")>
   <cfscript>
      paths = arrayNew(1);
      paths[1] = expandPath("../lib/spring-framework-2.5.6.SEC01/dist/spring.jar");
      paths[2] = expandPath("../lib/commons-logging-1.1.1/commons-logging-1.1.1.jar");
      paths[3] = expandPath("../java/dist/lib/greeting.jar");
      server.javaloader = createObject("component", "javaloader.JavaLoader").init(paths);
   </cfscript>
</cfif>

We place the JavaLoader into the server scope so it never times out which minimises the effect of a small memory leak in the underlying Java class loader that occurs each time the loader is created.

Next, we can create the Spring factory. We'll store the factory in the application scope and only create it if it does not already exist:

<cfif structKeyExists(url,"reload") or not structKeyExists(application,"factory")>
   <cfscript>

   // Create the main Spring factory object
   factory = server.javaloader.create("org.springframework.context.support.FileSystemXmlApplicationContext").init();

   // Advise Spring of the classes that have been loaded by the JavaLoader
   factory.setClassLoader( server.javaloader.getURLClassLoader() );

   // Advise Spring of the location of our Spring config file
   factory.setConfigLocation( expandPath("beans.xml") );

   // Load the config file and prepare our objects
   factory.refresh();

   // Store Spring in the application scope ready for use
   application.factory = factory;

   </cfscript>
</cfif>

Lastly, we can get our GreetingService out of Spring's factory and ask it to display its greeting.

<cfscript>
   greetingService = application.factory.getBean("greetingService");
</cfscript>

<cfoutput>
   #greetingService.sayGreeting()#
</cfoutput>

Hello World

When you execute this code, you should see the message defined in the beans.xml file:

Hello World!

Feedback

I've looked around for code on how to get CF and Spring to work together and have not have much luck with find specific examples, so I'm posting what I have. If you have some experience in integrating CF with Java and Spring then I'd love to get some feedback or recommendations on what I've posted.

Thanks!

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
3 Nov 2009 02:26PM
Mark Mandel said:
Mark Mandel's Gravatar There is a stack more that can be done with Spring and Javaloader, be sure to check out the documentation and examples in the downloads.
http://www.compoundtheory.com/javaloader/docs/#_Co...
3 Nov 2009 03:44PM
Kevan Stannard's Gravatar Thanks, Mark.
3 Nov 2009 03:48PM
Mark Mandel said:
Mark Mandel's Gravatar Oh, and I forgot to mention, if you want to talk to a good crew of people about Java & CF integration, you can't go past the JavaLoader-Dev Google Group:
http://groups.google.com/group/javaloader-dev

Okay, i'll stop plugging my stuff now ;o)
3 Nov 2009 04:10PM
Kevan Stannard's Gravatar Thanks, joined!
16 Dec 2009 05:14PM
Joe said:
Joe's Gravatar Haha, good one guys!
16 Dec 2009 05:16PM
mark said:
mark's Gravatar Wow, all of that work, for "Hello World!"
16 Dec 2009 05:16PM
Neil Middleton said:
Neil Middleton's Gravatar Insane
16 Dec 2009 05:23PM
Sam Soffes said:
Sam Soffes's Gravatar Wow. That is a lot of stuff just to say "Hello World".
16 Dec 2009 11:37PM
Thomas said:
Thomas's Gravatar The same with sinatra:

require 'rubygems'
require 'sinatra'
get '/hi' do
"Hello World!"
end

hmm, does anybody find a difference?
17 Dec 2009 12:52AM
Kevan Stannard's Gravatar Thanks Thomas, Sinatra certainly looks impressive and I look forward to learning a bit more about it. For everyone reading, the purpose of this entry is really about connecting to Spring managed Java classes from within CFML, and not really about the display of Hello World. The Hello World aspect is just a light way to present the material.
12 Feb 2010 07:13PM
Marty McGee said:
Marty McGee's Gravatar Kevin, this is an OUTSTANDING post. You have explained, in this simple and concise tutorial, how to hook up ColdFusion and Spring, with the help of Mark Mandel's JavaLoader CFC library, which opens the tremendous possibilities of server-based processing using Java. Ya, Ruby can spit out a hello world with less lines of code, but that really has nothing to do with your entry. Again, a great post for a coldfusioner like myself of 10 years, who are seeking simple explanations of how to hook up ColdFusion (the ultimate "language") with the rest of the world's languages and frameworks. Keep rollin'.
Add a comment
(will not be published)
(include http://)