Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

At this point, all objects will at least try to get created by Spring. If they cannot be created by Spring, then WebWork will create the object itself.

--------------

What is Spring and Why do you want to use it with WebWork?

Check out http://www.springframework.org for more details about Spring. To summarize, Spring provides several different layers. Spring's IoC container, for instance, provides a nice transparent way to wire together objects with their dependencies, such as services they use. It can also, with the help of its AOP framework, provide transactional behavior to plain Java beans. Spring also provides an MVC framework, which is what could be compared to WebWork. There are those who believe WebWork is a better MVC framework, and so would choose WebWork for this part and integrate the rest of the Spring stack.
There are a number of ways to integrate Spring into WebWork.

Use SpringObjectFactory

Next, you'll need to turn on the Spring listener in web.xml:

Code Block
xml
xml

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Sample Spring Configuration

At this point, you can add the standard Spring configuration at WEB-INF/applicationContext.xml. An example of this configuration isThe xwork-optional package from dev.java.net contains a module xwork-spring that contains all the necessary code to use Spring in WebWork. It contains primarily a SpringObjectFactory to wire up the dependencies for an Action before passing it to WebWork. Each action should be configured within a Spring application context as a prototype (because WebWork assumes a new instance of a class for every action invocation). Specify something like this in applicationContext.xml:

Code Block
xml
xml
<bean<?xml nameversion="some-action" class="fully.qualified.class.name" singleton="false">
    <property name="someProperty"><ref bean="someOtherBean"/></property>
</bean>

and in xwork.xml:

...


<action name="myAction" class="some-action">
    <result name="success">view.jsp</result>
</action>
1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="autodetect">
    <bean id="personManager" class="com.acme.PersonManager"/>
    ...
</beans>

Initializing Actions from Spring

Normally, in xwork.xml you specify the class for each action. This means that WebWork will create the action and wire up dependencies as specified as the default auto-wire behavior. However, sometimes you might want the bean to be completely managed by Spring. This is useful, for example, if you wish to apply AOP or Spring-enabled technologies, such as Acegi, to your beans. To do this, all you have to do is remove the class attribute from your WebWork action in xwork.xml and then add a bean in applicationContext.xml.

The only thing to remember when doing this is that there is a special naming convention when looking up actions in Spring. The convention is action:(optional-namespace/)actionName. For example, if you have an action in no namespace ("") called foo and another action in the /secure namespace called bar, your applicationContext.xml would look like so

Notice that the WebWork Action's class name some-action is the bean name defined in the Spring application context.

Another advantage of the SpringObjectFactory approach is that it can also be used to load interceptors using the same sort of logic. If the interceptor is stateless, then it's possible to create the interceptor as a singelton instance, but otherwise it's best to create it as a Spring prototype.
In order to be used, the default ObjectFactory that WebWork uses should be replaced with an instance of the SpringObjectFactory. There are two different ways to accomplish this. The first method is to use the ContextListener in the xwork-optional package. This method assumes that the Spring application context has already been configured. Add the following to web.xml:

Code Block
xml
xml
<!-- This needs to be after Spring ContextLoaderListener -->
<listener>
  <listener-class>com.opensymphony.xwork.spring.SpringObjectFactoryListener</listener-class>
</listener>

Note: this is actually a XWork configuration but for simplicity, I just assume WebWork.

The second method is to call the initObjectFactory method on com.opensymphony.xwork.spring.SpringObjectFactory. The easiest way to do this is to have Spring's application configure and supply the aforementioned method as the "init-method". Add the following to your applicationContext.xml:

Code Block
xmlxml

<bean id="spring-object-factory?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="autodetect">
    <bean id="action:foo" class="com.opensymphony.xwork.spring.SpringObjectFactory" init-method="initObjectFactory"/>
acme.Foo"/>
    <bean id="action:/secure/bar" class="com.acme.Foo"/>
</beans>

Remember: this is not required. This is only needed if you wish to override the default behavior when the action is created in WebWork by decorating it with Spring-enabled interceptors and IoC. Keep in mind that WebWork's Spring integration will do standard IoC, using whatever auto-wiring you specify, even if you don't explicitely map each action in Spring. So typically you don't need to do this, but it is good to know the naming convention if you need toNote: The second option should work when only using Xwork (as compared to XW and WW2).