| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
| <html> |
| <head> |
| <meta http-equiv="content-type" content=""> |
| <title>Axis2 integration with the Spring Framework</title> |
| <link href="../css/axis-docs.css" rel="stylesheet" type="text/css" media="all" /> |
| </head> |
| |
| <body lang="en"> |
| <h1>Axis2 Integration With The Spring Framework</h1> |
| |
| <p>This document is a guide on how to use Axis2 with the Spring Framework</p> |
| |
| <h2>Content</h2> |
| <ul> |
| <li><a href="#1">Introduction</a></li> |
| <li><a href="#2">Configuring Axis2 to be Spring aware</a> |
| <ul> |
| <li><a href="#21">Programming Model</a></li> |
| <li><a href="#22">Simple Spring config example</a></li> |
| <li><a href="#23">With a ServletContext </a></li> |
| <li><a href="#24">Without a ServletContext</a></li> |
| <li><a href="#25">Putting it all together</a></li> |
| <li><a href="#26">Spring inside an AAR </a> |
| <ul> |
| <li><a href="#261">The Spring inside an AAR layout</a></li> |
| <li><a href="#262">The Spring inside an AAR init class</a></li> |
| <li><a href="#263">Known issues running Spring inside the AAR</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| <a name="1"></a> |
| |
| <h2>Introduction</h2> |
| |
| <p>The idea behind Axis2 and Spring integration is that Axis2 simply needs to |
| have Spring supply one of its pre-loaded beans to the Axis2 Message |
| Receiver defined in the AAR services.xml . While Axis2 typically uses |
| reflection to instantiate the ServiceClass defined in the services.xml that |
| the Message Receiver will use, alternatively one can define a |
| ServiceObjectSupplier that will supply the Object.</p> |
| |
| <p>This guide will show how to use two separate ServiceObjectSupplier classes |
| that are part of the Axis2 standard distribution: One for use with a ServletContext, |
| and one without. 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 core functionality is required.</p> |
| |
| <p>This guide assumes some basic knowledge of Axis2. See the <a |
| href="userguide.html">User's Guide</a> for more information.</p> |
| <a name="2"></a> |
| |
| <h2>Configuring Axis2 to be Spring Aware</h2> |
| <a name="21"></a> |
| |
| <h3>Programming Model</h3> |
| |
| <p>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 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 .</p> |
| <a name="22"></a> |
| |
| <h3>Simple Spring Config Example</h3> |
| |
| <p>For the purpose of this example, and for no other reason besides |
| simplicity, we'll configure Spring via a WAR file's web.xml. Lets add a |
| context-param and a listener:</p> |
| <pre><listener> |
| <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> |
| </listener> |
| <context-param> |
| <param-name>contextConfigLocation</param-name> |
| <param-value>/WEB-INF/applicationContext.xml</param-value> |
| </context-param></pre> |
| |
| <p>Next we will show two examples of Spring's /WEB-INF/applicationContext.xml |
| referenced in the web.xml listener - one using a ServletContext, and one |
| without.</p> |
| <a name="23"></a> |
| |
| <h3>With a ServletContext</h3> |
| |
| <p>This 'with a ServletContext' example applicationContext.xml should be |
| familiar to any Spring user:</p> |
| <pre> <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> |
| |
| <beans> |
| <!-- Axis2 Web Service, but to Spring, its just another bean that has dependencies --> |
| <bean id="springAwareService" class="spring.SpringAwareService"> |
| <property name="myBean" ref="myBean"/> |
| </bean> |
| |
| <!-- just another bean / interface with a wired implementation, that's injected by Spring |
| into the Web Service --> |
| <bean id="myBean" class="spring.MyBeanImpl"> |
| <property name="val" value="Spring, emerge thyself" /> |
| </bean> |
| </beans></pre> |
| |
| <p>If the service is running in a Servlet Container, i.e., Axis2 will be able |
| to get a hold of ServletContext, the services.xml for the example would be |
| using SpringServletContextObjectSupplier such as:</p> |
| <pre> <service name="SpringAwareService"> |
| <description> |
| simple spring example |
| </description> |
| <parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter> |
| <parameter name="SpringBeanName" locked="false">springAwareService</parameter> |
| <operation name="getValue"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> |
| </operation> |
| </service> </pre> |
| |
| <p>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 .</p> |
| <a name="24"></a> |
| |
| <h3>Without a ServletContext</h3> |
| |
| <p>In the case Axis2 can't get a ServletContext, ie another transport or running 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' :</p> |
| <pre><?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> |
| |
| <beans> |
| <!-- Configure spring to give a hook to axis2 without a ServletContext --> |
| <bean id="applicationContext" |
| class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" /> |
| |
| <!-- Axis2 Web Service, but to Spring, its just another bean that has dependencies --> |
| <bean id="springAwareService" |
| class="spring.SpringAwareService"> |
| <property name="myBean" ref="myBean" /> |
| </bean> |
| |
| <!-- just another bean with a wired implementation, that's injected by Spring |
| into the Web Service --> |
| <bean id="myBean" |
| class="spring.MyBeanImpl"> |
| <property name="val" value="Spring, emerge thyself" /> |
| </bean> |
| </beans></pre> |
| |
| <p>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 would be using SpringAppContextAwareObjectSupplier such as:</p> |
| <pre> <service name="SpringAwareService"> |
| <description> |
| simple spring example |
| </description> |
| <parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter> |
| <parameter name="SpringBeanName" locked="false">springAwareService</parameter> |
| <operation name="getValue"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> |
| </operation> |
| </service> </pre> |
| |
| <p>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 .</p> |
| |
| <p>In a 'without a ServletContext' environment, one way you could load the |
| applicationContext.xml file is in a place that will be run once, upon |
| start-up, execute:</p> |
| <pre>import org.springframework.context.support.ClassPathXmlApplicationContext; |
| |
| public void createSpringAppCtx(ClassLoader cl) |
| throws Exception { |
| |
| ClassPathXmlApplicationContext ctx = new |
| ClassPathXmlApplicationContext(new String[] {Constants.MY_PATH + |
| "spring/applicationContext.xml"}, false); |
| ctx.setClassLoader(cl); |
| ctx.refresh();</pre> |
| } <a name="25"></a> |
| |
| <h3>Putting It All Together</h3> |
| |
| <p>From here, its 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 below:</p> |
| <pre>package spring; |
| |
| import org.apache.axiom.om.OMAbstractFactory; |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.om.OMFactory; |
| import org.apache.axiom.om.OMNamespace; |
| import org.apache.axiom.om.OMText; |
| |
| public class SpringAwareService { |
| |
| private MyBean myBean = null; |
| |
| //spring 'injects' this implementation |
| public void setMyBean(MyBean myBean) { |
| this.myBean = myBean; |
| } |
| |
| // The web service |
| public OMElement getValue(OMElement ignore) { |
| OMFactory factory= |
| OMAbstractFactory.getOMFactory(); |
| OMNamespace payloadNs= factory.createOMNamespace( |
| "http://springExample.org/example1", "example1"); |
| OMElement payload = |
| factory.createOMElement("string", payloadNs); |
| OMText response = factory.createOMText(this.myBean.emerge()); |
| payload.addChild(response); |
| return payload; |
| } |
| } </pre> |
| |
| <p>For those new to Spring, one of the ideas is that you program to an |
| Interface, and the implementation is pluggable. This idea is referenced in |
| the Spring config file above. Below is the interface:</p> |
| <pre>package spring; |
| |
| /** Interface for Spring aware Bean */ |
| public interface MyBean { |
| String emerge(); |
| }</pre> |
| |
| <p>Here's the implementation:</p> |
| <pre>/** Spring wired implementation */ |
| public class MyBeanImpl implements MyBean { |
| |
| String str = null; |
| // spring 'injects' this value |
| public void setVal(String s) { |
| str = s; |
| } |
| // web service gets this value |
| public String emerge() { |
| return str; |
| } |
| }</pre> |
| |
| <p>Lastly here's the client - not really necessary for the example, other |
| than for completeness:</p> |
| <pre>package client; |
| |
| import java.io.StringWriter; |
| |
| import javax.xml.stream.XMLOutputFactory; |
| |
| import org.apache.axiom.om.OMAbstractFactory; |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.om.OMFactory; |
| import org.apache.axiom.om.OMNamespace; |
| import org.apache.axis2.addressing.EndpointReference; |
| import org.apache.axis2.client.Options; |
| import org.apache.axis2.client.ServiceClient; |
| |
| public class TestClient { |
| private static EndpointReference targetEPR = |
| new EndpointReference( |
| "http://localhost:8080/axis2/services/SpringAwareService"); |
| |
| /** |
| * Simple axis2 client. |
| * |
| * @param args Main |
| */ |
| public static void main(String[] args) { |
| try { |
| OMFactory factory = OMAbstractFactory.getOMFactory(); |
| OMNamespace omNs = factory.createOMNamespace( |
| "http://springExample.org/example1", "example1"); |
| |
| OMElement method = factory.createOMElement("getValue", omNs); |
| OMElement value = factory.createOMElement("Text", omNs); |
| value.addChild(factory.createOMText(value, "Some String ")); |
| method.addChild(value); |
| |
| ServiceClient serviceClient = new ServiceClient(); |
| |
| Options options = new Options(); |
| serviceClient.setOptions(options); |
| options.setTo(targetEPR); |
| |
| //Blocking invocation |
| OMElement result = serviceClient.sendReceive(method); |
| |
| StringWriter writer = new StringWriter(); |
| result.serialize(XMLOutputFactory.newInstance() |
| .createXMLStreamWriter(writer)); |
| writer.flush(); |
| |
| System.out.println("Response: " + writer.toString()); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| } </pre> |
| |
| <p>The examples above assumes 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:</p> |
| <source><pre>./mySpring.jar |
| ./META-INF |
| ./META-INF/MANIFEST.MF |
| ./spring |
| ./spring/MyBean.class |
| ./spring/MyBeanImpl.class |
| ./spring/SpringAwareService.class |
| </pre> </source> |
| |
| <p>Since all the user classes are in mySpring.jar in this example, the AAR merely contains the |
| services.xml file:</p> |
| |
| <source> |
| <pre>./springExample.aar |
| ./META-INF |
| ./META-INF/MANIFEST.MF |
| ./META-INF/services.xml |
| </pre> </source> |
| |
| <p>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. Running the client, you should see this output:</p> |
| <pre>Response: <example1:string xmlns:example1="http://springExample.org/example1" |
| xmlns:tns="http://ws.apache.org/axis2">Spring, emerge thyself</example1:string></pre> |
| <a name="26"></a> |
| |
| <h3>Spring Inside an AAR</h3> |
| |
| <p>Frequently Axis2 users wish to run Spring inside the AAR. Here we show you |
| how. There are four points to be aware of:</p> |
| |
| <p>(A) You need to configure Spring to use the Axis2 Service Classloader. See the |
| <a href="#263">Known issues running Spring inside the AAR</a> area. </p> |
| |
| <p>(B) Its up to you to load Spring, though we give an example below.</p> |
| |
| <p>(C) For reasons such as classloader isolation the |
| SpringAppContextAwareObjectSupplier is the best choice.</p> |
| |
| <p>(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. </p> |
| <ul> |
| <li><strong><a name="261"></a>The Spring inside an AAR layout</strong> |
| </ul> |
| <source> |
| <pre>./springExample.aar |
| ./META-INF |
| ./META-INF/MANIFEST.MF |
| ./META-INF/services.xml |
| ./applicationContext.xml |
| ./lib |
| ./lib/axis2-spring-SNAPSHOT.jar |
| ./lib/spring.jar |
| ./spring |
| ./spring/MyBean.class |
| ./spring/MyBeanImpl.class |
| ./spring/SpringAwareService.class |
| ./spring/SpringInit.class </pre> </source> |
| |
| <p>As explained in the <a href="#24">Without a ServletContext</a> section, likewise the |
| 'Spring inside an AAR' config needs to hook Axis2 and Spring together via a Spring bean. |
| Place the following in your Spring config file:</p> |
| <pre> |
| <!-- Configure spring to give a hook to axis2 without a ServletContext --> |
| <bean id="applicationContext" |
| class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" /> |
| </pre> |
| <ul> |
| <li><strong><a name="262"></a>The Spring inside an AAR init class</strong></li> |
| </ul> |
| <p>One way to initialize Spring inside the AAR is to use the |
| org.apache.axis2.engine.ServiceLifeCycle interface. Here we give an example:</p> |
| <source><pre>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) { |
| } |
| }</pre> |
| </source> |
| <p>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 <a href="#263">Known issues running Spring inside the AAR</a> |
| area. </p> |
| <source><pre><serviceGroup> |
| <!-- Invoke SpringInit on server startup and shutdown --> |
| <service name="SpringAwareService" class="spring.SpringInit"> |
| <description> |
| simple spring example - inside the AAR |
| </description> |
| <!-- need the TCCL param when using spring inside the AAR --> |
| <parameter name="ServiceTCCL" locked="false">composite</parameter> |
| <parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter> |
| <parameter name="SpringBeanName" locked="false">springAwareService</parameter> |
| <operation name="getValue"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> |
| </operation> |
| </service> |
| </serviceGroup></pre> |
| </source> |
| <ul> |
| <li> |
| <strong><a name="263"></a>Known issues running Spring inside the AAR</strong> |
| </li> |
| </ul> |
| <p>The Axis2 classloader strategy by default 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. The behavior of 'composite' was the default in the development |
| cycle in between 1.0 and 1.1, but it resulted in the JIRA issue AXIS2-1214 - essentially |
| problems with getting an initContext.lookup() handle inside the AAR. Spring users typically |
| have little desire to use initContext.lookup() however, 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. While fully testing |
| JndiObjectFactoryBean with ejb has not been done yet - if you do, please send a message |
| to the axis users list - Datasources via Spring inside the AAR have been tested. Basically |
| it works as typically done with Spring, though if you are passing Hibernate XML files you need |
| to put them in a place where Spring will find them. The most flexible way is as follows, using |
| logging in DEBUG mode to see where Spring will look in your jar / class locations: </p> |
| <source><pre> |
| <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> |
| <property name="mappingLocations"> |
| <value>classpath*:**/MyEntity.hbm.xml</value> |
| </property> |
| ... |
| </bean> |
| </pre> </source> |
| </body> |
| </html> |