Versions Compared

Key

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

Table of Contents

Developing a Service using JAX-WS

...

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";
  }
}

...

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);
}

...

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="StockQuotePort",
   serviceName="StockQuoteReporter",
)
public class StockQuoteReporter implements QuoteReporter
{
  public Quote getQuote(String ticker)
  {
  ...
  }
}

...

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);
}

...

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
  );
}

...

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>