[groovy-user] Groovy scripts as Spring Beans

26 views
Skip to first unread message

Maarten Boekhold

unread,
Mar 4, 2013, 6:10:02 AM3/4/13
to us...@groovy.codehaus.org
Hi all,

I'm going to need to do some application customization work soon that
involves implementing an interface and wiring it into a spring
container. I just read that it's possible to write spring beans in
groovy as well, but the documentation on springsource mentions
explicitly that only groovy versions 1.0-1.5 are supported. Does anybody
know if more recent versions of groovy can be used as well?

Also, having never worked with Spring before, I am also not sure if I'm
supposed to provide the groovy-all jar myself or if they come with
spring already...

Maarten

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Guillaume Laforge

unread,
Mar 4, 2013, 6:28:23 AM3/4/13
to Groovy User
Hi Maarten,

It depends on how you want to use Groovy.
Whether you want to use it through the "lang:groovy" namespace, or like plain normal beans.
But in either case, you should be able to use a recent version of Groovy — but the documentation in Spring might need to be updated.
You'll probably have to define the version of groovy-all yourself, if you want to be specific about the particular Groovy version you want to use, but perhaps otherwise it's brought transitively when using the spring-context jar.
But I'm not a Spring expert, so worth double checking.
Further down the road, there's going to be a big Spring + Groovy theme in the next major Spring framework versions.

Guillaume

--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

Maarten Boekhold

unread,
Mar 4, 2013, 6:37:12 AM3/4/13
to us...@groovy.codehaus.org
Hi Guillaume,


On 03/04/2013 03:28 PM, Guillaume Laforge wrote:
Hi Maarten,

It depends on how you want to use Groovy.
Whether you want to use it through the "lang:groovy" namespace, or like plain normal beans.

lang:groovy preferrably. In fact I'd really like to use groovy-wslite in order to call an external web service from a "dynamic bean"...

With "plain normal beans" you are talking about compiled Groovy classes, which are then just included in the CLASSPATH of the Spring container/application?

But in either case, you should be able to use a recent version of Groovy � but the documentation in Spring might need to be updated.
You'll probably have to define the version of groovy-all yourself, if you want to be specific about the particular Groovy version you want to use, but perhaps otherwise it's brought transitively when using the spring-context jar.

What exactly do you mean with "brought transitively when using the spring-context jar"?


But I'm not a Spring expert, so worth double checking.

You might not be a Spring expert, but I'm a complete Spring noob :) So if I ask obvious questions, please bear with me. Working hard to update my spring knowledge.

Further down the road, there's going to be a big Spring + Groovy theme in the next major Spring framework versions.

Guillaume

On Mon, Mar 4, 2013 at 12:10 PM, Maarten Boekhold <boek...@yahoo.com> wrote:
Hi all,

I'm going to need to do some application customization work soon that involves implementing an interface and wiring it into a spring container. I just read that it's possible to write spring beans in groovy as well, but the documentation on springsource mentions explicitly that only groovy versions 1.0-1.5 are supported. Does anybody know if more recent versions of groovy can be used as well?

Also, having never worked with Spring before, I am also not sure if I'm supposed to provide the groovy-all jar myself or if they come with spring already...

Maarten

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

Guillaume Laforge

unread,
Mar 4, 2013, 6:50:45 AM3/4/13
to Groovy User
On Mon, Mar 4, 2013 at 12:37 PM, Maarten Boekhold <boek...@yahoo.com> wrote:
Hi Guillaume,


On 03/04/2013 03:28 PM, Guillaume Laforge wrote:
Hi Maarten,

It depends on how you want to use Groovy.
Whether you want to use it through the "lang:groovy" namespace, or like plain normal beans.

lang:groovy preferrably. In fact I'd really like to use groovy-wslite in order to call an external web service from a "dynamic bean"...

Using lang:groovy is interesting when you want to have "refreshable" beans, so that means having the requirement of being able to alter the bean later on.
You can also define such Groovy beans inside the application context XML file, but I'm uncertain what it really brings compared to having the proper Groovy source file available as a normal .groovy file.

The fact you want to use groovy-wslite doesn't force you to use the lang:groovy namespace at all.
That's why, personally, I'd got with "plain normal beans".
 
With "plain normal beans" you are talking about compiled Groovy classes, which are then just included in the CLASSPATH of the Spring container/application?

Exactly, plain Groovy classes, just like you have plain Java classes.
It's just your build that needs to be adapted to use the Groovy compiler — usually with the joint compiler.
 
But in either case, you should be able to use a recent version of Groovy — but the documentation in Spring might need to be updated.
You'll probably have to define the version of groovy-all yourself, if you want to be specific about the particular Groovy version you want to use, but perhaps otherwise it's brought transitively when using the spring-context jar.
What exactly do you mean with "brought transitively when using the spring-context jar"?

The lang:groovy namespace stuff is part of the spring-context subproject, as far as I can see.

If you look at the POM of that subproject:
You'll notice that the dependency is "optional", so you'll have to add the Groovy all JAR on your classpath.

So, it's actually not brought "transitively" (in the sense that depending on spring-context won't pull the dependency on Groovy).

Notice that it's using Groovy 1.8.8 by default, but I think it should just work fine with Groovy 2.1.1 as well.
 
But I'm not a Spring expert, so worth double checking.

You might not be a Spring expert, but I'm a complete Spring noob :) So if I ask obvious questions, please bear with me. Working hard to update my spring knowledge.

As the saying goes... there's no stupid question anyway ;-) 
So don't worry!

Guillaume

Further down the road, there's going to be a big Spring + Groovy theme in the next major Spring framework versions.

Guillaume

On Mon, Mar 4, 2013 at 12:10 PM, Maarten Boekhold <boek...@yahoo.com> wrote:
Hi all,

I'm going to need to do some application customization work soon that involves implementing an interface and wiring it into a spring container. I just read that it's possible to write spring beans in groovy as well, but the documentation on springsource mentions explicitly that only groovy versions 1.0-1.5 are supported. Does anybody know if more recent versions of groovy can be used as well?

Also, having never worked with Spring before, I am also not sure if I'm supposed to provide the groovy-all jar myself or if they come with spring already...

Maarten

---------------------------------------------------------------------
To unsubscribe from this list, please visit:




--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

Maarten Boekhold

unread,
Mar 4, 2013, 8:15:43 AM3/4/13
to us...@groovy.codehaus.org
On 03/04/2013 03:50 PM, Guillaume Laforge wrote:
lang:groovy preferrably. In fact I'd really like to use groovy-wslite in order to call an external web service from a "dynamic bean"...

Using lang:groovy is interesting when you want to have "refreshable" beans, so that means having the requirement of being able to alter the bean later on.
You can also define such Groovy beans inside the application context XML file, but I'm uncertain what it really brings compared to having the proper Groovy source file available as a normal .groovy file.

The fact you want to use groovy-wslite doesn't force you to use the lang:groovy namespace at all.
That's why, personally, I'd got with "plain normal beans".

Doesn't force me, but it's very useful during development of these web service calls, as I can easily update the SOAP document mapping without restarting the application (which is rather large).

�
With "plain normal beans" you are talking about compiled Groovy classes, which are then just included in the CLASSPATH of the Spring container/application?

Exactly, plain Groovy classes, just like you have plain Java classes.
It's just your build that needs to be adapted to use the Groovy compiler � usually with the joint compiler.

Ah, not possible, I'm not able to modify or recompile the existing code. I basically need to insert beans into a "shrink-wrapped" application.

Alternatively I might just do the development using a refreshable bean, but for production deployment try to compile the groovy source files and put everything into a jar file.
�

So, it's actually not brought "transitively" (in the sense that depending on spring-context won't pull the dependency on Groovy).

Notice that it's using Groovy 1.8.8 by default, but I think it should just work fine with Groovy 2.1.1 as well.

Awesome, should be able to manage that. And even 1.8.8 should be fine (still checking the exact version of spring that this application uses, I don't have access right now).

Maarten

Maarten Boekhold

unread,
Mar 5, 2013, 12:45:40 AM3/5/13
to us...@groovy.codehaus.org
On 03/04/2013 05:15 PM, Maarten Boekhold wrote:
Exactly, plain Groovy classes, just like you have plain Java classes.
It's just your build that needs to be adapted to use the Groovy compiler � usually with the joint compiler.

Ah, not possible, I'm not able to modify or recompile the existing code. I basically need to insert beans into a "shrink-wrapped" application.


Ah, I see why you mentioned adjusting the build by using the joint compiler. I don't think this is necessary for me, as I don't see a cyclical dependency between the existing Java code and the Groovy code. In this case, there's no need to modify/create any Java classes... The groovy class would be loaded by the Spring IoC container based on a <bean> definition. I assume that's possible? A compiled groovy class can be loaded by the Spring IoC container?

Maarten

Maarten Boekhold

unread,
Mar 5, 2013, 1:28:44 AM3/5/13
to us...@groovy.codehaus.org
Hi all,

On 03/04/2013 03:28 PM, Guillaume Laforge wrote:
> Hi Maarten,
>
> It depends on how you want to use Groovy.
> Whether you want to use it through the "lang:groovy" namespace, or
> like plain normal beans.
>
I've been wondering about how such "refreshable beans" work in Spring.

First of all, by necessity I assume that such beans have to be
stateless. If spring refreshes the instance of such a bean whenever the
underlying source file changes, then any state stored in an instance of
that bean would be lost.

Second, since this bean would presumably be wired into some other bean,
I assume that Spring uses some proxy mechanism for the actual bean,
since it won't be able to create a new instance and then update all
other beans that reference this bean, right? So I assume that the actual
*instance* of the bean is wrapped in a proxy, and that it is this
*proxy* that is wired into other beans, and whenever the underlying
source file changes, Spring just replaces the wrapped instance inside
the proxy with the new updated instance?

Guillaume Laforge

unread,
Mar 5, 2013, 4:18:09 AM3/5/13
to Groovy User
On Tue, Mar 5, 2013 at 6:45 AM, Maarten Boekhold <boek...@yahoo.com> wrote:
On 03/04/2013 05:15 PM, Maarten Boekhold wrote:
Exactly, plain Groovy classes, just like you have plain Java classes.
It's just your build that needs to be adapted to use the Groovy compiler — usually with the joint compiler.

Ah, not possible, I'm not able to modify or recompile the existing code. I basically need to insert beans into a "shrink-wrapped" application.

Ah, I see why you mentioned adjusting the build by using the joint compiler. I don't think this is necessary for me, as I don't see a cyclical dependency between the existing Java code and the Groovy code. In this case, there's no need to modify/create any Java classes... The groovy class would be loaded by the Spring IoC container based on a <bean> definition. I assume that's possible? A compiled groovy class can be loaded by the Spring IoC container?

If there's no dependency of your Java code to your Groovy code, then you don't need the "joint" compile to handle both, and you can just add a groovyc compiler pass after the Java pass. 
Then, once compiled on the classpath (in a jar or whatever), yes, Groovy classes are just classes like any other, so they are loaded by the IoC container just fine.

Guillaume Laforge

unread,
Mar 5, 2013, 5:10:38 AM3/5/13
to Groovy User
On Tue, Mar 5, 2013 at 7:28 AM, Maarten Boekhold <boek...@yahoo.com> wrote:
Hi all,


On 03/04/2013 03:28 PM, Guillaume Laforge wrote:
Hi Maarten,

It depends on how you want to use Groovy.
Whether you want to use it through the "lang:groovy" namespace, or like plain normal beans.

I've been wondering about how such "refreshable beans" work in Spring.

First of all, by necessity I assume that such beans have to be stateless. If spring refreshes the instance of such a bean whenever the underlying source file changes, then any state stored in an instance of that bean would be lost.

Yes, I'd expect that as well.
So state should be avoided.
 
Second, since this bean would presumably be wired into some other bean, I assume that Spring uses some proxy mechanism for the actual bean, since it won't be able to create a new instance and then update all other beans that reference this bean, right? So I assume that the actual *instance* of the bean is wrapped in a proxy, and that it is this *proxy* that is wired into other beans, and whenever the underlying source file changes, Spring just replaces the wrapped instance inside the proxy with the new updated instance?

I don't know exactly how it's been implemented.
But looking at the implementation here:
It doesn't seem to be using proxies.

Maarten Boekhold

unread,
Mar 5, 2013, 6:08:36 AM3/5/13
to us...@groovy.codehaus.org
On 03/05/2013 02:10 PM, Guillaume Laforge wrote:
> Second, since this bean would presumably be wired into some other
> bean, I assume that Spring uses some proxy mechanism for the actual
> bean, since it won't be able to create a new instance and then update
> all other beans that reference this bean, right? So I assume that the
> actual *instance* of the bean is wrapped in a proxy, and that it is
> this *proxy* that is wired into other beans, and whenever the
> underlying source file changes, Spring just replaces the wrapped
> instance inside the proxy with the new updated instance?
>
> I don't know exactly how it's been implemented.
> But looking at the implementation here:
> https://github.com/SpringSource/spring-framework/blob/3.2.x/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptFactory.java
> It doesn't seem to be using proxies.
>

Hmmm, so I don't see how this could possibly update already instantiated
beans based on the modified script. Posted on the spring forums about
this, maybe somebody will be able to clarify this.

Maarten Boekhold

unread,
Mar 5, 2013, 6:51:25 AM3/5/13
to us...@groovy.codehaus.org
On 03/05/2013 03:08 PM, Maarten Boekhold wrote:
On 03/05/2013 02:10 PM, Guillaume Laforge wrote:
Second, since this bean would presumably be wired into some other bean, I assume that Spring uses some proxy mechanism for the actual bean, since it won't be able to create a new instance and then update all other beans that reference this bean, right? So I assume that the actual *instance* of the bean is wrapped in a proxy, and that it is this *proxy* that is wired into other beans, and whenever the underlying source file changes, Spring just replaces the wrapped instance inside the proxy with the new updated instance?

I don't know exactly how it's been implemented.
But looking at the implementation here:
https://github.com/SpringSource/spring-framework/blob/3.2.x/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptFactory.java
It doesn't seem to be using proxies.


Hmmm, so I don't see how this could possibly update already instantiated beans based on the modified script. Posted on the spring forums about this, maybe somebody will be able to clarify this.

Decided to try my hand at a simple test case, and I can confirm that any already instantiated groovy bean is not modified if you modify the script source file:

beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
    <!-- Bean declarations go here -->
    <lang:groovy id="mybean" script-source="MainBean.groovy" refresh-check-delay="50000" />
   
</beans>
MainBean.groovy:
class MainBean {
    def doit() {
        println "Some original text"
    }
}

test.groovy:
@Grapes([
@Grab(group='org.springframework', module='spring-context', version='3.0.5.RELEASE')
])
import org.springframework.context.support.FileSystemXmlApplicationContext

ctx = new FileSystemXmlApplicationContext("beans.xml");


mybean = ctx.getBean("mybean")
println "${mybean.class.name}"
mybean.metaClass.methods.each { println it }

System.in.eachLine { line ->
    if (line == "exit") System.exit(0)

    mybean.invokeMethod("doit", null)
}

If you run "groovy test.groovy" and hit enter a few times, you'll see "Some original text" printed to stdout. Now modify MainBean.groovy and add some text, save. No matter now long you wait, this test continues to print "Some original text", not any updated text you modified in MainBean.groovy.

This isn't what I expected when reading about "refreshable beans" and dynamic scripts in the spring docs!

Maarten

Btw. I had to use invokeMethod() cos if I used just "mybean.doit()", I got strange errors. That's also the reason for those extra debug statements in test.groovy.

Caught: java.lang.ClassCastException: sun.proxy.$Proxy5 cannot be cast to MainBean
java.lang.ClassCastException: sun.proxy.$Proxy5 cannot be cast to MainBean
    at MainBean$doit.call(Unknown Source)
    at test$_run_closure2.doCall(test.groovy:18)
    at test.run(test.groovy:15)

Maybe somebody could explain why I'm getting this exception? Something to do with different ClassLoaders maybe? (OC would love that!)

Maarten Boekhold

unread,
Mar 5, 2013, 7:07:04 AM3/5/13
to us...@groovy.codehaus.org

Everybody,

Please ignore my previous email. I realized I had an extra zero in my refresh-check-delay, and was just not waiting long enough...

So that just leaves my question then on that strange exception when I try to call the actual doit() method. Having said that, this is just an artificial test case, so I'm not too concerned with it.

Maarten
Reply all
Reply to author
Forward
0 new messages