Integrating Groovy in Legacy Spring ApplicationsThere 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 FrameworkSpring'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.scriptingwhich is part of the
org.springframework.contextMaven 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: Notice, that the
langnamespace is used as a special namespace. Spring's
bshelements and, for each language, logically links them to custom
ScriptFactoryimplementations: At run-time, this task is done by an instance of
ScriptBeanDefinitionParser: for each bean definition prefixed with
langit generates a script factory bean according to the language element being specified. All XML attributes of
lang:groovyare indeed used to specify a script factory and not the Groovy object itself. Let us take a look at the
ScriptFactoryinterface: The most interesting methods are
getScriptedTypeis mainly used by Spring's IoC container to determine the bean type and check whether it implements certain interfaces, not much magic implied here.
requiresScriptedObjectRefreshcan 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.
getScriptedObjectis the heart of each script factory implementation. It is used as a factory method to create scripted Java objects.
Scripted Java ObjectsLet us take a look at the Groovy script factory implementation, which is found in
GroovyScriptFactory. and in
executeScript: As can be seen in the source snippet,
GroovyClassLoaderto parse the given script source string and to create a Java class object instance from it . 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
GroovyScriptFactorywould 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.
ScriptFactoryPostProcessorFirst of all, the
BeanPostProcessorinterface 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
BeanPostProcessoryou will notice that there are plenty of them. One with particular importance in the case of dynamic language support is the
InstantiationAwareBeanPostProcessoris 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 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
ScriptFactoryPostProcessordoes: The code creating the object bean definition looks the following way: The
BeanDefinitioninstance 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: 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 BeansRefreshing 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  or ). 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
RefreshableScriptTargetSourcewhich is responsible for providing a fresh bean whenever a certain delay has occurred. Creating a fresh mean is simply done by calling
getBeanof the current bean factory: 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
PROTOTYPEscope to the scripted object bean: The
BeanDefinition.SCOPE_PROTOTYPEscope causes the application container to create a new instance whenever the bean is retrieved via
getBeanet. 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 FeaturesIf 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
GroovyObjectCustomizerimplementations with Groovy script factories. The purpose of a
GroovyObjectCustomizeris to allow customization of all Groovy objects, generated by the given script factory. The interface is as easy as: This interface's implementations can be specified via the
customizer-refXML attribute. The
groovyObjectCustomizercan than be used to do meta-programming, etc.