Using Spring and Groovy to quick prototype actions
Spring 2.0 adds support for scripted beans. This means a script engine can be used to run a script that will look like a regular java class.
Struts also supports scripted actions, but this requires to change the struts config. This may be a good option, but not if you want your production web application to use compiled java classes, and just use scripting support for quick application prototyping.
Using Spring 2.0 scripted-beans, Groovy that can parse a 100% java source file and Struts allow to quickly change a "classic" java action into a scripted bean, and just hit refresh in the browser to see effects of a code change.
How to ?
- Create a simple interface that define the Struts action "execute" method:
public interface StrutsAction { public abstract ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception; }
1.#2 Create a SciptedBeanActionAdapter class :
public class SciptedBeanActionAdapter extends Action { private StrutsAction delegate; public SciptedBeanActionAdapter(StrutsAction delegate) { this.delegate = delegate; } public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return delegate.execute(mapping, form, request, response); } }
1.#3 Configure your web application to use this requestProcessor :
public class GroovyAutowiringTilesRequestProcessor extends AutowiringTilesRequestProcessor { protected Action processActionCreate(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws IOException { WebApplicationContext wac = getWebApplicationContext(); String beanName = DelegatingActionUtils .determineActionBeanName(mapping); if (wac.containsBean(beanName)) { StrutsAction bean = (StrutsAction) wac.getBean(beanName, StrutsAction.class); return new SciptedBeanActionAdapter(bean); } return super.processActionCreate(request, response, mapping); } }
This processor will look into spring context for a bean that implements StrutsAction and which name is the action mapping path.
1.#4 Add classpath*:localContext.xml to your spring web application context. This file will not be required at runtime, so there is no impact on the production application.
- Put a localContext.xml file into your application server classpath. I myself created it in $TOMCAT/shared/classes.
- Add Groovy, asm and Spring-support jars in your web application libs
Your application is now ready for quick prototyping !
Hot reload action's java code
Now, consider you have a FooAction mapped to "/foo.do" you want to edit quickly.
- Make your action implement StrutsAction. You only have to add "implements StrutsAction" as your action allready extends struts Action and defines the execute method.
- Edit your localContext.xml and add :
<alias name="groovyAction" alias="/foo"/> <lang:groovy id="groovyAction" script-source="file:D:/../src/java/.../FooAction.java" refresh-check-delay="1"> </lang:groovy>
If you want to use dependency injection, simply add
<lang:property name="property" ref="bean"/>
1.#3 Start the app, go to your web page.
- Change the code and simply hit refresh to see effects. No recompile, repackage, redeploy required !