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 ?

  1. 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.

  1. Put a localContext.xml file into your application server classpath. I myself created it in $TOMCAT/shared/classes.
  2. 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.

  1. Make your action implement StrutsAction. You only have to add "implements StrutsAction" as your action allready extends struts Action and defines the execute method.
  2. 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.

  1. Change the code and simply hit refresh to see effects. No recompile, repackage, redeploy required !
  • No labels