Over a million developers have joined DZone.

Lightweight meets Heavyweight: Spring, Groovy and the enterprise

· Java Zone

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

As I am preparing for the 2G conference next month, one of the things I am most struck with is again how seamlessly Groovy and Spring can play together. These two technologies give development teams the flexibility to seamlessly transition from lightweight to heavyweight "Enterprise" solutions.

Anyone who has spent any time around me has heard me rant about how unnecessary a full-blown J2EE stack is for most application development needs. While many companies would like to believe their applications are J2EE "necessary" the reality is that most applications do not have the throughput or transactional requirements required for a full-blown J2EE stack. Most organizations base the decision to build applications on a J2EE stack not on actual technical requirements, but on the need to hug the giant (often blue) J2EE teddy bear and hope it will protect them from the scary night.

Groovy and Spring let us quickly build J2EE applications without the overhead. More importantly, combining these two technologies gives us a smooth transition to an enterprise solution. This is a critical point:

Most architecture groups look to finding a single one size development stack rather then looking for a development stack that allows them to move from light to heavyweight implementations with little migratory pain. Enforcing a one size fits all technical stack significantly drives the final cost of delivering a solution.

The Humble Message Driven Bean

I love the EJB Message Drive Bean. I think they are a very elegant solution for building simple asynchronous invocations. However, they can be a big pain to setup in a J2EE container. Often times I want a solution and I want it fast. So lets take a look at how we can write a Spring/Groovy solution that provides the same capability as a J2EE MDB. To do this we need to take the following actions:
  1. Write a Groovy-based class that is going to act as our MDB.
  2. Configure Spring to setup a queue (In this case I am using ActiveMQ)
  3. Configure Spring to link the queue and our MDB class.
  4. Write a piece of client code to dump a message onto the queue .

Writing the MDB Class

For our MDB class, I am going to use one of the examples from my talks. This MDB will take data passed onto the queue and then use a DAO to update a record. The example I am showing belows takes the primary key of the record to be updated (e.g. employee id) and then updates the employee's address with a lat/long value.

package com.netchange.racerhino.map

import javax.jms.Message
import javax.jms.MessageListener

class UpdateFieldRepMDB implements MessageListener{

def fieldRepService
public void onMessage(Message pMessage){
def holderLocation = new Location(
latitude: new Double(pMessage.getString("latitude")).doubleValue(),
longitude:new Double(pMessage.getString("longitude")). doubleValue())

def fieldRep = new FieldRepresentative(employeeId:pMessage.getString("employeeId"),
fieldRepService.updateFieldRepsLatLong( fieldRep)

The key thing to note in the above code example is that I have to make sure my Groovy class implements the MessageListener interface. Once I have my MDB written above I need to register it in a Spring configuration file. The entry for this bean will look something like:

  <lang:groovy id="UpdateFieldRepMDB" 
<lang:property name="fieldRepService" ref="FieldRepService"/>


Now this one of the beauties of Spring. I have just registered my Groovy class as a bean within Spring. Spring treats my Groovy class like any other Spring bean. My Groovy class can now fully participate in all of the services offered by Spring. This includes using the class as a listener for a Message Queue.

Configuring Spring to Use a Queue

For my example here, I am going to use the Apache ActiveMQ project. This project provides a fully functional, JMS compliant message queue that is incredibly easy to setup. To use ActiveMQ, I literally have to download the distribution and fire up the activemq script in the bin directory and away I go. (Obviously there is far more I want to do here to operationalize my queue, but that is outside the scope of what I am doing here.)

So lets configure Spring to use ActiveMQ and setup a queue. To do this I am going to need to add two tags to my Spring configuration file.

<bean id="mqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://JCC.local:61616"/>

<bean id="fieldRepDest" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="fieldrepresentative.updatelatlong.queue"/>

The first tag defines the connection factory and URL Spring is going to use when sending a message. The second tag defines an actual queue that will be available when Spring attempts to communicate with ActiveMQ. In our example above, we have one MQ called "fieldrepresentative.updatelatlong.queue" This queue will be automatically created if it does not already exist. The next thing we are going to want to do is "hook" our MDB up to our queue.

Making the Hookup

Hooking up our MDQ to our queue requires an additional tag in our Spring configuration file.
<bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="mqConnectionFactory"/>
<property name="destination" ref="fieldRepDest"/>
<property name="messageListener" ref="UpdateFieldRepMDB"/>

Spring uses the concept of a ListenerContainer to bring together an MQ connection, a target queue and the Spring-enabled class that will process messages off of the queue. In the example above the "connectionFactory" property defines a reference to the connection we will use to communicate to our ActiveMQ instance. The "destination" property points to what queue is going to be listened to and the "messageListener" defines the Spring bean (in this case our Groovy class) that will be process the record.

Spring offers a number of different ListenerContainers that can be configured. The example shown above is the most basic type and is not transactional. However, Spring does offer a full-blown JTA-compliant ListenerContainer that can participate in transactions.

Finally the Client Code

To actually write to the queue is incredibly easy. The code snippet below is using straight JMS calls from within a Groovy-based unit test. I could use a Spring JMS template, but I chose to explicitly use the JMS calls to dump a message on a queue.

def connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616")
def connection =connectionFactory.createConnection()

def session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE)
def dest = new ActiveMQQueue("fieldrepresentative.updatelatlong.queue")
def producer = session.createProducer(dest)

def MapMessage message = session.createMapMessage()
message.setString("employeeId", "TS12345")
message.setString("latitude", "12345")
message.setString("longitude", "97874")



One of the key take aways above is that we were able to build a solution that offered J2EE like capability and a smooth enterprise migration path. All of the code is written in Groovy which means if necessary it could be compiled down to Java bytecode and mixed and matched with Java classes. In addition, we can always rip the Spring-based MDB out and put in a J2EE based MDB solution. Our applications will never know the difference.

Spring acts as an intermediation layer that abstracts away the implementation details of how things are called. Groovy provides us with the language velocity needed to deliver solutions quickly without having to deal with the normal "gunk" associated with building a statically-based Java/J2EE solutions.

Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.


Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}