Google

Oct 17, 2012

SOAP (JAX-WS) Web Service Tutorial with Apache CXF, eclipse and maven

In the previous tutorial RESTful service with Apache CXF was demonstrated. This tutorial modifies the same one for SOAP based Web Service.


Step 1: You need to bring in the relevant CXF framework JAR files. The transitive dependencies will bring in the other dependent Spring jar files, JAXB jar files, and many other jar files listed in the screenshot below.

The pom.xml file is shown below:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.mytutorial</groupId>
 <artifactId>simpleWeb</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>simpleWeb Maven Webapp</name>
 <url>http://maven.apache.org</url>


 <properties>
  <cxf.version>2.2.3</cxf.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>

 
  <!-- CXF SOAP Web Service JARS -->
  <dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-frontend-jaxws</artifactId>
  <version>${cxf.version}</version>
 </dependency>
 <dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-transports-http</artifactId>
  <version>${cxf.version}</version>
 </dependency>
  

 </dependencies>
 <build>
  <finalName>simpleWeb</finalName>
 </build>
</project>


Now, if you right-mouse-click on simpleWeb,  and select "Maven --> Update Depencies", you can see all the transitively dependent jar files in the "Java Perspective" as shown below.


As you can see, it transitively brings in Spring and JAXB jars in addition to other relevant jars.

Step 2: Define the SOAP (i.e. JAX-WS) Web Service interface and implementation classes with relevant annotations.

Interface HelloUserWebService.java

package com.mytutorial.webservice;

import javax.jws.WebService;

import com.mytutorial.pojo.User;

@WebService
public interface HelloUserWebService {
 //parameter that gets passed via the URL
 User greetUser(String userName);
}

Implementation HelloUserWebServiceImpl.java

package com.mytutorial.webservice;

import javax.jws.WebParam;
import javax.jws.WebService;

import com.mytutorial.pojo.User;

@WebService(endpointInterface = "com.mytutorial.webservice.HelloUserWebService")
public class HelloUserWebServiceImpl implements HelloUserWebService {

 
 public User greetUser(@WebParam(name="name") String userName) {
  User user = new User();
  user.setName(userName);
  return user;
 }

}


Step 3: Define the web service endpoint via cxf.xml, which internally uses the Spring framework. Define this under sr/main/resources folder under a package com.mytutorial.webservice.

<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.xsd
                          http://cxf.apache.org/jaxws
            http://cxf.apache.org/schemas/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="auth"
                  implementor="com.mytutorial.webservice.HelloUserWebServiceImpl"
                  address="/userservices"/>
</beans>


Step 4: The web.xml file and the User.java files are same as the RESTful Web Service tutorial. You should now have the relevant artifacts as shown below.




Step 5: Deploy the simpleWeb.war to the Tomcat server from within eclipse or from outside eclipse as described in the simple web JEE tutorial.

Step 6:  Open a wen browser like google chrome, and type the following URL -> http://localhost:8080/simpleWeb/. This will list the JAX-WS and JAX-RS  Web services that are available.



Step 7:  You can now open a WSDL (Web Services Description Language) file on the browser with the following URL --> http://localhost:8080/simpleWeb/userservices?wsdl

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="HelloUserWebServiceImplService" targetNamespace="http://webservice.mytutorial.com/" xmlns:ns1="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://webservice.mytutorial.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="http://webservice.mytutorial.com/" version="1.0" xmlns:tns="http://webservice.mytutorial.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="greetUser" type="tns:greetUser" />
<xs:element name="greetUserResponse" type="tns:greetUserResponse" />
<xs:element name="user" type="tns:user" />
<xs:complexType name="greetUser">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="greetUserResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="tns:user" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="user">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="greetUser">
    <wsdl:part element="tns:greetUser" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="greetUserResponse">
    <wsdl:part element="tns:greetUserResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="HelloUserWebService">
    <wsdl:operation name="greetUser">
      <wsdl:input message="tns:greetUser" name="greetUser">
    </wsdl:input>
      <wsdl:output message="tns:greetUserResponse" name="greetUserResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloUserWebServiceImplServiceSoapBinding" type="tns:HelloUserWebService">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="greetUser">
      <soap:operation soapAction="" style="document" />
      <wsdl:input name="greetUser">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="greetUserResponse">
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloUserWebServiceImplService">
    <wsdl:port binding="tns:HelloUserWebServiceImplServiceSoapBinding" name="HelloUserWebServiceImplPort">
      <soap:address location="http://localhost:8080/simpleWeb/userservices" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>



Step 8: From the above WSDL, you can either create a SOAP UI Client to test the above JAX-WS service, or write a stand-alone client Java class to test it programmatically.

package com.mytutorial.client;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.mytutorial.pojo.User;
import com.mytutorial.webservice.HelloUserWebService;

public final class SoapClientTest {

 private SoapClientTest() {
 }

 public static void main(String args[]) throws Exception {

  JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

  factory.getInInterceptors().add(new LoggingInInterceptor());
  factory.getOutInterceptors().add(new LoggingOutInterceptor());
  factory.setServiceClass(HelloUserWebService.class);
        //The URL should be externalized to a configuration file 
     factory.setAddress("http://localhost:8080/simpleWeb/userservices");
  HelloUserWebService client = (HelloUserWebService) factory.create();

  User user = client.greetUser("John");
  System.out.println("Response is: " + user.getName());

 }

}

The output will be:

15/10/2012 1:10:57 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.apache.cxf.bus.spring.BusApplicationContext@9506dc4: display name [org.apache.cxf.bus.spring.BusApplicationContext@9506dc4]; startup date [Mon Oct 15 13:10:57 EST 2012]; root of context hierarchy
15/10/2012 1:10:57 PM org.apache.cxf.bus.spring.BusApplicationContext getConfigResources
INFO: No cxf.xml configuration file detected, relying on defaults.
15/10/2012 1:10:57 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.apache.cxf.bus.spring.BusApplicationContext@9506dc4]: org.springframework.beans.factory.support.DefaultListableBeanFactory@62da3a1e
15/10/2012 1:10:57 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@62da3a1e: defining beans [cxf,org.apache.cxf.bus.spring.BusApplicationListener,org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor,org.apache.cxf.bus.spring.Jsr250BeanPostProcessor,org.apache.cxf.bus.spring.BusExtensionPostProcessor,org.apache.cxf.resource.ResourceManager,org.apache.cxf.configuration.Configurer,org.apache.cxf.binding.BindingFactoryManager,org.apache.cxf.transport.DestinationFactoryManager,org.apache.cxf.transport.ConduitInitiatorManager,org.apache.cxf.wsdl.WSDLManager,org.apache.cxf.phase.PhaseManager,org.apache.cxf.workqueue.WorkQueueManager,org.apache.cxf.buslifecycle.BusLifeCycleManager,org.apache.cxf.endpoint.ServerRegistry,org.apache.cxf.endpoint.ServerLifeCycleManager,org.apache.cxf.endpoint.ClientLifeCycleManager,org.apache.cxf.transports.http.QueryHandlerRegistry,org.apache.cxf.endpoint.EndpointResolverRegistry,org.apache.cxf.headers.HeaderManager,org.apache.cxf.catalog.OASISCatalogManager,org.apache.cxf.endpoint.ServiceContractResolverRegistry,org.apache.cxf.jaxws.context.WebServiceContextResourceResolver,org.apache.cxf.jaxws.context.WebServiceContextImpl,org.apache.cxf.binding.soap.SoapBindingFactory,org.apache.cxf.binding.soap.SoapTransportFactory,org.apache.cxf.binding.soap.customEditorConfigurer,org.apache.cxf.binding.xml.XMLBindingFactory,org.apache.cxf.ws.addressing.policy.AddressingAssertionBuilder,org.apache.cxf.ws.addressing.policy.AddressingPolicyInterceptorProvider,org.apache.cxf.ws.addressing.policy.UsingAddressingAssertionBuilder,org.apache.cxf.transport.http.policy.HTTPClientAssertionBuilder,org.apache.cxf.transport.http.policy.HTTPServerAssertionBuilder,org.apache.cxf.transport.http.policy.NoOpPolicyInterceptorProvider,org.apache.cxf.transport.http.ClientOnlyHTTPTransportFactory]; root of factory hierarchy
15/10/2012 1:10:58 PM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
INFO: Creating Service {http://webservice.mytutorial.com/}HelloUserWebServiceService from class com.mytutorial.webservice.HelloUserWebService
15/10/2012 1:10:58 PM org.apache.cxf.interceptor.LoggingOutInterceptor$LoggingCallback onClose
INFO: Outbound Message
---------------------------
ID: 1
Address: http://localhost:8080/simpleWeb/userservices
Encoding: UTF-8
Content-Type: text/xml
Headers: {SOAPAction=[""], Accept=[*/*]}
Payload: John
--------------------------------------
15/10/2012 1:10:59 PM org.apache.cxf.interceptor.LoggingInInterceptor logging
INFO: Inbound Message
----------------------------
ID: 1
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {content-type=[text/xml;charset=UTF-8], Date=[Mon, 15 Oct 2012 02:10:59 GMT], Content-Length=[236], Server=[Apache-Coyote/1.1]}
Payload: John
--------------------------------------
Response is: John








Labels:

2 Comments:

Anonymous PiF said...

I can't really find the web.xml and user.java files "from the other tutorial". Could you please include them in this tutorial?

5:23 PM, October 01, 2013  
Blogger Unknown said...

please check http://java-success.blogspot.com.au/2012/10/restful-web-service-tutorial-with.html

8:44 PM, October 01, 2013  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home