| <!-- |
| ~ Licensed to the Apache Software Foundation (ASF) under one |
| ~ or more contributor license agreements. See the NOTICE file |
| ~ distributed with this work for additional information |
| ~ regarding copyright ownership. The ASF licenses this file |
| ~ to you under the Apache License, Version 2.0 (the |
| ~ "License"); you may not use this file except in compliance |
| ~ with the License. You may obtain a copy of the License at |
| ~ |
| ~ http://www.apache.org/licenses/LICENSE-2.0 |
| ~ |
| ~ Unless required by applicable law or agreed to in writing, |
| ~ software distributed under the License is distributed on an |
| ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| ~ KIND, either express or implied. See the License for the |
| ~ specific language governing permissions and limitations |
| ~ under the License. |
| --> |
| |
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" |
| "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> |
| <html> |
| <head> |
| <meta http-equiv="content-type" content=""/> |
| <title>Axis2 integration with the Spring Framework</title> |
| </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> |
| |
| <p> |
| For users of JSON and <a href="https://spring.io/projects/spring-boot">Spring Boot</a> |
| - or anyone interesed in a complete Spring Boot example that includes Spring Security - |
| see the sample application in the <a href= |
| "json-springboot-userguide.html">JSON and Spring Boot User's Guide.</a> |
| </p> |
| |
| <p> |
| Update: Spring inside the AAR is no longer supported. See this commit: |
| </p> |
| |
| <pre> |
| commit 9e392c0ae1f0abab3d4956fbf4c0818c9570021e |
| Author: Andreas Veithen <veithen@apache.org> |
| Date: Sat May 6 22:21:10 2017 +0000 |
| |
| AXIS2-3919: Remove the alternate class loading mechanism: |
| - It degrades performance. |
| - There is no test coverage for it. |
| - With r1794157 in place, in most cases, no temporary files will be created and there is no need for a fallback mechanism. |
| </pre> |
| |
| <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> |
| </ul> |
| </li> |
| </ul> |
| <a name="1"></a> |
| |
| <h2>Introduction</h2> |
| |
| <p>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.</p> |
| |
| <p>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.</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> |
| |
| <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 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 .</p> |
| <a name="22"></a> |
| |
| <h3>Simple Spring Config Example</h3> |
| |
| <p>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:</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 example (with a ServletContext) 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 the 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">org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter> |
| <parameter name="SpringBeanName">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 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' :</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 <strong>not</strong> 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:</p> |
| <pre> <service name="SpringAwareService"> |
| <description> |
| simple spring example |
| </description> |
| <parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter> |
| <parameter name="SpringBeanName">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 an environment <strong>without a ServletContext</strong>, one way you |
| could load the applicationContext.xml file is in a place that will be run |
| once. Upon start-up, execute the following:</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, 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:</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 who are new to Spring, one of the ideas is that you program an |
| Interface, as 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 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:</p> |
| <pre>./mySpring.jar |
| ./META-INF |
| ./META-INF/MANIFEST.MF |
| ./spring |
| ./spring/MyBean.class |
| ./spring/MyBeanImpl.class |
| ./spring/SpringAwareService.class</pre> |
| <p>Since all the user classes are in mySpring.jar in this example, the AAR |
| merely contains the services.xml file:</p> |
| <pre>./springExample.aar |
| ./META-INF |
| ./META-INF/MANIFEST.MF |
| ./META-INF/services.xml</pre> |
| <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. When 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> |
| </body> |
| </html> |