Apache CXF 2.0 Documentation > Index > How-Tos > Writing a service with Spring |
This example will lead you through creating your first service with Spring. You'll learn how to:
This example corresponds to the spring_http example in the CXF distribution.
Open up your favorite IDE and create a new project. The first thing we need to do is add the necessary CXF dependencies to the project. You can find these dependencies in the CXF distribution in the lib directory.
commons-logging-1.1.jar geronimo-activation_1.1_spec-1.0-M1.jar (or Sun's Activation jar) geronimo-annotation_1.0_spec-1.0.jar (JSR 250) geronimo-javamail_1.4_spec-1.0-M1.jar (or Sun's JavaMail jar) geronimo-servlet_2.5_spec-1.1-M1.jar (or Sun's Servlet jar) jaxb-api-2.1.jar jaxb-impl-2.1.2.jar jaxws-api-2.0.jar jsr181-api-1.0-MR1.jar saaj-api-1.3.jar saaj-impl-1.3.jar stax-api-1.0.1.jar wsdl4j-1.6.1.jar wstx-asl-3.2.0.jar XmlSchema-1.2.jar
The Spring jars:
aopalliance-1.0.jar spring-2.0.jar
And the CXF jars:
cxf-api-2.0-incubator-RC-SNAPSHOT.jar cxf-common-schemas-2.0-incubator-RC-SNAPSHOT.jar cxf-common-utilities-2.0-incubator-RC-SNAPSHOT.jar cxf-metacode-2.0-incubator-RC-SNAPSHOT.jar cxf-rt-bindings-soap-2.0-incubator-RC-SNAPSHOT.jar cxf-rt-core-2.0-incubator-RC-SNAPSHOT.jar cxf-rt-databinding-jaxb-2.0-incubator-RC-SNAPSHOT.jar cxf-rt-frontend-jaxws-2.0-incubator-RC-SNAPSHOT.jar cxf-rt-frontend-simple-2.0-incubator-RC-SNAPSHOT.jar cxf-rt-transports-http-2.0-incubator-RC-SNAPSHOT.jar cxf-tools-common-2.0-incubator-RC-SNAPSHOT.jar
First we'll write our service interface. It will have one operation called "sayHello" which says "Hello" to whoever submits their name.
package demo.spring; import javax.jws.WebService; @WebService public interface HelloWorld { String sayHi(String text); }
Our implementation will then look like this:
package demo.spring; import javax.jws.WebService; @WebService(endpointInterface = "demo.spring.HelloWorld") public class HelloWorldImpl implements HelloWorld { public String sayHi(String text) { return "Hello " + text; } }
The @WebService annotation on the implementation class lets CXF know which interface we want to create our WSDL with. In this case its simply our HelloWorld interface.
CXF contains support for "nice XML" within Spring 2.0. For the JAX-WS side of things, we have a <jaxws:endpoint> bean which sets up a server side endpoint.
Lets create a "beans.xml" file in our WEB-INF directory which declares an endpoint bean:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxws:endpoint id="helloWorld" implementor="demo.spring.HelloWorldImpl" address="http://localhost/HelloWorld" /> </beans>
The bean is pretty self explanatory. The id becomes the id of the bean in the Spring context. The serviceClass property is our implementation class. Finally, the address property specifies the location which we want to host our service at. This can be either a full address with host & port or just a path.
We'll need to add two things to our web.xml. First, the Spring ContextLoaderLister. This starts Spring and loads our beans.xml file. We can specify where our file is via a <context-param>. The second thing is the CXF Servlet.
<web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/beans.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>CXFServlet</servlet-name> <display-name>CXF Servlet</display-name> <servlet-class> org.apache.cxf.transport.servlet.CXFServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
It is important to note that the address that you chose for your endpoint bean must be one your servlet listens on. For instance, if my Servlet was register for "/some-services/*" but my address was "/more-services/HelloWorld", there is no way CXF could receive a request.
CXF includes a JaxWsProxyFactory bean which create a client for you from your service interface. You simply need to tell it what your service class is (the HelloWorld interface in this case) and the URL of your service. You can then create a client bean via the JaxWsProxyFactory bean by calling it's create() method.
Here's an example:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd"> <bean id="client" class="demo.spring.HelloWorld" factory-bean="clientFactory" factory-method="create"/> <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="demo.spring.HelloWorld"/> <property name="address" value="http://localhost:9002/HelloWorld"/> </bean> </beans>
If you were going to access your client you could now simply pull it out of the Spring context (or better yet, inject it into your application using Spring!):
ApplicationContext context = ...; // your Spring ApplicationContext HellWorld client = (HelloWorld) context.getBean("client");
For more information on using Spring you may want to read the Configuration and Spring sections of the User's Guide.