Archive

Archive for the ‘spring framework’ Category

The Micro Framework Approach

December 3, 2010 5 comments


Flattr this
The demand for Grails and Groovy is clearly raising these days – at least here in Austria and Germany. Although most of my workshops have their individual adaptions (depending on the previous knowledge and programming language experience of participants) there are parts which can more or less be found unmodified in every workshop: Groovy essentials/advanced topics and what I call micro framework examples. This article is about the idea behind micro framework examples and why I find them that useful as workshop examples.

What is a Micro Framework Example?

I strongly believe that true understanding on patterns behind frameworks like Hibernate and Spring can’t easily be treat in a bunch of slides. Explaining patterns is one thing but to actually see how those are applied is another one. One approach I’ve found to be really useful in workshops is the use of micro framework examples. A micro framework example implements the core functionality behind a specific framework – reduced to the very fundamentals. One advantage to implement a micro framework example together with participants is to force triggering a thinking process of what functionality is needed and how it can be implemented. Another side-effect is that it allows to slightly introduce the original frameworks ubiquitous language simply by using the same class and method names.

Let me give you an example. The most threatening topic for many of my clients is to understand Hibernate and its persistence patterns. One approach to create a better understanding would be to implement a micro Hibernate framework example. This can be done in a simple Groovy script MicroHibernate.groovy which defines two classes and a simple test case. The first class implements the registry pattern and is called SessionFactory:

class SessionFactory {

    private def storage

    def SessionFactory(def storage)  {
        this.storage = storage
    }

    def newStorageConnection()  {
        return storage
    }
}

The SessionFactory acts as the main access point to get a reference to some storage connection. In the micro framework example this will simply be a Map. Dealing with SQL or even a real database would uselessly complicate the example and we want to concentrate on the core essentials. Let’s go on to the next class which implements the persistence context pattern:


class Session {

    static Log log = LogFactory.getLog(Session)

    private def sessionFactory

    def Session(def sessionFactory) { this.sessionFactory = sessionFactory }

    def snapshots = [:] // a Map(Domain-Class, Map(Identifier, Properties))
    def identityMap = [:] // a Map(Domain-Class, Map(Identifier, ObjectRef))
    def modifiedPersistentObjects = [:] // a Map(Domain-Class, List(Identifier))
    
    def propertyChanged(def obj)  {
        if (!modifiedPersistentObjects[obj.getClass()]) modifiedPersistentObjects[obj.getClass()] = []

        modifiedPersistentObjects[obj.getClass()] << obj.id

        log.info "propertyChanged of object: ${obj} with id ${obj.id}"
    }

    def load(Class<?> domainClassType, Long identifier)  {
        
        if (identityMap[domainClassType] && identityMap[domainClassType][identifier])  {
            return identityMap[domainClassType][identifier]
        }
        
        def conn = sessionFactory.newStorageConnection()
        def loadedObj = conn[domainClassType][identifier]
        if (!loadedObj) throw new Exception("Object of type ${domainClassType} with id ${identifier} could not be found!")
        
        if (!snapshots[domainClassType]) snapshots[domainClassType] = [:]
        if (!identityMap[domainClassType]) identityMap[domainClassType] = [:]


        def properties = loadedObj.getProperty("props")
        snapshots[domainClassType][identifier] = properties.inject([:], { m, property -> m[property] = loadedObj[property]; m })

        log.info "create snapshot of ${domainClassType} id ${identifier} with properties ${snapshots[domainClassType][identifier]}"

        identityMap[domainClassType][identifier] = loadedObj
        
        loadedObj.metaClass.getId = { -> identifier } 
        loadedObj.metaClass.setProperty = { String name, Object arg ->
            def metaProperty = delegate.metaClass.getMetaProperty(name)

            if (metaProperty)  {
                owner.propertyChanged(loadedObj)
                
                metaProperty.setProperty(delegate, arg)
            }
        }
        
        return loadedObj
    }
}

A Session object can be used to retrieve already persistent objects and to persist so-called transient objects. I like to start by implementing the load method which loads a persistent object from the storage connection of the current session factory. Of course, this is not an example for Groovy beginners but with a little knowledge of MOP and with some programming guidance it should not be a big thing to understand what is going on. At the end let’s define some test case which shows how both classes are actually used:

def storage = [:]

class Person {
    String name

    String toString() { name }

    static props = ['name']
}

storage[Person] = [:]
storage[Person][1 as Long] = new Person(name: 'Max Mustermann')
storage[Person][2 as Long] = new Person(name: 'Erika Mustermann')

def sessionFactory = new SessionFactory(storage)
def session = sessionFactory.newSession()

def person = session.load(Person, 1)

Interestingly, even without considering SQL, DB connection handling, threading issues etc. participants already get a feeling of several Hibernate gotchas beginners otherwise often struggle with:

  • the first level cache
  • the need for proxies or MOP modifications
  • Hibernate’s use of object snapshots
  • the IdentityMap pattern
  • repeatable read transaction isolation level
  • etc.

It is amazing how much can be explained by implementing some framework’s core functionality in about 5 minutes. The Session functionality gets than extended by flush, discard and save/delete functionality. If programmers have been through the process of implementing such a micro Hibernate example they often get a basic and fundamental understanding of how an orm framework could work and what the main challenging problems are. By keeping the class and method names in sync with the concrete Hibernate implementations participants learn the framework’s basic domain language.

GSamples – A Repository for Sharing Workshop Examples

The example mentioned above is available in a public github repository what I called GSamples [0], a collection of Groovy and Grails workshop examples. At the time of publishing this article it contains two micro framework examples, the other one is a simple dependency injection container. In addition, GSamples holds Groovy scripts dealing with Groovy Essentials and another one dealing with advanced Groovy topics like the Meta-Object Protocol and Closures. Feel free to extend, distribute or use it!

[0] GSamples – https://github.com/andresteingress/gsamples

Happy Messaging with ActiveMQ and SI (Part 1)

October 14, 2010 1 comment


Flattr this
In one of my current projects we needed to set up a communication channel between two distinct Grails applications. One of them is the master application which runs an embedded ActiveMQ message broker [0]. The second one – the slave application – provides service APIs to the master application.

Since Grails heavily relies on Spring, we decided to use Spring Integration as messaging framework [1]. Spring Integration is a messaging framework which supports various Enterprise Application Integration Patterns [2], without being bound to any specific messaging protocol. Since our project team chose to use ActiveMQ we go with JMS as underlying messaging protocol in our project.

Setting up an embedded ActiveMQ message broker

ActiveMQ is a fully JMS 1.1 compliant messaging provider which is available under the Apache Software License. It has quite a bag of features, the most important ones for us where persistent messages support. Besides running ActiveMQ as a distinct server, one can choose to run ActiveMQ as an embedded server inside the application.

Configuring an embedded ActiveMQ broker using Grails’ Beans DSL is pretty straight-forward (once you get used to the Beans DSL of course):

xmlns amq:'http://activemq.apache.org/schema/core'

def brokerName = 'myEmbeddedBroker'

amq.'broker'(brokerName: brokerName, useJmx: true, persistent: false) {
  amq.'managementContext'  {
    amq.'managementContext'(connectorPort: 2011, jmxDomainName: 'embeddedBroker')
  }

  amq.'plugins'  {
    amq.'loggingBrokerPlugin'
  }

  amq.'transportConnectors'  {
    amq.'transportConnector'(name: 'openwire', uri: 'tcp://localhost:61616')
  }
}

The code above configures an embedded broker called myEmbeddedBroker which only persists messages in-memory (persist: false), exposes itself as JMX bean (useJmx: true) and configures a transport connector using Openwire over TCP.

In order to let the master application (which holds the configuration above) connect to its embedded message broker, we need to set up a connection factory:

connectionFactoryLocal(ActiveMQConnectionFactory)  {
  brokerURL = "vm://${brokerName}"
}

After all, we will define two message queues one for outgoing API requests to the slave application and one for incoming responses:

"requestQueue"(org.apache.activemq.command.ActiveMQQueue, "QUEUE.REQUEST")
"responseQueue"(org.apache.activemq.command.ActiveMQQueue, "QUEUE.RESPONSE")

Spring Integration comes into play

So far we have set up an embedded message broker which could be used for plain JMS API message exchange. In our project we decided to go with Spring Integration because it already implements several EAI patterns (e.g. router, gateway, etc.) and abstract from the underlying messaging protocol.

A reference manual on Spring Integration can be found at [3], but let me give you a short introduction. Spring Integration (SI) is a messaging framework which implements patterns found in the book Enterprise Application Integration Patterns [4]. That is, SI is all about messages and message exchange. To exchange a message from point A to point B there needs to be a channel between A and B. Besides messages, channels are the second most important domain entity in SI.

Channels are injected into your application components just like any other Spring bean. The basic MessageChannel interface is pretty rudimentary:

public interface MessageChannel {

	boolean send(Message<?> message);
	boolean send(Message<?> message, long timeout);
}

The use-case in our project was to automatically create a message and send it to some preconfigured channel whenever the programmers chooses to call a service API method:


def someApi

def doSomething()  {   
   someApi.executeRemotely('first param', 'second param') // this should trigger message creation and sending/receiving
}

A call to executeRemotely should automatically create a message object from the input parameters and send it to some sort of API request channel.

Luckily, SI provides the concept of gateways which solve that particular problem. At runtime, a gateway is a proxy object for a particular interface which, on a method call, creates a message object and sends it via some preconfigured channel. Like channels, gateways are Spring beans and can therefore be configured via the Beans DSL:

xmlns integration:'http://www.springframework.org/schema/integration'
xmlns jms:'http://www.springframework.org/schema/integration/jms'

integration.'channel'(id: 'apiChannelRequest')
integration.'channel'(id: 'apiChannelResponse')

integration.'gateway'(id: 'someApi', 'service-interface': org.ast.SomeApi.class.getName(), 'default-request-channel': 'apiChannelRequest', 'default-reply-channel': 'apiChannelResponse')  {

  integration.'method'(name: 'executeRemotely')  {
    integration.'header'(name: 'API_METHOD_NAME', value: 'executeRemotely')
  }
}

As you can see from the configuration snippet above, the gateway has a request/reply channel configured since gateways are synchronous (in SI 2.0 there is asynchronous gateway support) and bidirectional. The SomeApi interface uses SI annotations for further message configuration:

interface SomeApi {
    Boolean executeRemotely(final @Header("HEADER_NAME") String param1, final String param2)
}

From the gateway’s view the interface above means: whenever executeRemotely is called, put param1 into a message header with name HEADER_NAME and put the second parameter into the message’s payload. Maybe you noticed the API_METHOD_NAME parameter in the gateway configuration above – that was a message header too. We needed to manually inject a unique method identification token (in our case the method name only was enough) in order to call the correct method on the slave application side.

Configuring JMS messaging

So far we’ve set up an environment with an embedded ActiveMQ message broker and two ActiveMQ message queues. Now we need to configure the link between the SI channels configured in the last section and those JMS queues. Since gateways are bidirectional, SI needs to store some reply channel information whenever instantiating an API request. This is automatically done via the gateway implementation. If we would run inside a SI environment only we wouldn’t need to care about this fact. In our case, we chose to use gatways to communicate between a master and a slave application which are in production deployed on separate server instances.

In SI, a JMSOutboundGateway can be used for those JMS request/reply scenarios. It is the clue between SI channels and out ActiveMQ JMS queues:

jms.'outbound-gateway'(id: "jmsGateway", 'connection-factory': 'pooledJmsConnectionFactoryLocal', 'request-destination': "requestQueue", 'request-channel': "apiChannelRequest", 'reply-destination': "responseQueue",'reply-channel': 'apiChannelResponse')

In the slave application, there needs to be an inverse configuration using a JMS inbound gateway:

jms.'inbound-gateway'(id: 'jmsInbound', 'connection-factory': 'pooledJmsConnectionFactoryRemote', 'request-destination-name': 'QUEUE.REQUEST', 'request-channel': 'incomingRequest', 'reply-destination-name': 'QUEUE.RESPONSE')

The configuration snippet inside the slave application simply routes incoming messages to the incomingRequests channel. Notice that no reply channel has been specified in order to keep the reply channel which has been added by the master application in the message.

In the next part of this article series we’ll have a closer look at the slave application and how it is configured to invoke methods an Grails service beans.

[0] ActiveMQ Message Broker
[1] Spring Integration
[2] Enterprise Application Integration
[3] Spring Integration – Reference Manual
[4] Amazon: Enterprise Integration Patterns

Integration and Grails

In most applications, it is a common requirement to implement a mail sending mechanism. Indeed, there is the mail plugin [0] which achieves that use case by injecting a sendMail method in Grails artefacts:

sendMail {     
  to "fred@g2one.com"     
  subject "Hello Fred"     
  body 'How are you?' 
}

But maybe you already had the situation that you felt that this level of integration is not enough – maybe you wanted to use message pooling or you wanted to have multiple task executors processing the message queue from time to time.

Luckily there exists an extension to the Spring Framework which is ment to handle such tasks: Spring Integration [1].

A Small Introduction to Spring Integration

Spring Integration is all about enabling messaging architectures in Spring-based applications. In this context, messaging does not mean sending e-mails. In a message-oriented middleware (MOM) software components communicate by sending packets of data. Each message has a producer (that part that generated the message) and one or more consumers (doing something with the data provided by the message).

A Messaging System

Compared to pure method invocations, a messaging communication always implies asynchrony – the producer thread typically does not wait for the consumers to get responses, it sends and forgets. But as the messaging system leverages transaction support, message persistency, pooling of messages, and various other services, using a messaging architecture is especially an option in integration scenarios with external systems (e.g. an SMTP server).

Adding Spring Integration as Dependency

A dependency to Spring Integration can simply be specified in the application’s BuildConfig.groovy:

dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
        // ...
   	compile('org.springframework.integration:spring-integration-mail:1.0.4.RELEASE')  {
          excludes "spring-aop", "spring-beans", "spring-context", "spring-context-support", "spring-core", "spring-tx"
        }
    }

Be aware that Grails itself has a dependency on multiple Spring modules, that is the reason why the code sample above explicitly excludes those modules. As you can see, there is a specific Spring Integration module for mail support with artefact-id spring-integration-mail which is used in this example. There are various extensions e.g. for RMI, HTTP, JMS etc. integration scenarios.

A simple configuration

As mentioned, producers, consumers and messages play a central role in messaging systems. Another important concept is called a channel. A channel is a logical pathway between a sender and its receivers. Spring Integration supports two conceptually different channel types: event-based and polling channels.

Event-based channels are rather easy to understand. Whenever a message is sent on an event-based channel, the subscribers immediately receive that message. On the other side, polling channels poll the channel for new messages and if messages are found, those are handled by the associated consumers.

Let us assume the use case for our application is to send mails in chunks – either the application sends chunks of 50 messages or it waits for a certain timeout to occur.

First step is to create an integration.xml and to define a pollable channel in there:

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

    <channel id="someMessageChannel"/>

</beans:beans>

The integration.xml file can simply be referenced by Grails resources.xml or resources.groovy.

Per default such a declaration declares a org.springframework.integration.channel.DirectChannel bean. A direct channel is a point-to-point channel that supports execution of message operations in a single thread.

As the someMessageChannel is a Spring bean it can be injected into Grails service classes:

class MyService {

  static transactional = true

  MessageChannel someMessageChannel
  
  def void someOperation()  {
    // ...
    someMessageChannel.send(...)
  }
}

The MessageChannel can now be used to send org.springframework.integration.core.Message instances:

  someMessageChannel.send(new GenericMessage<String>("my payload"))

In this case, the message simply has an instance of java.lang.String as payload, but the GenericMessage actually is generic and supports arbitrary classes. In our use case of sending mails, the application has to construct a more complicated message, including message headers in addition to the message payload:

    def headers = [:]

    headers.put MailHeaders.FROM, from
    headers.put MailHeaders.SUBJECT, subject
    headers.put MailHeaders.TO, receiver

    // create an instance of javax.mail.internet.MimeMessage
    // ...
    someMessageChannel.send(new GenericMessage<MimeMailMessage>(new MimeMailMessage(mimeMessage), headers))

This is the time we need to add another component to our configuration file: we need to add an SMTP adapter. An adapter acts as messaging client and invokes functionality of the adapted application or component. The Spring Integration Mail module provides an adapter that delegates to Spring’s JavaMailSender. Thus in order to add get the mail adapter working, you need a mail sender in the application context:

  <channel id="someMessageChannel"/>

  <!-- mailSender bean needs to be configured somewhere in the application context... -->
  <mail:outbound-channel-adapter channel="someMessageChannel" mail-sender="mailSender"/>
</beans:beans>

Last step is to add polling capabilities to our someMessageChannel which can be done with some additional XML configuration:

  <channel id="someMessageChannel"/>

  <!-- mailSender bean needs to be configured somewhere in the application context... -->
  <mail:outbound-channel-adapter channel="someMessageChannel" mail-sender="mailSender">
    <poller max-messages-per-poll="50">
      <interval-trigger interval="30" time-unit="SECONDS"/>
    </poller>
  </mail:outbound-channel-adapter>
</beans:beans>

Please notice, in a real world example the application would probably not create a message instance which is tied to a MimeMessage. In place of adding the mail related information on message creation, one could use Transformer implementations to do that just before the mail adapter receives the message.

Conclusion

Spring Integration is a mighty Spring extension – if you are seriously developing Grails applications you should consider taking a look at it. Sending mail is only the peak of the iceberg – if you think especially of enterprise integration scenarios with other applications or external systems using a messaging system (and maybe a JMS messaging server) can enforce performance and reliability of applications.

If you want to delve into the topic of enterprise integration patterns, take a look at [Amazon-Link, 4], btw Spring Integration’s design is inspired by the patterns mentioned there.

[0] Grails Mail Plugin – http://www.grails.org/Mail+plugin
[1] Spring Integration Project Homepage
[2] Spring Integration in Central Maven Repo
[3] Enterprise Integration Patterns – Hohpe, Woolfe, et.al.


Integrating Groovy in Legacy Spring Applications

April 13, 2010 2 comments

There are times when you have (or want ;-)) to integrate Groovy in a productive application or, in more complex applications, you just want to realize your application’s controller and/or view part (think M-V-C) in a dynamic language, but leave the rest in good-old Spring. Starting with version 2.0, Spring offers support for dynamic languages and comes with support for integrating beans written in Groovy out-of-the-box.

Dynamic Language Support in the Spring Framework

Spring’s dynamic language support currently supports Groovy, JRuby and BeanShell. The integration layer itself consists of several classes dealing with dynamic class loading/creation and class reloading, all of them can be found in org.springframework.scripting which is part of the org.springframework.context Maven module.

Let us first of all take a look at how the integration of Groovy scripts works. In order to declare a controller bean, we would have to use the following XML snippet in the MVC dispatcher context file:

<?xml version="1.0" encoding="UTF-8"?>
<beans...>
  <lang:groovy id="personController" script-source="classpath:PersonController.groovy">
    <lang:property name="personRepository" ref="personRepository" />
  </lang:groovy>

  <!-- an otherwise normal bean that will be injected by the Groovy-backed Messenger -->
  <bean id="personRepository" class="org.some.domain.PersonRepositoryJDBC">
      <!-- ... -->
  </bean>
</beans>

Notice, that the lang namespace is used as a special namespace. Spring’s LangNamespaceHandler registers for groovy, jruby and bsh elements and, for each language, logically links them to custom ScriptFactory implementations:

public class LangNamespaceHandler extends NamespaceHandlerSupport {
  // ...  
  registerScriptBeanDefinitionParser("groovy", "org.springframework.scripting.groovy.GroovyScriptFactory");
  registerScriptBeanDefinitionParser("jruby", "org.springframework.scripting.jruby.JRubyScriptFactory");
  registerScriptBeanDefinitionParser("bsh", "org.springframework.scripting.bsh.BshScriptFactory");
  // ...

At run-time, this task is done by an instance of ScriptBeanDefinitionParser: for each bean definition prefixed with lang it generates a script factory bean according to the language element being specified. All XML attributes of lang:groovy are indeed used to specify a script factory and not the Groovy object itself.

Let us take a look at the ScriptFactory interface:


public interface ScriptFactory {

  String getScriptSourceLocator();

  Class[] getScriptInterfaces();

  boolean requiresConfigInterface();

  Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces);

  Class getScriptedObjectType(ScriptSource scriptSource);

  boolean requiresScriptedObjectRefresh(ScriptSource scriptSource);
}

The most interesting methods are getScriptedObject, getScriptedType and requiresScriptedObjectRefresh.

getScriptedType is mainly used by Spring’s IoC container to determine the bean type and check whether it implements certain interfaces, not much magic implied here.

requiresScriptedObjectRefresh can be used for a certain script source to determine whether it has been modified and requires a refresh. Refreshing of dynamic beans is the main feature justifying using dynamic language support. One could easily configure the application to refresh Groovy beans during development, but keeping them static in the production environment (who would ever consider to take a change directly in a source-file in the production environment ;-)), tremendously fastening development.

getScriptedObject is the heart of each script factory implementation. It is used as a factory method to create scripted Java objects.

Scripted Java Objects

Let us take a look at the Groovy script factory implementation, which is found in GroovyScriptFactory.

public Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces)  {

  synchronized (this.scriptClassMonitor) {
    // some caching stuff...
					
    this.scriptClass = getGroovyClassLoader().parseClass(scriptSource.getScriptAsString(),         scriptSource.suggestedClassName());

  if (Script.class.isAssignableFrom(this.scriptClass)) {
    // A Groovy script, probably creating an instance: let's execute it.
    Object result = executeScript(scriptSource, this.scriptClass);
    this.scriptResultClass = (result != null ? result.getClass() : null);
    return result;
  } else {
    this.scriptResultClass = this.scriptClass;
  }
  }
  scriptClassToExecute = this.scriptClass;
}

// Process re-execution outside of the synchronized block.
return executeScript(scriptSource, scriptClassToExecute);
		

and in executeScript:

protected Object executeScript(ScriptSource scriptSource, Class scriptClass) throws ScriptCompilationException {
			
  // ...
  GroovyObject goo = (GroovyObject) scriptClass.newInstance();

  if (this.groovyObjectCustomizer != null) {
    // Allow metaclass and other customization.
    this.groovyObjectCustomizer.customize(goo);
  }

  if (goo instanceof Script) {
    // A Groovy script, probably creating an instance: let's execute it.
    return ((Script) goo).run();
  } else {
    // An instance of the scripted class: let's return it as-is.
    return goo;
  }
  // ...
}

As can be seen in the source snippet, getScriptedObject uses a GroovyClassLoader to parse the given script source string and to create a Java class object instance from it [3]. Since every script factory is directly connected to a single script source, the embedded caching mechanism is as easy as holding an instance variable to the scripted object and class.

Another possibility for the GroovyScriptFactory would have been to use Groovy’s GroovyScriptEngine. In contrast to Groovy’s class loader it recognizes changes in the class inheritance paths and reloads affected class files directly. If you do not want to customize Spring’s behavior you have to be aware of that circumstance.

So far we have seen how a single XML bean definition relates to a script factory and how that script factory can be used to create dynamic objects, but where is the place that calls getScriptedObject? The answer is: that place needs to be generated by the ScriptFactoryPostProcessor, which is a descendant of Spring’s bean-post processor interface.

ScriptFactoryPostProcessor

First of all, the BeanPostProcessor interface specifies callbacks which can be used as hook-ins for custom modification of container-managed beans. ApplicationContexts will automatically detect beans of this type and apply them on subsequent bean creations. If you use your favorite IDE’s command to show all descendants of BeanPostProcessor you will notice that there are plenty of them. One with particular importance in the case of dynamic language support is the InstantiationAwareBeanPostProcessor.

InstantiationAwareBeanPostProcessor is used to intercept the application container before instantiation and after instantiating a managed-bean. This post-processor type is typically used to suppress object instantiation of the specified bean and to create some proxy or other place-holder to intercept bean method calls.

Spring’s Groovy integration provides an implementation of that post-processor: ScriptFactoryPostProcessor.

The script factory post-processor hooks into the post-process after object instantiation. As we have already seen the bean definition parser created script factory object beans. It is the script factory post-processor which intercepts creation of script factories before the factory object has been instantiated.

When we take a look at XML bean definition again

<lang:groovy id="personController" script-source="classpath:PersonController.groovy">
  <lang:property name="personRepository" ref="personRepository" />
</lang:groovy>

we know that the definition is some kind of hybrid between script factory (defined by the XML attributes) and scripted object (defined by the properties) definition.

Splitting into two separate bean definitions, a factory bean definition and a scripted object bean definition, is exactly what the ScriptFactoryPostProcessor does:

// ...
this.scriptBeanFactory.registerBeanDefinition(scriptFactoryBeanName, createScriptFactoryBeanDefinition(bd));
// ...
BeanDefinition objectBd = createScriptedObjectBeanDefinition(bd, scriptFactoryBeanName, scriptSource, scriptedInterfaces);
// ...

The code creating the object bean definition looks the following way:

protected BeanDefinition createScriptedObjectBeanDefinition(BeanDefinition bd, String scriptFactoryBeanName, ScriptSource scriptSource, Class[] interfaces) {

    GenericBeanDefinition objectBd = new GenericBeanDefinition(bd);
    objectBd.setFactoryBeanName(scriptFactoryBeanName);
    objectBd.setFactoryMethodName("getScriptedObject");
    objectBd.getConstructorArgumentValues().clear();
    objectBd.getConstructorArgumentValues().addIndexedArgumentValue(0, scriptSource);
    objectBd.getConstructorArgumentValues().addIndexedArgumentValue(1, interfaces);
    return objectBd;
}

The BeanDefinition instance which is handed as the first argument, holds the initial bean definition. It is copied and the bean rewritten to be a bean created by a factory method. After all, Spring’s Groovy integration and related components modify the initial XML definition to something like:

<bean name="scriptFactory.personController" class="org.springframework.scripting.groovy.GroovyScriptFactory">
   <constructor-arg type="java.lang.String" value="classpath:PersonController.groovy"/> 
</bean>

<bean id="personController" name="scriptedObject.personController" factory-bean="scriptFactory.messenger" factory-method="getScriptedObject" class="groovy.script.PersonController">
   <!-- ... -->
</bean>

Scripted Beans in Spring

As already mentioned, one of the main reasons you may want to use Spring’s Groovy integration is dynamic refreshing of Groovy classes during run-time. The question which might raise is: why is it worth to use Spring’s integration and not a custom solution like throwing GroovyClassLoader in the class loader hierarchy?

Refreshing Groovy Beans

Refreshing Groovy beans can be comfortable during development. In fact, refreshing beans comes down to reloading modified Groovy classes at run-time. I guess you already know that this is a potential trap for memory leaks (for an introduction to this problem take a look at [0] or [1]).

Spring takes on a burden and solves the problem of class reloading and memory leaks by implementing a mechanism which allows beans to refresh themselves at some time during container life-time. AOP proxies are used to utilize this behavior. In the case of its dynamic language support, it provides a RefreshableScriptTargetSource which is responsible for providing a fresh bean whenever a certain delay has occurred. Creating a fresh mean is simply done by calling getBean of the current bean factory:

protected Object obtainFreshBean(BeanFactory beanFactory, String beanName) {
    return beanFactory.getBean(beanName);
}

This code only works since the scriptable bean post-processor checks whether a delay has been set in the XML configuration and, if yes, applies the PROTOTYPE scope to the scripted object bean:

long refreshCheckDelay = resolveRefreshCheckDelay(bd);
if (refreshCheckDelay >= 0) {
    objectBd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}

The BeanDefinition.SCOPE_PROTOTYPE scope causes the application container to create a new instance whenever the bean is retrieved via getBean et. al. methods. Whenever a bean needs to be refreshed the factory method of the script factory, getScriptedObject, will be called to get a newly created scripted object bean.

Additional Features

If you know Grails and its object-relational mapping framework GORM, you surely have seen dynamically added methods, e.g. dynamic findes like User.findAllByLogin("mustermann"). Spring’s integration layer provides a way for Groovy objects to register so-called GroovyObjectCustomizer implementations with Groovy script factories.

The purpose of a GroovyObjectCustomizer is to allow customization of all Groovy objects, generated by the given script factory. The interface is as easy as:

public interface GroovyObjectCustomizer {
  void customize(GroovyObject goo);
}

This interface’s implementations can be specified via the customizer-ref XML attribute.

<bean id="groovyObjectCustomizer" class="org.some.groovy.GlobalGroovyObjectCustomizer"/>

<lang:groovy id="personController" script-source="classpath:PersonController.groovy" customizer-ref="groovyObjectCustomizer">
  <lang:property name="personRepository" ref="personRepository" />
</lang:groovy>

The groovyObjectCustomizer can than be used to do meta-programming, etc.

Alternatives

Notice, integrating Groovy in Spring does not need to be that complicated anyway if you don’t care about dynamically reloading Groovy sources. Since Groovy comes with its own compiler, it all comes down to JVM byte-code at the end. That means you are free to use all of Spring’s features as long as the outcoming byte-code conforms to that of its Java equivalent. E.g. you can use Spring MVC annotations to declare controllers:

@RequestMapping("/person/**")
@Controller
class PersonController {

  @Autowired
  def PersonRepository personRepository

  @RequestMapping(value = "/person", method = RequestMethod.POST)
  def String create(@Valid Person person, BindingResult result, ModelMap model) {

    if (result.hasErrors()) {
      model["person"] = person
      "person/create"
    } else {

      personRepository.persist person

      redirect "/person/${person.getId()}"
    }
  }

  @RequestMapping(value = "/person/form", method = RequestMethod.GET)
  def String createForm(ModelMap model) {
    model["person"] = new Person()

    "person/create"
  }

  @RequestMapping(value = "/person/{id}", method = RequestMethod.GET)
  def String show(@PathVariable("id") Long id, ModelMap model) {
    model["person"] = personRepository.findPerson(id)

    "person/show"
  }
  // ...
}

There is no additional configuration effort. This makes it even more interesting to implement the controller and view completely on top of Groovy and realize the domain in statically typed, good-old Java.

Summary

Spring’s dynamic language support covers Groovy, JRuby and BeanShell out-of-the-box and could be easily extended. The framwork’s approach is to support certain artifacts to be implemented by Groovy, e.g. Controllers, Repositories, Services etc.

The main feature that would suffice to actually use its integration layer, instead of compiling classes and getting the application’s build-processes in the correct order, is refreshing of scripted objects. Although you might not want to enable this feature in production, it indeed saves you a lot of time during development and it saves a lot of headaches for taking care of class loading memory leaks.

[0] Reloading Java Classes: Objects, Classes and ClassLoaders
[1] ClassLoader leaks: the dreaded “Out of Memory” Exception
[2] Spring Documentation – Dynamic Language Support
[3] Embedding Groovy – Groovy Project Codehaus

Categories: groovy, spring framework