See latest update: Groovy Works
A further update is available here.
Last week I started implementing my Struts 2 actions in Groovy. After a few days I decided I liked Groovy, but I wanted more. I didn't want to have to restart my servlet container every time I recompiled a class. I just wanted to be able to edit, save, and reload in my browser.
I researched using Spring to instantiate my actions, but Spring's scripting integration only supports singletons. So, to get around this I extended the Struts 2 Spring Plugin to integrate the GroovyClassLoader. That created problems with Spring's use of AspectJ's pointcuts to support declarative transactions. (Thread on Spring forum.)
So, I dropped back to Spring, and with some guidance from Chris Tam on the Spring JIRA I implemented the prototype scope for scripted beans. This is what the whole thing rests on. Spring takes care of instantiating our actions and watches to see if the source file has been changed. If the source has been changed Spring recompiles the script and returns the new action instance.
At this point I can write my actions in Groovy and have them be instantiated and recompiled on the fly by Spring. I can do the same for my service beans, also using Spring.
Unfortunately this requires a patched version of Spring that supports scoped scripted beans. (Total of about 15 lines of code and comments, patch attached to the JIRA issue referenced above.)
My project is managed using Maven. I started with the Struts 2 archetype some time ago, which includes support for the Jetty plugin. So, my development process is now edit my Groovy file, save, and run 'mvn compile'. This copies my .groovy file to the target/classes directory so it will be on the classpath.
My ultimate goal is to have a simple environment for Struts 2, where I don't need to reload the server for every change in the application. I can edit, and test in my browser directly without requiring a "compile" or "deployment" phase. The only time I want to need to restart the server is for changes to my Struts 2 config, such as a new action; changes to my Spring context configuration; or changes to my persistence configuration.
Additionally any framework that integrates with Spring could use these techniques to eliminate restarts, and move toward using dynamic scripting languages for implementation.
I started mixing in Spring's declarative transactions using aop pointcuts and it blows up pretty solidly. I think I'm dealing with a classloader issue. It appears to me that within the Spring container AspectJ has a classloader that is a child of the main classloader for the Spring container. When Spring creates a GroovyClassLoader instance it is also a child of the main Spring classloader and therefore a sibling of the AspectJ classloader. When AspectJ tries to figure out what the groovy bean is it can't because it has no visibility to the GroovyClassLoader, which is a sibling.
I'm not sure what the resolution to this could be. It seems somewhat intractable. It would almost seem that if you're going to mix scripting languages into a Spring context the classloaders needs to be created very carefully. Where all scripting language classloaders are a parent of the AspectJ classloader. Problem is Spring seems to create a class loader per scripted bean that it loads.
I will report more as I find more.
Recent comments
6 weeks 4 days ago
7 weeks 2 days ago
7 weeks 5 days ago
8 weeks 5 days ago
9 weeks 18 hours ago
9 weeks 23 hours ago
9 weeks 5 days ago
12 weeks 6 days ago
13 weeks 4 days ago
13 weeks 4 days ago