Integrating the Spring Framework with Webwork 1.x (1.4.1 or higher)
This is a step by step guide on integrating WebWork with the Spring Framework http://www.springframework.org
. Like the integration with PicoContainer (see PicoContainer Integration), Spring can be used to manage Webwork Actions, handle the "wiring" of business objects, action or any JavaBeans, by the time the web application starts up. Another benefit of integrating Spring is that it enables the use of interceptors and all other AOP features.
The first step is to ensure that you have the appropriate jars in place. Copy spring.jar to your WEB-INF/lib directory. If you want to use interceptors and other AOP features, then you should also copy cglib.jar, asm.jar, and aopalliance.jar to the web lib directory.
The next step is to specify an implementation of ActionFactoryProxy, SpringActionFactoryProxy. This will cause Webwork to first attempt to find actions in Spring's ApplicationContext; if it's not found Webwork will then look for it in the same manner as without Spring (simply instantiate the action class).
A custom ActionFactory, SpringActionFactory, must be specified to insert the SpringActionFactoryProxy into the ActionFactory stack.
In webwork.properties change/add this line:
webwork.action.factory=webwork.action.factory.SpringActionFactory
Finally, register the spring listener or servlet in your web.xml, by adding the following (this example uses the servlet for compatibility with old/odd containers, but if your container supports it you should use the spring listener instead).
web.xml
<servlet>
<servlet-name>springloader</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
This takes care of the webwork side of things. Next, spring must be configured.
For the purposes of this example, webwork has one Action class (com.springapp.TestAction). com.springapp.EntityManager is a 'manager' business object that the TestAction requires. TestAction has get/setManager methods that take in an EntityManager.
Spring can also be used to specify interceptors. In this example, a trivial TimerInterceptor is specified that simply logs the duration of method calls for all our beans (including actions).
WEB-INF/applicationContext.xml
<!DOCTYPE beans PUBLIC "-
"http:>
<beans>
<!--
The webwork action. Note that the name OR id must be the fully qualified
name, this is required for webwork to successfully look up the action,
as it uses class names.
The singleton property specifies that this bean should be created on
every call. WebWork assumes that there is an action is specific to
its request.
->
<bean id="test" name="com.springapp.TestAction"
class="com.springapp.TestAction"
singleton="false">
<!- Specify the manager property of the action class ->
<property name="manager"><ref local="entityManager"/></property>
</bean>
<!- Specify the entity manager. Here we are not required to us the
classname as the id or name, since it is not a webwork action. ->
<bean id="entityManager"
class="com.springapp.EntityManager" singleton="true" />
<!- Specify our timer interceptor ->
<bean id="timerInterceptor" class="com.springapp.TimerInterceptor" />
<!-
This bean is responsible for applying the interceptor to our classes.
The proxyTargetClass must be set to true to enforce usage of cglib,
rather than dynamic proxies. Dynamic proxies won't work with the valuestack
->
<bean id="proxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass">
<value>true</value>
</property>
<!- Specify the interceptors to apply ->
<property name="interceptorNames">
<list>
<ref bean="timerInterceptor"/>
</list>
</property>
<!- Specify the beans to apply the interceptors on -->
<property name="beanNames">
<list>
<value>test</value>
<value>*Manager</value>
</list>
</property>
</bean>
</beans>
For the sake of completeness, here are the Java sources:
TestAction.java
package com.springapp;
import webwork.action.ActionSupport;
public class TestAction extends ActionSupport
{
private EntityManager manager;
public EntityManager getManager()
{
return manager;
}
public void setManager(EntityManager manager)
{
this.manager = manager;
}
}
EntityManager.java
package com.springapp;
public class EntityManager
{
public String getStuff()
{
return "some stuff";
}
}
TimerInterceptor.java
package com.springapp;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class TimerInterceptor implements MethodInterceptor
{
private static final Log log = LogFactory.getLog(TimerInterceptor.class);
public Object invoke(MethodInvocation methodInvocation) throws Throwable
{
if(methodInvocation.getMethod().getDeclaringClass()==Object.class)
{
return methodInvocation.proceed();
}
long startTime = System.currentTimeMillis();
String className = methodInvocation.getThis().getClass().getName();
int dot = className.lastIndexOf('.');
if(dot > -1) className = className.substring(dot + 1, className.length());
try
{
return methodInvocation.proceed();
}
finally
{
log.info(className + '.' + methodInvocation.getMethod().getName()
+ " " + (System.currentTimeMillis() - startTime) + "ms");
}
}
}
All that remains is the standard webwork configuration of mapping views to actions via actions.xml or views.properties.
Finally, deploy your web application, and have Spring help with assembling and wiring business objects into your actions - no more lookup code across your Action code!
If you mean the getRootFactory method, then use the cvs version of webwork 1.4, which has this method. No new functionality, the sole purpose of it is some minor refactoring so that you can subclass it to just specify where to get java actions from, without having to copy and paste the rest of the action factories and proxies in your subclass.