Introduction

Axis2 and Spring integration takes place when Spring supplies one of its
pre-loaded beans to the Axis2 Message Receiver defined in the AAR
services.xml. Axis2 typically uses reflection to instantiate the ServiceClass
defined in the services.xml used by the Message Receiver. Alternatively, you
can define a ServiceObjectSupplier that will supply the Object.

This guide describes how to use two separate ServiceObjectSupplier classes
that are a part of the Axis2 standard distribution - one for use with a
ServletContext, and one without. Configuring Axis2 with a ServletContext is
simpler than without, and is recommended for most use cases. Without a
ServletContext, ie, Spring inside the AAR, requires an extra Spring bean
and is considered an advanced use case. Once configured, the Web service itself
acts like any other Spring wired bean. These Spring beans can be loaded any way
desired as Axis2 has no configuration file dependencies from Spring. Spring
versions 1.2.6, 1.2.8 and 2.0 have been tested, but probably any version
would work as only the core functionality is required.

This guide assumes some basic knowledge of Axis2. See the User's Guide for more information.

Programming Model

From an Axis2 standpoint, two hooks are needed to be placed into the AAR
services.xml - the ServiceObjectSupplier that hooks Axis2 and Spring
together, and the name of the Spring bean that Axis2 will use as the service.
All Message Receivers are currently supported, as would be any Message
Receiver that extends org.apache.axis2.receivers.AbstractMessageReceiver .

Simple Spring Config Example

For the purpose of this example, we'll configure Spring via a WAR file's
web.xml. Let's add a context-param and a listener:

If the service is running in a Servlet Container, i.e., Axis2 will be able
to get a hold of the ServletContext, the services.xml for the example would
be using SpringServletContextObjectSupplier such as:

While the above example uses RawXMLINOutMessageReceiver as its
messageReceiver class, all Message Receivers are currently supported, as
would be any Message Receiver that extends
org.apache.axis2.receivers.AbstractMessageReceiver .

Without a ServletContext

In case Axis2 can't get a ServletContext, (i.e., uses a different
transport or is running Axis2 inside the AAR etc,) you have the option of
defining a bean that takes advantage of Spring's internal abilities
(ApplicationContextAware interface, specifically) to provide an Application
Context to Axis2, with a bean ref 'applicationContext' :

If the service is not running in a Servlet Container,
i.e., Axis2 will not be able to get a hold of ServletContext or you prefer
not to, the services.xml for the example will be using
SpringAppContextAwareObjectSupplier such as:

While the above example uses RawXMLINOutMessageReceiver as its
messageReceiver class, all Message Receivers are currently supported, as
would be any Message Receiver that extends
org.apache.axis2.receivers.AbstractMessageReceiver .

In an environment without a ServletContext, one way you
could load the applicationContext.xml file is in a place that will be run
once. Upon start-up, execute the following:

Putting It All Together

From here, it's just standard Axis2 coding. Only now the service has
Spring wiring capabilities. The implementation is the same whether using
either SpringServletContextObjectSupplier or
SpringAppContextAwareObjectSupplier. The service is as follows:

The examples above assume that both the spring framework .jar and the
axis2-spring-*.jar are under WEB-INF/lib. In such a case, the classes shown
in this tutorial need to be placed in a JAR under WEB-INF/lib. In this
example the JAR layout is:

To run this example, make sure you have the axis2-spring*.jar that comes
from the axis2-std-*-bin distro in the server side WEB-INF/lib, as well as
the appropriate Spring jar - most will use the full spring.jar, but the
minimum requirements are spring-core, spring-beans, spring-context, and
spring-web. When running the client, you should see this output:

(C) For reasons such as classloader isolation, the
SpringAppContextAwareObjectSupplier is the best choice.

(D) The springframework .jar and axis2-spring-*.jar will be placed inside
the AAR under the lib directory. Please move the
axis2-spring-*.jar from WEB-INF/lib to inside the AAR, as shown below - it
will not work otherwise.

One way to initialize Spring inside the AAR is to use the
org.apache.axis2.engine.ServiceLifeCycle interface. Here we give an
example:

package spring;
import org.apache.axis2.engine.ServiceLifeCycle;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringInit implements ServiceLifeCycle {
/**
* This will be called during the deployement time of the service.
* irrespective
* of the service scope this method will be called
*/
public void startUp(ConfigurationContext ignore, AxisService service) {
try {
System.out.println("Starting spring init");
ClassLoader classLoader = service.getClassLoader();
ClassPathXmlApplicationContext appCtx = new
ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"}, false);
appCtx.setClassLoader(classLoader);
appCtx.refresh();
System.out.println("spring loaded");
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* This will be called during the system shut down time.
* irrespective
* of the service scope this method will be called
*/
public void shutDown(ConfigurationContext ctxIgnore, AxisService ignore) {
}
}

Here's the services.xml that now includes SpringInit and the
SpringAwareService shown above. There is also the composite parameter which
is needed when loading Spring in the AAR - see the Known
issues running Spring inside the AAR area.

By default, the Axis2 classloader strategy does not permit Spring to run
inside the AAR. To allow Spring to run inside the AAR, the 'composite'
parameter is used in the services.xml as shown in the example above. There
was default behavior of 'composite' in the development cycle in between 1.0
and 1.1, but it resulted in the JIRA issue AXIS2-1214 -problems with getting
an initContext.lookup() handle inside the AAR. Spring users typically have
little desire to use initContext.lookup(), as they get their Datasources via
org.springframework.jdbc.datasource.DriverManagerDataSource in an XML file or
with annotations. For EJB home references and the like, Spring provides
JndiObjectFactoryBean.

A common requirement is to run Hibernate along with Spring with Axis2 web services.
It is easier to run Hibernate as well as Spring outside the AAR as shown in the
ServletContext example, ie, place the Spring and Hibernate jars in WEB-INF/lib and
the hibernate config files under WEB-INF/classes. With that advisement, Spring provides
an API that allows Spring to load Hibernate under the contraints of an AAR.

Hibernate by default looks for its config files in the classpath. By running Hibernate
inside the AAR, Hibernate won't be able to find its config files. The way to get
around this limitation is either to expand the AAR or place the hibernate config
files in a specific directory under WEB-INF/classes - and then use
Spring's setMappingDirectoryLocations for several options.

By placing Spring into DEBUG mode you can look at the logs to see where Spring will look
for your jar / class locations. Use the wildcards in the following example to list your mapping
locations as shown: