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

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

Example Scenario:

We need to build a web service based on SOAP which takes two binary numbers as request and send us the added sum as response.


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. Metro 2.3
e. Java 1.8

Jars Used –

webservices-rt-2.3.jar
webservices-api-2.3.jar
javax.annotation-api-1.2-b03.jar
servlet-api-2.5.jar

Before we begin:

The below image depicts 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 for this tutorial.

–    Eclipse project folder structure (at the beginning):

SOAPOverviewMetroMavenWeb

–    Maven configuration (Initial)

file : pom.xml. The below pom.xml of Maven shows the dependencies of this web service and the plugin (jaxws-maven-plugin) needed to build our classes from WSDL.

<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>QuickOverviewMetro</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>QuickOverviewMetro 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.glassfish.metro</groupId>
            <artifactId>webservices-rt</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>QuickSOAPOverviewMetro</finalName>
        <plugins>
            <plugin>
                <groupId>org.jvnet.jax-ws-commons</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>wsimport</goal>
                        </goals>
                        <configuration>
                            <wsdlDirectory>src/main/resources/wsdl</wsdlDirectory>
                            <genJWS>true</genJWS>
                            <wsdlFiles>
                                <wsdlFile>BinaryAdditionService.wsdl</wsdlFile>
                            </wsdlFiles>
                            <wsdlLocation>WEB-INF/wsdl</wsdlLocation>
                            <sourceDestDir>src/main/java</sourceDestDir>
                            <vmArgs>
                                <vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
                            </vmArgs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>org.jvnet.jax-ws-commons</groupId>
                                        <artifactId>jaxws-maven-plugin</artifactId>
                                        <versionRange>[2.3,)</versionRange>
                                        <goals>
                                            <goal>wsimport</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

– WSDL and class mapping

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

Please run maven clean and install and you should see the java classes in the source folder created from WSDL.

WSDLClassesMapping

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 wsimport tool of Metro. Each package has one package-info.java file. In this example, we have used maven plugin of wsimport to build classes. Alternatively, you can use the wsimport executable in your $JAVA_HOME/bin directory for the same purpose.

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.

BinaryAdditionService_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…

Project artifacts:

1. Final project directory structure:

MetroProjectStructure

 

2. Implementation class

file : BinaryAdditionService_BinaryAdditionServiceSOAPImpl.java. 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.

 

package com.javanbeyond.binaryadditionservice;

import javax.jws.WebService;
import javax.xml.ws.BindingType;

/**
 * This class was generated by the JAX-WS RI. JAX-WS RI 2.2.8 Generated source
 * version: 2.2
 
 */
@WebService(portName = "BinaryAdditionServiceSOAP", serviceName = "BinaryAdditionService", targetNamespace = "http://www.javanbeyond.com/BinaryAdditionService/", wsdlLocation = "WEB-INF/wsdl", endpointInterface = "com.javanbeyond.binaryadditionservice.BinaryAdditionService")
@BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
public class BinaryAdditionService_BinaryAdditionServiceSOAPImpl
        implements BinaryAdditionService {

    public BinaryAdditionService_BinaryAdditionServiceSOAPImpl() {
    }

    /**
     
     @param parameters
     @return returns com.javanbeyond.binaryadditionservice.BinaryAddResponse
     */
    public BinaryAddResponse binaryAdd(BinaryAddRequest parameters) {

        try {
            // Create an 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. Sun JAX-RS runtime configuration

file: sun-jaxws.xml. This file is used for web service configuration in Metro. All our endpoints with their url pattern, implementation class and WSDL location is declared in this file. In our case, we have only one endpoint.

<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
    <endpoint name="soapMetro" implementation="com.javanbeyond.binaryadditionservice.BinaryAdditionService_BinaryAdditionServiceSOAPImpl" url-pattern="/BinaryAdditionService" wsdl="WEB-INF/classes/wsdl/BinaryAdditionService.wsdl"></endpoint>
</endpoints>

4. Deployment Descriptor

file:web.xml. Deployment descriptor file for mapping URIs to Metro servlet. A listener class is also declared for receiving notification events about ServletContext lifecycle changes.

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>soap</servlet-name>
        <display-name>MetroLibraryService</display-name>
        <description>Endpoint for Metro Library Service</description>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>soap</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
</web-app>

 

5. Maven dependencies (Final) and plugin disabled

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>QuickOverviewMetro</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>QuickOverviewMetro 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.glassfish.metro</groupId>
            <artifactId>webservices-rt</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>QuickSOAPOverviewMetro</finalName>
        <!-- <plugins> <plugin> <groupId>org.jvnet.jax-ws-commons</groupId> <artifactId>jaxws-maven-plugin</artifactId> <version>2.3</version> <executions> <execution> <goals> <goal>wsimport</goal> </goals> <configuration> <wsdlDirectory>src/main/resources/wsdl</wsdlDirectory> <genJWS>true</genJWS> <wsdlFiles> <wsdlFile>BinaryAdditionService.wsdl</wsdlFile> </wsdlFiles> <wsdlLocation>WEB-INF/wsdl</wsdlLocation> <sourceDestDir>src/main/java</sourceDestDir> <vmArgs> <vmArg>-Djavax.xml.accessExternalSchema=all</vmArg> </vmArgs> </configuration> </execution> </executions> </plugin> </plugins>-->
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>org.jvnet.jax-ws-commons</groupId>
                                        <artifactId>jaxws-maven-plugin</artifactId>
                                        <versionRange>[2.3,)</versionRange>
                                        <goals>
                                            <goal>wsimport</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </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/QuickSOAPOverviewMetro/BinaryAdditionService?wsdl”

SOAPUI Project Metro

 

3. Once SOAPUI creates a sample request for the service, fill in the details in the request and hit the service with two binary numbers. You will get a binary addition in the response.

SOAPUIMetroRequestResponse

 

 

 

Leave a Reply

Back to Top
%d bloggers like this: