Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Developing a Service using JAX-WS

...

  • Start with a WSDL contract and generate Java objects to implement the service.
  • Start with a Java object and service enable it using annotations.

For new development the preferred path is to design your services in WSDL and then generate the code to implement them. This approach enforces the concept that a service is an abstract entity that is implementation neutral. It also means you can spend more time working out the exact interface your service requires before you start coding.

However, there are many cases where you may need to service enable an existing application. While JAX-WS eases the process, it does require that you make some changes to source code of your application. You will need to add annotations to the source. It also requires that you migrate your code to Java 5.0.

...

Code Block
titleImplementation of the Greeter Service

package demo.hw.server;

import org.apache.hello_world_soap_http.Greeter;

@javax.jws.WebService(portName = "SoapPort", serviceName = "SOAPService",
 targetNamespace = "http://apache.org/hello_world_soap_http",
 endpointInterface = "org.apache.hello_world_soap_http.Greeter")

public class GreeterImpl implements Greeter {

  public String greetMe(String me)
  {
        System.out.println("Executing operation greetMe");
        System.out.println("Message received: " + me + "\n");
        return "Hello " + me;
     }

  public String sayHi()
  {
        System.out.println("Executing operation sayHi\n");
        return "Bonjour";
     }
}

Java First Development

To create a service starting from Java you need to do the following:

  1. Create a Service Endpoint Interface (SEI) that defines the methods you wish to expose as a service.

    Tip
    titleTip

    You can work directly from a Java class, but working from an interface is the recommended approach. Interfaces are better for sharing with the developers who will be responsible for developing the applications consuming your service. The interface is smaller and does not provide any of the service's implementation details.

  2. Add the required annotations to your code.
  3. Generate the WSDL contract for your service.

    Tip
    titleTip

    If you intend to use the SEI as the service's contract, it is not necessary to generate a WSDL contract

  4. Publish the service.

...

The service endpoint interface (SEI) is the piece of Java code that is shared between a service and the consumers that make requests on it. When starting with a WSDL contract, the SEI is generated by the code generators. However, when starting from Java, it is the up to a the developer to create the SEI.

There are two basic patterns for creating an SEI:

  • Green field development
    You are developing a new service from the ground up. When starting fresh, it is best to start by creating the SEI first. You can then distribute the SEI to any developers that are responsible for implementing the services and consumers that use the SEI.

    Note
    titleNote

    The recommended way to do green field service development is to start by creating a WSDL contract that defines the service and its interfaces.

  • Service enablement
    In this pattern, you typically have an existing set of functionality that is implemented as a Java class and you want to service enable it. This means that you will need to do two things:
    1. Create an SEI that contains only the operations that are going to be exposed as part of the service.
    2. Modify the existing Java class so that it implements the SEI.

      Note
      titleNote

      You can add the JAX-WS annotations to a Java class, but that is not recommended.

...

Code Block
titleSimple SEI

package org.apache.cxf;

public interface QuoteReporter
{
  public Quote getQuote(String ticker);
}

...

Code Block
titleImplementation for SEI

package org.apache.cxf;

import java.util.*;

public class StockQuoteReporter implements QuoteReporter
{
  ...
  public Quote getQuote(String ticker)
  {
    Quote retVal = new Quote();
    retVal.setID(ticker);
    retVal.setVal(Board.check(ticker));[1]
    Date retDate = new Date();
    retVal.setTime(retDate.toString());
    return( retVal);
  }
}

Annotating the Code

JAX-WS relies on the annotation feature of Java 5. The JAX-WS annotations are used to specify the metadata used to map the SEI to a fully specified service definition. Among the information provided in the annotations are the following:

  • The target namespace for the service.
  • The name of the class used to hold the request message.
  • The name of the class used to hold the response message.
  • If an operation is a one way operation.
  • The binding style the service uses.
  • The name of the class used for any custom exceptions.
  • The namespaces under which the types used by the service are defined.

    Tip
    titleTip

    Most of the annotations have sensible defaults and do not need to be specified. However, the more information you provide in the annotations, the better defined your service definition. A solid service definition increases the likely hood that all parts of a distributed application will work together.

...

Code Block
titleInterface with the @WebService Annotation

package com.mycompany.demo;

import javax.jws.*;

@WebService(name="quoteUpdater",
            targetNamespace="http://cxf.apache.org",
            wsdlLocation="http://somewhere.com/quoteExampleService?wsdl")
public interface QuoteReporter
{
  public Quote getQuote(@WebParam(name="ticker") String ticker);
}

...

  1. Specifies that the value of the name attribute of the wsdl:portType element defining the service interface is quoteUpdater.
  2. Specifies that the target namespace of the service is http://cxf.apache.orgImage Removed.
  3. Specifies that the service will use the pre-defined WSDL contract which is published at http://somewhere.com/quoteExampleService?wsdlImage Removed.

The @WebParam annotation is necessary as java interfaces do not store the Parameter name in the .class file. So if you leave out the annotation your parameter will be named arg0.

...

Code Block
titleAnnotated Service Implementation Class

package org.apache.cxf;

import javax.jws.*;

@WebService(endpointInterface="org.apache.cxf.quoteReporter",
            targetNamespace="http://cxf.apache.org",
            portName="portName="StockQuotePort",
            serviceName="StockQuoteReporter",
            )
public class StockQuoteReporter implements QuoteReporter
{
  public Quote getQuote(String ticker)
  {
  ...
  }
}

...

Tip
titleTip

The more details you provide in the SEI, the SEIthe easier it will be for developers to implement applications that can use the functionality it defines. It will also provide for better generated WSDL contracts.

...

Code Block
titleSpecifying an RPC/LITERAL SOAP Binding

package org.eric.demo;

import javax.jws.*;
import javax.jws.soap.*;
import javax.jws.soap.SOAPBinding.*;

@WebService(name="quoteReporter")
@SOAPBinding(style=Style.RPC, use=Use.LITERAL)
public interface QuoteReporter
{
  ...
}

...

Code Block
titleSEI with Annotated Methods

package org.apache.cxf;

import javax.jws.*;
import javax.xml.ws.*;

@WebService(name="quoteReporter")
public interface QuoteReporter
{
  @WebMethod(operationName="getStockQuote")
  @RequestWrapper(targetNamespace="http://demo.mycompany.com/types",
                  className="java.lang.String")
  @ResponseWrapper(targetNamespace="http://demo.mycompany.com/types",
                   className="org.eric.demo.Quote")
  public Quote getQuote(String ticker);
}

...

The method parameters in the SEI coresspond correspond to the wsdl:message elements and their wsdl:part elements. JAX-WS provides annotations that allow you to describe the wsdl:part elements that are generated for the method parameters.

...

Property

Values

Description

name

 

Specifies the name of the parameter as it appears in the WSDL. For RPC bindings, this is name of the wsdl:part representing the parameter. For document bindings, this is the local name of the XML element representing the parameter. Per the JAX-WS specification, the default is argN, where N is replaced with the zero-based argument index (i.e., arg0, arg1, etc.)

targetNamespace

 

Specifies the namespace for the parameter. It is only used with document bindings where the parameter maps to an XML element. The defaults default is to use the service's namespace.

mode

Mode.IN (default)
Mode.OUT
Mode.INOUT

Specifies the direction of the parameter.

header

false (default)
true

Specifies if the parameter is passed as part of the SOAP header.

partName

 

Specifies the value of the name attribute of the wsdl:part element for the parameter when the binding is document.

...

Code Block
titleFully Annotated SEI

package org.apache.cxf;

import javax.jws.*;
import javax.xml.ws.*;
import javax.jws.soap.*;
import javax.jws.soap.SOAPBinding.*;
import javax.jws.WebParam.*;

@WebService(name="quoteReporter")
@SOAPBinding(style=Style.RPC, use=Use.LITERAL)
public interface QuoteReporter
{
  @WebMethod(operationName="getStockQuote")
  @RequestWrapper(targetNamespace="http://demo.mycompany.com/types",
                  className="java.lang.String")
  @ResponseWrapper(targetNamespace="http://demo.mycompany.com/types",
                   className="org.eric.demo.Quote")
  @WebResult(targetNamespace="http://demo.mycompany.com/types",
             name="updatedQuote")
  public Quote getQuote(
                        @WebParam(targetNamespace="http://demo.mycompany.com/types",
                                  name="stockTicker",
                                  mode=Mode.IN)
                        String ticker
  );
}

Generating WSDL

...

Code Block
titleGenerated WSDL from an SEI

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://demo.eric.org/"
                  xmlns:tns="http://demo.eric.org/"
		    xmlns:ns1=""
		    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		    xmlns:ns2="http://demo.eric.org/types"
		    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
		    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <xsd:schema>
      <xs:complexType name="quote">
        <xs:sequence>
          <xs:element name="ID" type="xs:string" minOccurs="0"/>
          <xs:element name="time" type="xs:string" minOccurs="0"/>
          <xs:element name="val" type="xs:float"/>
        </xs:sequence>
      </xs:complexType>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="getStockQuote">
    <wsdl:part name="stockTicker" type="xsd:string">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getStockQuoteResponse">
    <wsdl:part name="updatedQuote" type="tns:quote">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="quoteReporter">
    <wsdl:operation name="getStockQuote">
      <wsdl:input name="getQuote" message="tns:getStockQuote">
    </wsdl:input>
      <wsdl:output name="getQuoteResponse" message="tns:getStockQuoteResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="quoteReporterBinding" type="tns:quoteReporter">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getStockQuote">
      <soap:operation style="rpc"/>
      <wsdl:input name="getQuote">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="getQuoteResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="quoteReporterService">
    <wsdl:port name="quoteReporterPort" binding="tns:quoteReporterBinding">
      <soap:address location="http://localhost:9000/quoteReporterService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>