Quick Overview of SOAP Webservice with Axis2

In this tutorial, we will learn how to build a simple SOAP web service using Axis2.

Example Scenario:

We need to build a web service based on SOAP using Axis2, which should do binary addition and provide us the 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. Axis2 1.6.2
e. Java 1.8

Jars used – 

axis2-adb-1.6.2.jar
axis2-kernel-1.6.2.jar
axiom-api-1.2.13.jar
geronimo-javamail_1.4_spec-1.7.1.jar
jaxen-1.1.3.jar
geronimo-stax-api_1.0_spec-1.0.1.jar
apache-mime4j-core-0.7.2.jar
axiom-impl-1.2.13.jar
wstx-asl-3.2.9.jar
geronimo-ws-metadata_2.0_spec-1.1.2.jar
geronimo-jta_1.1_spec-1.1.jar
servlet-api-2.3.jar
commons-httpclient-3.1.jar
commons-codec-1.2.jar
commons-fileupload-1.2.jar
wsdl4j-1.6.2.jar
XmlSchema-1.4.7.jar
neethi-3.0.2.jar
woden-api-1.0M9.jar
woden-impl-dom-1.0M9.jar
woden-impl-commons-1.0M9.jar
commons-logging-1.1.1.jar
jsr311-api-1.0.jar
geronimo-activation_1.1_spec-1.0.2.jar

Before we begin:

The following image depicts the folder structure of maven web project with WSDL in the resource folder.

To learn how to create a WSDL, please read this tutorial. We are going to use the same WSDL for this tutorial.

–    Eclipse project folder structure (at the beginning):

SOAP Webservice Axis2

–     pom.xml

Maven unit of work to declare project dependencies, compile code and build aar (axis2 archive) file for uploading in Axis2 war application. The pom.xml uses two plugins. The first plugin creates java classes for binding purpose from WSDL using the default binding framework of Axis2 i.e. adb. You can also use any of the other supported binding frameworks, which are XmlBeans, JiBX and JAXBRI. The second plugin bundles the created classes into an aar file for uploading to Axis2 war application.

<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>QuickSOAPOverviewAxis2</artifactId>
    <packaging>aar</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>QuickOverviewAxis2 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.axis2</groupId>
            <artifactId>axis2</artifactId>
            <version>1.6.2</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.apache.axis2</groupId>
            <artifactId>axis2-adb</artifactId>
            <version>1.6.2</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.axis2</groupId>
                <artifactId>axis2-wsdl2code-maven-plugin</artifactId>
                <version>1.6.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>wsdl2code</goal>
                        </goals>
                        <configuration>
                            <packageName>com.javanbeyond.binaryadditionservice</packageName>
                            <!-- WSDL file location -->
                            <wsdlFile>src/main/resources/BinaryAdditionService.wsdl</wsdlFile>
                            <!-- Location where sources will be created. -->
                            <outputDirectory>${basedir}/src/main/java</outputDirectory>
                            <!-- Using default databinding. -->
                            <databindingName>adb</databindingName>
                            <skipWSDL>true</skipWSDL>
                            <flattenFiles>true</flattenFiles>
                            <!-- We want only server side classes for web service implementation -->
                            <generateServerSide>true</generateServerSide>
                            <generateServicesXml>true</generateServicesXml>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.axis2</groupId>
                <artifactId>axis2-aar-maven-plugin</artifactId>
                <version>1.6.2</version>
                <extensions>true</extensions>
                <configuration>
                    <includeDependencies>false</includeDependencies>
                    <aarName>QuickSOAPOverviewAxis2</aarName>
                    <!-- Location where aar should be created -->
                    <outputDirectory>${basedir}/target</outputDirectory>
                    <!-- Location of services.xml which can be put inside aar and which                         was created by axis2-wsdl2code-maven-plugin -->
                    <servicesXmlFile>${basedir}/src/main/java/services.xml</servicesXmlFile>
                    <!-- Location of wsdl which can be put inside aar -->
                    <wsdlFile>${basedir}/src/main/resources/BinaryAdditionService.wsdl</wsdlFile>
                    <!-- The final name of the wsdl inside aar. Default is services.wsdl -->
                    <wsdlFileName>AdditionService.wsdl</wsdlFileName>
                </configuration>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>aar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Please run maven clean and install and you should see the java classes and few more artifacts created from WSDL.

– The created files from WSDL

  1. services.xml : The configuration file for the service which is used by Axis2 runtime to get service class information, operation mapping, message receivers etc of the service. This is not the only configuration file available in Axis2. For a detail list of  configuration files and its usage, please refer Axis2 Configuration Guide.

  2. BinaryAdditionServiceSkeleton.java :  The implementation class of the service which contains business logic.

  3. BinaryAdditionServiceMessageReceiverInOut.java : This class acts as a bridge between Axis2 engine and service skeleton instance. After a message is processed by the handlers, the Axis2 engine hands it over to a MessageReceiver. As far as Axis2 message processing is considered, Axis2 core engine considers the message to be processed complete when a message receiver is invoked. In this example, the message receiver is declared outside the operation, which will be applied to all operations of the service. Message receivers can also be declared inside operation, specific to each operation of the service.

  4. BinaryAddRequest : The java equivalent of the request XML which ADB uses for data binding.

  5. BinaryAddResponse : The java equivalent of response XML which ADB uses for data binding.

  6. ExtensionMapper.java : Class to support xsi:type.

Let’s Proceed…

  1. Final project directory structure:

    AxisWebserviceaar file

 

Please note the creation of aar (axis2 archive) file. This is the file we are going to deploy inside Axis2 war.

2. The skeleton class

file:BinaryAdditionServiceSkeleton.java. BinaryAdditionServiceSkeleton is the class which receives the request from client. We have implemented our addition logic in this class.

 

/**
 * BinaryAdditionServiceSkeleton.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis2 version: 1.6.2  Built on : Apr 17, 2012 (05:33:49 IST)
 */
package com.javanbeyond.binaryadditionservice;

import com.javanbeyond.www.binaryadditionservice.BinaryAddResponse;

/**
 * BinaryAdditionServiceSkeleton java skeleton for the axisService
 */
public class BinaryAdditionServiceSkeleton {

    /**
     * Auto generated method signature
     
     @param binaryAddRequest
     @return binaryAddResponse
     */

    public com.javanbeyond.www.binaryadditionservice.BinaryAddResponse binaryAdd(
            com.javanbeyond.www.binaryadditionservice.BinaryAddRequest binaryAddRequest) {
        BinaryAddResponse response = new BinaryAddResponse();
        response.setOut(Integer
                .toBinaryString(Integer.parseInt(binaryAddRequest.getA()2)
                        + Integer.parseInt(binaryAddRequest.getB()2)));
        return response;
    }

}

3. The service configuration file

file: services.xml. The description of services are specified using services.xml. Each service archive file needs to have a services.xml in order to be a valid service. If the service needs to be further fine-tuned, it can be done using services.xml.

<!-- This file was auto-generated from 
    WSDL --><!-- by the Apache Axis2 version: 1.6.2 
    Built on : Apr 17, 2012 (05:33:49 IST) --><serviceGroup>
    <service name="BinaryAdditionService">
        <messageReceivers>
            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out" class="com.javanbeyond.binaryadditionservice.BinaryAdditionServiceMessageReceiverInOut"></messageReceiver>
        </messageReceivers>
        <parameter name="ServiceClass">com.javanbeyond.binaryadditionservice.BinaryAdditionServiceSkeleton</parameter>
        <parameter name="useOriginalwsdl">true</parameter>
        <parameter name="modifyUserWSDLPortAddress">true</parameter>
        <operation name="binaryAdd" mep="http://www.w3.org/ns/wsdl/in-out" namespace="http://www.javanbeyond.com/BinaryAdditionService/">
            <actionMapping>http://www.javanbeyond.com/BinaryAdditionService/binaryAdd</actionMapping>
            <outputActionMapping>http://www.javanbeyond.com/BinaryAdditionService/BinaryAdditionService/binaryAddResponse</outputActionMapping>
        </operation>
    </service>
</serviceGroup>

4. Rerun maven clean install and the created aar file should have our logic now.

5. aar file deployment steps:

  1. Download the axis2 war and deploy it in Tomcat.
  2. Open your favorite browser and type “http://localhost:8080/axis2”.

Axis2WelcomeScreen

3. Click on “Administration” and provide username as “admin” and password “axis2”. Please refer to axis2 website for more details.

Axis2 war admin

4. Click on “Upload Service”.

Upload aar Axis2

5. Select the aar file created  and upload it.

6. Click on “Available Services”. Refresh the page . You should see the service name along with service endpoint URL. Client would use this url to access the service.

Uploaded aar file

Note : If the service is not visible, please restart Tomcat and then try.

Example Execution:

1. Open SOAPUI and create a SOAP project with the url “http://localhost:8080/axis2/services/BinaryAdditionService?wsdl”

Axis2SOAP UI Project

2. Hit the service with two binary values and you will get their binary sum in response.

Axis2 SOAPUI Request and Response

 

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

 

 

Quick Overview of SOAP (JAX-WS) webservice with CXF

In this tutorial, we will learn how to build a simple SOAP web service using CXF, a popular implementation of JAX-WS.

Example Scenario:

We need to build a web service based on SOAP, which would take two binary numbers in request and provide their added result 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:

Following is the folder structure of maven web project with WSDL in the resource folder.

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

To learn how to create a WSDL, please read this tutorial. We are going to use the same WSDL here.

–    Eclipse initial project folder structure:

CXF Web Project

–     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>QuickSOAPOverviewCXF</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>QuickSOAPOverviewCXF 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>QuickSOAPOverviewCXF</finalName>
        <plugins>
            <!--             Plugin to create equivalent java classes for the wsdl schema -->
            <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>
                            <!-- where to create the java classes -->
                            <sourceRoot>${basedir}/src/main/java</sourceRoot>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>${basedir}/src/main/resources/BinaryAdditionService.wsdl</wsdl>
                                    <wsdlLocation>classpath:BinaryAdditionService.wsdl</wsdlLocation>
                                    <extraargs>
                                        <!-- We want server side implementation 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 and you should see the following java classes created from WSDL.

 

CXFGeneratedClasses

– 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.

CXFWSDLClassMappingBinding

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.

BinaryAddResponse.java : The Response class whose object will be marshalled to response XML.

BinaryAddRequest.java : The Request class which the incoming payload will be unmarshalled to and passed to implementation operation method.

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.

Let’s Proceed…

  1. Final project directory structure:

SOAP CXF Project Structure

2. Implementation class

file : BinaryAdditionServiceSOAPImpl. This is the implementation class of our web service interface. It has a method created from WSDL operation and all our processing logic will be in this method or will start from this method. The XML request payload is unmarshalled to BinaryAdditionRequest object and passed to the operation name method as an argument.

 


/**
 * 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.jws.soap.SOAPBinding;
import javax.xml.bind.annotation.XmlSeeAlso;

/**
 * This class was generated by Apache CXF 3.0.3 2016-06-09T21:50:03.647-05:00
 * Generated source version: 3.0.3
 
 */

@javax.jws.WebService(serviceName = "BinaryAdditionService", portName = "BinaryAdditionServiceSOAP", targetNamespace = "http://www.javanbeyond.com/BinaryAdditionService/", wsdlLocation = "classpath:BinaryAdditionService.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#binaryAdd(com
     * .javanbeyond.binaryadditionservice.BinaryAddRequest parameters )*
     */
    public com.javanbeyond.binaryadditionservice.BinaryAddResponse binaryAdd(
            BinaryAddRequest parameters) {
        LOG.info("Executing operation binaryAdd");
        System.out.println(parameters);
        try {
            // Create a Object Factory method for this package to create
            // equivalent java objects for this
            // namespace/package
            ObjectFactory objFactory = new ObjectFactory();
            BinaryAddResponse _return = objFactory.createBinaryAddResponse();
            _return.setOut(Integer
                    .toBinaryString(Integer.parseInt(parameters.getA()2)
                            + Integer.parseInt(parameters.getB()2)));
            return _return;
        catch (java.lang.Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

}

3. Spring configuration.

file : BinaryAdditionConfig.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 -->
    <jaxws:endpoint id="calculateEndpoint" implementor="#binaryCalculate" address="/BinaryCalculatorService"></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:BinaryAdditionConfig.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>

5.  Maven Dependencies

file : pom.xml. Maven unit of work to declare project dependencies, compile code and build war file for deployment in Tomcat. Comment the plugin part to prevent it from rebuilding and overriding our changes in Implementation class when we rebuild our code.

<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>QuickSOAPOverviewCXF</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>QuickSOAPOverviewCXF 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>QuickSOAPOverviewCXF</finalName>
        <plugins>
            <!--             Plugin to create equivalent java classes for the wsdl schema -->
            <!-- <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>                             where to create the java classes                             <sourceRoot>${basedir}/src/main/java</sourceRoot>                             <wsdlOptions>                                 <wsdlOption>                                     <wsdl>${basedir}/src/main/resources/BinaryAdditionService.wsdl</wsdl>                                     <wsdlLocation>classpath:BinaryAdditionService.wsdl</wsdlLocation>                                     <extraargs>                                         We want server side implementation classes                                         <extraarg>-impl</extraarg>                                         <extraarg>-verbose</extraarg>                                     </extraargs>                                 </wsdlOption>                             </wsdlOptions>                         </configuration>                         <goals>                             <goal>wsdl2java</goal>                         </goals>                     </execution>                 </executions>             </plugin> --></plugins>
    </build>
</project>

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/QuickSOAPOverviewCXF/soap/BinaryCalculatorService?wsdl”

SOAPUI Create Project

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

SOAPUI Request Create

4. Fill any binary input and press the send button. You should get a response of added binary numbers.

 

SOAP UI response

 

Create WSDL using Eclipse

In this tutorial, we will learn to create a simple WSDL using Eclipse. This WSDL portrays that it will take two binary numbers in request and provide their summation in response.

Technologies used –
a. Eclipse IDE for Java EE developer 4.5.0.20150621-1200 (Mars)
b. Preinstalled Maven with Eclipse Mars

Steps:

  1. Right click on the folder where you want to create WSDL and go to New > Other > Web Services > WSDL File

SOAPWSDLCreate

 

2. Click on Next and give a name to the WSDL. Then click Next. Change the target namespace value to your desired value. Leave other options as it is.

Target Namespace Choice

3. Click on Finish.

WSDL Design View

4. Change the address location of the Service (i.e. BinaryAdditionService) and operation name (i.e. NewOperation) to your choice.

tnsOperationName Change

 

5.  Double click on the rightmost arrow across input. A new tab should appear beside WSDL design screen.

RequestMessage Screen

6. If you want, change the request message (i.e. binaryAdd) name.

WSDL Request Message Name change

7. Change the request message parameter name (i.e. in) in binaryAddType. Right  click on request message parameter and add a parameter above or below the current parameter. Additionally, you can also change the type of the input parameter(s).

Add parameters

8.  After modifying and adding parameters, save the changes.

WSDL Modified operation parameters

9 . In the above case, we added the type of “a” as string, which is a predefined type in schema. If you want to add custom type, you should right click on the parameter and select “Set Type” and click on “New …”.

WSDL Complex Type

10. Once you click ok and double click on “binaryAddRequestType”, you should see the newly created type separated. Right clicking on it will give you tons of different options to proceed further.

WSDL-CustomTypeElement

11. If you want to add more operations, go back to the WSDL design view and right click on the operation and click on “Add Operation” and repeat the above steps.

WSDL add more operations

 

12. If the directions are followed properly, a sample WSDL as below will be created.

 

<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="binaryAddRequest">
                <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="binaryAddResponse">
                <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:binaryAddRequest" name="parameters"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="binaryAddResponse">
        <wsdl:part element="tns:binaryAddResponse" name="parameters"></wsdl:part>
    </wsdl:message>
    <wsdl:portType name="BinaryAdditionService">
        <wsdl:operation name="binaryAdd">
            <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="binaryAdd">
            <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>

 

Back to Top