Tuesday Aug 06

Key Concepts

Web Services Java Tutorial

Sébastien Dante Ursini
PDFPrintE-mail
Thursday, 28 July 2011 13:56
Written by Sébastien Dante Ursini
AddThis Social Bookmark Button

Web Services in Java using Maven

Creating your first Web Service is incredibly easy. In fact, by using Maven you can have your first service up and running in minutes with few coding.We present a step-by-step walkthrough of building and deploying a Web service that performs a reverse string manipulation and return the result.

In this tutorial the following topics will be covered :

Step 1 : Create the server project

In this step we will create a project called wsServer (Web Service Server) using Maven.  The pom file below define the required dependencies and the project structure.

Web service server project maven pom

<?xml version="1.0"?>
<project
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
    xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ubiteck</groupId>
    <artifactId>wsClient</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.1.4</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>1.10</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>wsgen</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!-- Generation -->
                    <sei>com.ubiteck.ws.server.MyServiceImpl</sei>
                </configuration>
                <!-- if you want to use a specific version of JAX-WS, -->
                                <!-- you can do so like this -->
                <dependencies>
                    <dependency>
                        <groupId>com.sun.xml.ws</groupId>
                        <artifactId>jaxws-tools</artifactId>
                        <version>2.1.4</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

In our tutorial we will use the reference implementation of the Java API for XML Web Services (JAX-WS) specification and the corresponding JAX-WS Maven plugin.

This plugin contains Maven adapter for JAX-WS's toolset. The original version of this was developed in the codehaus mojo project, but as of March 2007, the project is moved to jax-ws-commons.

JAX-WS supports the following standards

  • JAX-WS 2.0/2.1/2.2 (JSR 224)
  • WS-I Basic Profile 1.2 and 2.0
  • WS-I Attachments Profile 1.0
  • WS-I Simple SOAP Binding Profile 1.0
  • WS-Addressing 1.0 - Core, SOAP Binding, WSDL Binding

In our pom we have configured the Maven plugin to reads a service endpoint implementation class (com.ubiteck.ws.server.MyServiceImpl) and generates all of the portable artifacts for a JAX-WS web service. The <sei> argument in the plugin indicate  the service endpoint implementation class name.

If you are using eclipse you can generate the eclipse project setting files by using the following Maven command : 

maven web service project eclipse project creation

mvn eclipse:eclipse

Step 2 : Create the Web service

We will now declare the SEI. A service endpoint interface (SEI) is a Java interface that declares the methods that a client can invoke on the service.


Spring java source

package com.ubiteck.ws.server;
import javax.jws.WebMethod;
import javax.jws.WebService;
/**
 * Web Service example  
 * 
 * @author sursini
 */
@WebService
public interface MyService {
    @WebMethod
    String reverse(String value);
}

We have one unique method called reverse. As explained it returns a revesed string according to the value provided. The reverse method is tagged with the a @WebMethod annotation to mark the method as exposed as a Web Service operation.

The next source code is the implementation of the SEI.  The @WebService annotation is used to define the endpointInterface (The complete name of the service endpoint interface defining the service's abstract Web Service contract.) 

Spring java source

package com.ubiteck.ws.server;

import javax.jws.WebService;
@WebService(endpointInterface = "com.ubiteck.ws.server.MyService")
public class MyServiceImpl implements MyService {
    @Override
    public String reverse(String value) {
        if (value == null) return null;
        return new StringBuffer(value).reverse().toString();
    }
}



Step 3 : Publish the web service

Now i want to have the WebService exposed when I just run the main method of the following class (Publisher). That is where the EndPoint class comes in:

Webservice endpoint publish class example

package com.ubiteck.ws.server;
 import javax.xml.ws.Endpoint;
public class Publisher {
    public static void main(String[] args) {
    Endpoint.publish("http://localhost:8080/WS/MyService",new MyServiceImpl());
    }
}

The Endpoint publish static method specify the URL on which the WebService should be available and pass the class-with-WebService annotation to handle the calls received at that URL.

If you run execute the class and type the url in your favorite browser you should see the following page :

Web Services

No JAX-WS context information available.

JAX-WS RI Endpoint.publish API uses by default a light-weight HTTP server implementation that is included in Sun's Java SE 6. So no, it does not use an embedded GlassFish nor an embedded Tomcat and even less your existing Tomcat install: it uses an embedded container i.e. something running inside the same JVM. Just FYI, it is however possible to plug other implementations as long as they provide aService Provider Implementation (SPI). For example, Jetty 6 does so, see J2se6HttpServerSPI

To obtain the wsdl content type the same url with ?wsdl at the end : http://localhost:8080/WS/MyService?wsdl

Web Service diagram

The result should look like :

<?xml version="1.0" encoding="UTF-8"?>
<definitions 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://server.ws.ubiteck.com/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    targetNamespace="http://server.ws.ubiteck.com/" 
    name="MyServiceImplService"> 

   <types> 
      <xsd:schema> 
         <xsd:import namespace="http://server.ws.ubiteck.com/" schemaLocation="http://localhost:8080/WS/MyService?xsd=1"></xsd:import> 
      </xsd:schema> 
   </types> 

   <message name="reverse"> 
      <part name="parameters" element="tns:reverse"></part> 
   </message> 

   <message name="reverseResponse"> 
      <part name="parameters" element="tns:reverseResponse"></part> 
   </message> 

   <portType name="MyService"> 
      <operation name="reverse"> 
         <input message="tns:reverse"></input> 
         <output message="tns:reverseResponse"></output> 
      </operation> 
   </portType> 

   <binding name="MyServiceImplPortBinding" type="tns:MyService"> 
      <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding> 
      <operation name="reverse"> 
         <soap:operation soapAction=""></soap:operation> 
         <input> 
            <soap:body use="literal"></soap:body> 
         </input> 
         <output> 
            <soap:body use="literal"></soap:body> 
         </output> 
      </operation> 
   </binding> 

   <service name="MyServiceImplService"> 
      <port name="MyServiceImplPort" binding="tns:MyServiceImplPortBinding"> 
         <soap:address location="http://localhost:8080/WS/MyService"></soap:address> 
      </port> 
   </service> 
</definitions>

The XSD could be accessed using http://localhost:8080/WS/MyService?xsd=1

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://server.ws.ubiteck.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://server.ws.ubiteck.com/"> 
 
   <xs:element name="reverse" type="tns:reverse"></xs:element> 
 
   <xs:element name="reverseResponse" type="tns:reverseResponse"></xs:element> 
 
   <xs:complexType name="reverse"> 
      <xs:sequence> 
         <xs:element name="arg0" type="xs:string" minOccurs="0"></xs:element> 
      </xs:sequence> 
   </xs:complexType> 
 
   <xs:complexType name="reverseResponse"> 
      <xs:sequence> 
         <xs:element name="return" type="xs:string" minOccurs="0"></xs:element> 
      </xs:sequence> 
   </xs:complexType> 

</xs:schema>

Step 4 : Create client side project

We have now a running Web Service, we can call the Web Service using the browser we are ready to develop a client application in Java. To do that we will parse and the wsdl file and generate java code needed to to access our Web Service. To do so we will use the jaxws maven plugin.

Below the Maven project object model : 

Web service client project Maven pom

<?xml version="1.0"?>
<project
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
    xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ubiteck</groupId>
    <artifactId>sample</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.1.4</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>1.10</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>wsimport</goal>
                        </goals>
                    </execution>
                </executions>
                <!-- -->
                <configuration>
                    <wsdlUrls>
                        <wsdlUrl>http://localhost:8080/WS/MyService?wsdl</wsdlUrl>
                    </wsdlUrls>
                    <sourceDestDir>${project.build.directory}/generated</sourceDestDir>
                    <verbose>true</verbose>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${project.build.directory}/generated</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Step 5 : Import the wsdl and binding file

In the pom we have defined a wsimport goal using the jaxws-maven-plugin to import and generate the java code according to the wsdl found at http://localhost:8080/WS/MyService?wsdl and defined using the plugin argument. The generated java code is stored in the Maven target folder under generated according to the <sourceDestDir> parameter. 

The result of the wsimport should display the following information

Maven wsimport result

[INFO] Processing: http://localhost:8080/WS/MyService?wsdl
[DEBUG] The binding Directory is C:\var\workspaces\wsClient\src\jaxws
[DEBUG] jaxws:wsimport args: [-s, C:\var\workspaces\wsClient\target\generated, -d, C:\var\workspaces\wsClient\target\classes, -verbose]
[INFO] jaxws:wsimport args: [-s, C:\var\workspaces\wsClient\target\generated, -d, C:\var\workspaces\wsClient\target\classes, -verbose, http://localhost:8080/WS/MyService?wsdl]
parsing WSDL...


generating code...

com\ubiteck\ws\server\MyService.java
com\ubiteck\ws\server\MyServiceImplService.java
com\ubiteck\ws\server\ObjectFactory.java
com\ubiteck\ws\server\Reverse.java
com\ubiteck\ws\server\ReverseResponse.java
com\ubiteck\ws\server\package-info.java

compiling code...

So we have 6 java files generated 

ClassPurpose

MyService

Service Endpoint interface

MyServiceImplService

Used only by JAX-WS clients

ObjectFactory

JAXB XML Registry

Reverse Wrapper bean for request message
ReverseResponse Wrapper bean for response message
Package-info

Holder for JAXB package annotations

To use the generated code in our Eclipse project we are using the build-helper-maven-plugin to add the generated code in our source folders. 

Step 6 : Create the Web service client class

To ensure we have the java source generated as a source folder in our Eclipse project we will cleanup and recreate our Eclipse project settings file using the following maven command

Maven command to recreate eclipse project settings files

mvn eclipse:clean eclipse:eclipse

We have now access to the jax-ws client class then we can create our web service client class : 

Spring java source

package com.ubiteck.ws.client;

import com.ubiteck.ws.server.MyService;
import com.ubiteck.ws.server.MyServiceImplService;

public class MyServiceClient {
    public static void main(String[] args){
    MyServiceImplService serviceImpl = new MyServiceImplService();
    MyService service = serviceImpl.getMyServiceImplPort(); 
    System.out.println(service.reverse("123456"));
    }
}

In our class we are instantiating the MyServiceImplService class to obtain an instance of our service Endpoint interface by calling getMyServiceImplPort method. 

Step 7 : Run the web service client application

The client application is configured we can call our service : 

service.reverse("123456")

That are all the steps for publishing and using a WebService in plain old Java application.

If you enjoyed this tutorial and want to promote it don't hesitate to click on 


Tags: project, artifactid, http, class, version, create, client, name=, service, reverse
Sébastien Dante Ursini

Sébastien Dante Ursini

Java/Finance Specialist 
17 Years of experience in Java
22 Year in Banking/Finance
Based in Geneva/Switzerland

Java Tutorial on Facebook