CXF SOAP (JAX-WS) Webservice Wrapped Style

In this tutorial, we will take the WSDL created here and change it to a wrapped style web service.

Example Scenario:

In the example Quick Overview of SOAP (JAX-WS) webservice with CXF, we built a web service from WSDL and the parameter style is called BARE. The method of the interface takes a request object and returns a response object. The one we are going to build here is called WRAPPED style. It means that each parameter of WSDL message is placed into the message body as a child of message root, which is the operation name. In RPC style of web service call, this is default. Let’s tweak the created WSDL a little bit to make it wrapped style. The web service would take two binary inputs and provide the sum in response.


Project artifacts:

Technologies used –

a. Eclipse IDE for Java EE developer 4.5.0.20150621-1200 (Mars)
b. Preinstalled Maven with Eclipse Mars
c. Tomcat 7.0.64
d. CXF 3.0.3
e. Java 1.8

Jars used –

cxf-rt-frontend-jaxws-3.0.3.jar
xml-resolver-1.2.jar
asm-3.3.1.jar
cxf-core-3.0.3.jar
woodstox-core-asl-4.4.1.jar
stax2-api-3.1.4.jar
xmlschema-core-2.1.0.jar
cxf-rt-bindings-soap-3.0.3.jar
cxf-rt-wsdl-3.0.3.jar
wsdl4j-1.6.3.jar
cxf-rt-databinding-jaxb-3.0.3.jar
jaxb-impl-2.2.10-b140310.1920.jar
jaxb-core-2.2.10-b140310.1920.jar
cxf-rt-bindings-xml-3.0.3.jar
cxf-rt-frontend-simple-3.0.3.jar
cxf-rt-ws-addr-3.0.3.jar
cxf-rt-ws-policy-3.0.3.jar
neethi-3.0.3.jar
slf4j-log4j12-1.5.6.jar
slf4j-api-1.5.6.jar
log4j-1.2.14.jar
cxf-rt-transports-http-3.0.3.jar
commons-logging-1.1.1.jar
spring-web-4.1.7.RELEASE.jar
spring-aop-4.1.7.RELEASE.jar
aopalliance-1.0.jar
spring-beans-4.1.7.RELEASE.jar
spring-context-4.1.7.RELEASE.jar
spring-expression-4.1.7.RELEASE.jar
spring-core-4.1.7.RELEASE.jar

Before we begin:

To learn how to create maven web project, please read this tutorial.

To learn how to create a WSDL, please read this tutorial.

– The  modified WSDL

If noticed carefully, in wrapped style development of web service, the operation name, the message part name and the element name are all same.

The element name of the response in created by appending “Response” to the request element name.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.javanbeyond.com/BinaryAdditionService/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="BinaryAdditionService" targetNamespace="http://www.javanbeyond.com/BinaryAdditionService/">
    <wsdl:types>
        <xsd:schema targetNamespace="http://www.javanbeyond.com/BinaryAdditionService/">
            <xsd:element name="binaryAddWrapped">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="a" type="xsd:string"></xsd:element>
                        <xsd:element name="b" type="xsd:string"></xsd:element>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="binaryAddWrappedResponse">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="out" type="xsd:string"></xsd:element>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="binaryAddRequest">
        <wsdl:part element="tns:binaryAddWrapped" name="parameters"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="binaryAddResponse">
        <wsdl:part element="tns:binaryAddWrappedResponse" name="parameters"></wsdl:part>
    </wsdl:message>
    <wsdl:portType name="BinaryAdditionService">
        <wsdl:operation name="binaryAddWrapped">
            <wsdl:input message="tns:binaryAddRequest"></wsdl:input>
            <wsdl:output message="tns:binaryAddResponse"></wsdl:output>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="BinaryAdditionServiceSOAP" type="tns:BinaryAdditionService">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"></soap:binding>
        <wsdl:operation name="binaryAddWrapped">
            <soap:operation soapAction="http://www.javanbeyond.com/BinaryAdditionService/binaryAdd"></soap:operation>
            <wsdl:input>
                <soap:body use="literal"></soap:body>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"></soap:body>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="BinaryAdditionService">
        <wsdl:port binding="tns:BinaryAdditionServiceSOAP" name="BinaryAdditionServiceSOAP">
            <soap:address location="http://www.javanbeyond.com/"></soap:address>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

 

– The initial project directory structure 

WrappedStyleDire Struct

– pom.xml ( at the beginning)

<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.javanbeyond</groupId>
    <artifactId>QuickSOAPWrappedStyle</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>QuickSOAPWrappedStyle Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <repositories>
        <repository>
            <id>apache-snapshots</id>
            <name>Apache SNAPSHOT Repository</name>
            <url>http://repository.apache.org/snapshots/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>QuickSOAPWrappedStyle</finalName>
        <plugins>
            <!-- the plugin that converts the wsdl to java source code -->
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>3.0.3</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <sourceRoot>${basedir}/src/main/java</sourceRoot>
                            <wsdlOptions>
                                <wsdlOption>
                                    <!-- wsdl location to be used for building java classes. -->
                                    <wsdl>${basedir}/src/main/resources/BinaryAdditionServiceWrapped.wsdl</wsdl>
                                    <!-- wsdl location for run time -->
                                    <wsdlLocation>classpath:BinaryAdditionServiceWrapped.wsdl</wsdlLocation>
                                    <extraargs>
                                        <!-- we need server side implementation java classes -->
                                        <extraarg>-impl</extraarg>
                                        <extraarg>-verbose</extraarg>
                                    </extraargs>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

 

Please run maven clean and install.

You should see java classes being created. Comment the plugins tag in pom.xml so that when we build the war file, the java classes shouldn’t be recreated and our changes are not overridden.

Let’s proceed…

  1. Final project directory structure

Wrapped Final Directory Struc

– WSDL and class mapping

The following image depicts the mapping based on which CXF tool wsdl2java and JAXB created the classes from WSDL and schema.

WSDLClassMappingWrapped

package-info.java : It contains the mapping between target namespace of the WSDL (http://www.javanbeyond.com/BinaryAdditionService/) and the created package name (com.javanbeyond.binaryadditionservice).It can be modified by passing -p argument to wsdl2java tool of CXF. Each package has one package-info.java.

ObjectFactory.java : It acts as a factory class to create objects for the classes in its package. If there are multiple namespaces in schema, so will be multiple packages and each package has its own ObjectFactory class.

BinaryAddWrapped.java : The Request class which acts as a wrapper for the incoming request and into which the incoming payload is unmarshalled to.

BinaryAddWrappedResponse.java : The Response class which acts as a wrapper for the outgoing response from operation method and which is marshalled to response XML.

BinaryAdditionService.java : The web service interface created based on port type in WSDL.

BinaryAdditionServiceSOAPImpl.java : The implementation class of BinaryAdditionService interface. All our business logic will be written here or will start here.

BinaryAdditionService_Service.java : The client representation of the Service.

2. Implementation class

file : BinaryAdditionServiceSOAPImpl. This class has a method created from WSDL operation and all our business logic should be in this method or should start from this method. If you look closely, the method parameters and return types are different from BARE style. It takes two String and returns one, instead of a request and response object. At the time of unmarshalling, the parameters are extracted from the request object and passed as arguments to the operation method. At the time of marshalling, the returning parameter is wrapped inside the response object.

 


/**
 * Please modify this class to meet your needs
 * This class is not complete
 */

package com.javanbeyond.binaryadditionservice;

import java.util.logging.Logger;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

/**
 * This class was generated by Apache CXF 3.0.3 2015-09-25T22:40:17.940-05:00
 * Generated source version: 3.0.3
 
 */

@javax.jws.WebService(serviceName = "BinaryAdditionService", portName = "BinaryAdditionServiceSOAP", targetNamespace = "http://www.javanbeyond.com/BinaryAdditionService/", wsdlLocation = "classpath:BinaryAdditionServiceWrapped.wsdl", endpointInterface = "com.javanbeyond.binaryadditionservice.BinaryAdditionService")

public class BinaryAdditionServiceSOAPImpl implements BinaryAdditionService {

    private static final Logger LOG = Logger
            .getLogger(BinaryAdditionServiceSOAPImpl.class.getName());

    /*
     * (non-Javadoc)
     
     * @see com.javanbeyond.binaryadditionservice.BinaryAdditionService#
     * binaryAddWrapped(java.lang.String a ,)java.lang.String b )*
     */
    // in Wrapped style , instead of receiving request object, we are receiving
    // the parts of the request
    public java.lang.String binaryAddWrapped(java.lang.String a,
            java.lang.String b) {
        LOG.info("Executing operation binaryAddWrapped");
        try {
            java.lang.String _return = Integer.toBinaryString(
                    Integer.parseInt(a, 2+ Integer.parseInt(b, 2));
            // We don't have to return the response object. Just the part is
            // enough
            return _return;
        catch (java.lang.Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

}

 

3. Spring configuration.

file : BinaryAdditionWrappedConfig.xml. Spring application context file to bind different instances of classes (beans) in spring container including our web service class within an application.

 

<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-3.2.xsd   http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
    <!-- The actual implementation class and the corresponding url to access         it . Check how a simple bean is exposed as web service in cxf -->
    <jaxws:endpoint id="calculateEndpoint" implementor="#binaryCalculate" address="/WrappedBinaryCalculatorService"></jaxws:endpoint>
    <bean id="binaryCalculate" class="com.javanbeyond.binaryadditionservice.BinaryAdditionServiceSOAPImpl"></bean>
</beans>

 

4. Deployment descriptor

file: web.xml. Deployment descriptor file for mapping URIs to CXF servlet. The spring configuration file location is added as a context parameter through web.xml.

 

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:BinaryAdditionWrappedConfig.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/soap/*</url-pattern>
    </servlet-mapping>
</web-app>

Example Execution:

  1. Please run maven clean and install and deploy the war file created in Tomcat . You can use your own choice of SOAP client. In this tutorial, we will use SOAPUI, a popular web service client.
  2. Open SOAPUI and create a SOAP project with the url “http://localhost:8080/QuickSOAPWrappedStyle/soap/WrappedBinaryCalculatorService?wsdl”

SOAP Project CXF WrappedStyle

3. Press OK. A SOAP project should get created.

SOAPUI Project Wrapped Style

4. Fill any binary input and press the send button. You should get the sum as response .

Wrapped SOAP UI Request Response

 

 

Leave a Reply

Back to Top
%d bloggers like this: