JAX-WS Service Development Options - 6.3

Talend ESB Service Developer Guide

EnrichVersion
6.3
EnrichProdName
Talend Data Fabric
Talend Data Services Platform
Talend ESB
Talend MDM Platform
Talend Open Studio for ESB
Talend Real-Time Big Data Platform
task
Design and Development
Installation and Upgrade
EnrichPlatform
Talend ESB

JAX-WS Annotated Services from Java

The JAX-WS APIs include a set of annotations which allow you to build services using annotated classes. These services are based on a single class which contains a set of operations.

Here's a simple example:

@WebService
public class Hello {
   public String sayHi(String name) {
      return "Hello " + name;
   }
}

JAX-WS includes many more annotations as well such as:

  • @WebMethod - allows you to customize the operation name, exclude the operation from inclusion in the service, etc

  • @WebParam - allows you to customize a parameter's name, namespace, direction (IN or OUT), etc

  • @WebResult - allows you to customize the return value of the web service call

Data is marshalled from XML to Java and vice versa via the JAXB data-binding.

Services are publish via one of two means:

  • The JAX-WS standard Endpoint APIs

  • CXF's XML configuration format - i.e. <jaxws:endpoint ... />

JAX-WS Annotated Services from WSDL

If you have existing WSDLs for your service or wish to write your WSDL first and then generate classes, CXF has many tools to help you do this.

The WSDL2Java tool will generate a JAX-WS annotated service and server stub from your WSDL. You can run it one of three ways:

  • The command line

  • The Maven plugin

  • With the WSDL2Java API

Note that CXF generally restricts WSDL support to WSI-BP, not the full WSDL 1.1 specification.

Developing a Service using JAX-WS

You can develop a service using one of two approaches:

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

WSDL First Development

Using the WSDL first model of service development, you start with a WSDL document that defines the service you wish to implement. This WSDL document could be obtained from another developer, a system architect, a UDDI registry, or you could write it yourself. The document must contain at least a fully specified logical interface before you can begin generating code from it.

Once you have a WSDL document, the process for developing a JAX-WS service is three steps:

  1. Generate starting point code.

  2. Implement the service's operations.

  3. Publish the implemented service.

Generating the Starting Point Code

JAX-WS specifies a detailed mapping from a service defined in WSDL to the Java classes that will implement that service. The logical interface, defined by the wsdl:portType element, is mapped to a service endpoint interface (SEI). Any complex types defined in the WSDL are mapped into Java classes following the mapping defined by the Java Architecture for XML Binding (JAXB) specification. The endpoint defined by the wsdl:service element is also generated into a Java class that is used by consumers to access endpoints implementing the service.

The wsdl2java command automates the generation of this code. It also provides options for generating starting point code for your implementation and an ant based makefile to build the application. wsdl2java provides a number of arguments for controlling the generated code.

Running wsdl2java

You can generate the code needed to develop your service using the following command: wsdl2java -ant -impl -server -d outputDir myService.wsdl

The command does the following:

  • The -ant argument generates a Ant makefile, called build.xml , for your application.

  • The -impl argument generates a shell implementation class for each portType element in the WSDL document.

  • The -server argument generates a simple main() to launch your service as a stand alone application.

  • The -d outputDir argument tells wsdl2java to write the generated code to a directory called outputDir.

  • myService.wsdl is the WSDL document from which code is generated.

Generated code

Table1 describes the files generated for creating a service.

Table 1: Generated Classes for a Service

File

Description

portTypeName.java

The SEI. This file contains the interface your service implements. You should not edit this file.

serviceName.java

The endpoint. This file contains the Java class your clients will use to make requests on the service.

portTypeNameImpl.java

The skeleton implementation class. You will modify this file to implement your service.

portTypeName_portTypeName... ImplPort_Server.java

A basic server main() that allows you to deploy your service as a stand alone process.

Implementing the Service

Once the starting point code is generated, you must provide the business logic for each of the operations defined in the service's interface.

Generating the implementation code

You generate the implementation class for your service with wsdl2java 's -impl flag.

Note

If your service's contract included any custom types defined in XML Schema, you will also need to ensure that the classes for the types are also generated and available.

Generated code

The service implementation code consists of two files:

  • portTypeName.java is the service interface(SEI) for the service.

  • portTypeNameImpl.java is the class you will use to implement the operations defined for the service.

Implement the operation's logic

You provide the business logic for your service's operations by completing the stub methods in portTypeNameImpl.java . For the most part, you use standard Java to implement the business logic. If your service uses custom XML Schema types, you will need to use the generated classes for each type to manipulate them. There are also some CXF specific APIs that you can use to access some advanced features.

Example

For example, an implementation class for a service that defined the operations sayHi and greetMe may look like the below example.

Example 1. Implementation 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.

    Note

    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.

    Note

    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.

Creating the SEI

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

    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

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

Writing the interface

The SEI is a standard Java interface. It defines a set of methods that a class will implement. It can also define a number of member fields and constants to which the implementing class has access.

In the case of an SEI the methods defined are intended to be mapped to operations exposed by a service. The SEI corresponds to a wsdl:portType element. The methods defined by the SEI correspond to wsdl:operation elements in the wsdl:portType element.

Note

JAX-WS defines an annotation that allows you to specify methods that are not exposed as part of a service. However, the best practice is to leave such methods out of the SEI.

The below shows a simple SEI for a stock updating service.

Example 2. Simple SEI

package org.apache.cxf;

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

Implementing the interface

Because the SEI is a standard Java interface, the class that implements it is just a standard Java class. If you started with a Java class you will need to modify it to implement the interface. If you are starting fresh, the implementation class will need to implement the SEI.

The below shows a class for implementing the above interface. .

Example 3. Implementation 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.

    Note

    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.

Required Annotations

In order to create a service from Java code you are only required to add one annotation to your code. You must add the @WebService() annotation on both the SEI and the implementation class.

The @WebService annotation

The @WebService annotation is defined by the javax.jws.WebService interface and it is placed on an interface or a class that is intended to be used as a service. @WebService has the following properties:

Property

Description

name

Specifies the name of the service interface. This property is mapped to the name attribute of the wsdl:portType element that defines the service's interface in a WSDL contract. The default is to append PortType to the name of the implementation class.

targetNamespace

Specifies the target namespace under which the service is defined. If this property is not specified, the target namespace is derived from the package name.

serviceName

Specifies the name of the published service. This property is mapped to the name attribute of the wsdl:service element that defines the published service. The default is to use the name of the service's implementation class. Note: Not allowed on the SEI

wsdlLocation

Specifies the URI at which the service's WSDL contract is stored. The default is the URI at which the service is deployed.

endpointInterface

Specifies the full name of the SEI that the implementation class implements. This property is only used when the attribute is used on a service implementation class. Note: Not allowed on the SEI

portName

Specifies the name of the endpoint at which the service is published. This property is mapped to the name attribute of the wsdl:port element that specifies the endpoint details for a published service. The default is the append Port to the name of the service's implementation class. Note: Not allowed on the SEI

Note

You do not need to provide values for any of the @WebService annotation's properties. However, it is recommended that you provide as much information as you can.

Annotating the SEI

The SEI requires that you add the @WebService annotation. Since the SEI is the contract that defines the service, you should specify as much detail as you can about the service in the @WebService annotation's properties.

The below shows the interface defined in above with the @WebService annotation.

Example 4. Interface 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);
}

The @WebService annotation above does the following:

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

  3. Specifies that the service will use the pre-defined WSDL contract published at http://somewhere.com/quoteExampleService?wsdl.

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.

Annotating the service implementation

In addition to annotating the SEI with the @WebService annotation, you also have to annotate the service implementation class with the @WebService annotation. When adding the annotation to the service implementation class you only need to specify the endpointInterface property. As shown in the next example the property needs to be set to the full name of the SEI.

Example 5. Annotated 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) {
      ...
   }
}

Optional Annotations

While the @WebService annotation is sufficient for service enabling a Java interface or a Java class, it does not provide a lot of information about how the service will be exposed as an endpoint. The JAX-WS programming model uses a number of optional annotations for adding details about your service, such as the binding it uses, to the Java code. You add these annotations to the service's SEI.

Note

The more details you provide in 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.

Defining the Binding Properties with Annotations

If you are using a SOAP binding for your service, you can use JAX-WS annotations to specify a number of the bindings properties. These properties correspond directly to the properties you can specify in a service's WSDL contract.

The @SOAPBinding annotation

The @SOAPBinding annotation is defined by the javax.jws.soap.SOAPBinding interface. It provides details about the SOAP binding used by the service when it is deployed. If the @SOAPBinding annotation is not specified, a service is published using a wrapped doc/literal SOAP binding.

You can put the @SOAPBinding annotation on the SEI and any of the SEI's methods. When it is used on a method, setting of the method's @SOAPBinding annotation take precedent.

The following table shows the properties for the @SOAPBinding annotation.

Property

Values

Description

style

Style.DOCUMENT (default) Style.RPC

Specifies the style of the SOAP message. If RPC style is specified, each message part within the SOAP body is a parameter or return value and will appear inside a wrapper element within the soap:body element. The message parts within the wrapper element correspond to operation parameters and must appear in the same order as the parameters in the operation. If DOCUMENT style is specified, the contents of the SOAP body must be a valid XML document, but its form is not as tightly constrained.

use

Use.LITERAL (default) Use.ENCODED

Specifies how the data of the SOAP message is streamed.

parameterStyle

ParameterStyle.BARE ParameterStyle.WRAPPED (default)

Specifies how the method parameters, which correspond to message parts in a WSDL contract, are placed into the SOAP message body. A parameter style of BARE means that each parameter is placed into the message body as a child element of the message root. A parameter style of WRAPPED means that all of the input parameters are wrapped into a single element on a request message and that all of the output parameters are wrapped into a single element in the response message. If you set the style to RPC you must use the WRAPPED parameter style.

The below shows an SEI that uses rpc/literal SOAP messages.

Example 6. Specifying 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 {
   ...
}

Defining Operation Properties with Annotations

When the runtime maps your Java method definitions into XML operation definitions it fills in details such as:

  • what the exchanged messages look like in XML.

  • if the message can be optimized as a one way message.

  • the namespaces where the messages are defined.

The @WebMethod annotation

The @WebMethod annotation is defined by the javax.jws.WebMethod interface. It is placed on the methods in the SEI. The @WebMethod annotation provides the information that is normally represented in the wsdl:operation element describing the operation to which the method is associated.

The following table describes the properties of the @WebMethod annotation.

Property

Description

operationName

Specifies the value of the associated wsdl:operation element's name. The default value is the name of the method.

action

Specifies the value of the soapAction attribute of the soap:operation element generated for the method. The default value is an empty string.

exclude

Specifies if the method should be excluded from the service interface. The default is false .

The @RequestWrapper annotation

The @RequestWrapper annotation is defined by the javax.xml.ws.RequestWrapper interface. It is placed on the methods in the SEI. As the name implies, @RequestWrapper specifies the Java class that implements the wrapper bean for the method parameters that are included in the request message sent in a remote invocation. It is also used to specify the element names, and namespaces, used by the runtime when marshalling and unmarshalling the request messages.

The following table describes the properties of the @RequestWrapper annotation.

Property

Description

localName

Specifies the local name of the wrapper element in the XML representation of the request message. The default value is the name of the method or the value of the @WebMethod annotation's operationName property.

targetNamespace

Specifies the namespace under which the XML wrapper element is defined. The default value is the target namespace of the SEI.

className

Specifies the full name of the Java class that implements the wrapper element.

Note

Only the className property is required.

The @ResponseWrapper annotation

The @ResponseWrapper annotation is defined by the javax.xml.ws.ResponseWrapper interface. It is placed on the methods in the SEI. As the name implies, @ResponseWrapper specifies the Java class that implements the wrapper bean for the method parameters that are included in the response message sent in a remote invocation. It is also used to specify the element names, and namespaces, used by the runtime when marshalling and unmarshalling the response messages.

The following table describes the properties of the @ResponseWrapper annotation.

Property

Description

localName

Specifies the local name of the wrapper element in the XML representation of the response message. The default value is the name of the method with Response appended or the value of the @WebMethod annotation's operationName property with Response appended.

targetNamespace

Specifies the namespace under which the XML wrapper element is defined. The default value is the target namespace of the SEI.

className

Specifies the full name of the Java class that implements the wrapper element.

Note

Only the className property is required.

The @WebFault annotation

The @WebFault annotation is defined by the javax.xml.ws.WebFault interface. It is placed on exceptions that are thrown by your SEI. The @WebFault annotation is used to map the Java exception to a wsdl:fault element. This information is used to marshall the exceptions into a representation that can be processed by both the service and its consumers.

The following table describes the properties of the @WebFault annotation.

Property

Description

name

Specifies the local name of the fault element.

targetNamespace

Specifies the namespace under which the fault element is defined. The default value is the target namespace of the SEI.

faultName

Specifies the full name of the Java class that implements the exception.

Important

The name property is required.

The @Oneway annotation

The @Oneway annotation is defined by the javax.jws.Oneway interface. It is placed on the methods in the SEI that will not require a response from the service. The @Oneway annotation tells the run time that it can optimize the execution of the method by not waiting for a response and not reserving any resources to process a response.

Example

The next example shows an SEI whose methods are annotated.

Example 7. SEI 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);
}

Defining Parameter Properties with Annotations

The method parameters in the SEI coresspond 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.

The @WebParam annotation

The @WebParam annotation is defined by the javax.jws.WebParam interface. It is placed on the parameters on the methods defined in the SEI. The @WebParam annotation allows you to specify the direction of the parameter, if the parameter will be placed in the SOAP header, and other properties of the generated wsdl:part .

The following table describes the properties of the @WebParam annotation.

Property

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 is to use the service's namespace.

mode

Specifies the direction of the parameter: Mode.IN (default), Mode.OUT, Mode.INOUT

header

Specifies if the parameter is passed as part of the SOAP header. Values of true or false (default).

partName

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

The @WebResult annotation

The @WebResult annotation is defined by the javax.jws.WebResult interface. It is placed on the methods defined in the SEI. The @WebResult annotation allows you to specify the properties of the generated wsdl:part that is generated for the method's return value.

The following table describes the properties of the @WebResult annotation.

Property

Description

name

Specifies the name of the return value as it appears in the WSDL. For RPC bindings, this is name of the wsdl:part representing the return value. For document bindings, this is the local name of the XML element representing the return value. The default value is return.

targetNamespace

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

header

Specifies if the return value is passed as part of the SOAP header.

partName

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

Example

This example shows an SEI that is fully annotated.

Example 8. Fully 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

Once you have annotated your code, you can generate a WSDL contract for your service using the java2wsdl command.

Generated WSDL from an SEI

The below example shows the WSDL contract generated for the SEI shown above.

<?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>

JAX-WS Configuration

The following sections list JAX-WS specific configuration items.

Configuring an Endpoint

A JAX-WS Endpoint can be configured in XML in addition to using the JAX-WS APIs. Once you've created your server implementation , you simply need to provide the class name and an address. Here is a simple example:

<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-2.0.xsd
      http://cxf.apache.org/jaxws
      http://cxf.apache.org/schemas/jaxws.xsd">

<jaxws:endpoint id="classImpl"
   implementor="org.apache.cxf.jaxws.service.Hello"
   endpointName="e:HelloEndpointCustomized"
   serviceName="s:HelloServiceCustomized"
   address="http://localhost:8080/test"
   xmlns:e="http://service.jaxws.cxf.apache.org/endpoint"
   xmlns:s="http://service.jaxws.cxf.apache.org/service"/>

</beans>

Be sure to include the JAX-WS schemaLocation attribute specified on the root beans element. This allows CXF to validate the file and is required. Also note the namespace declarations at the end of the <jaxws:endpoint/> tag--these are required because the combined "{namespace}localName" syntax is presently not supported for this tag's attribute values.

The jaxws:endpoint element (which appears to create an EndpointImpl under the covers) supports many additional attributes:

Name

Value

endpointName

The endpoint name this service is implementing, it maps to the wsdl:port@name. In the format of "ns:ENDPOINT_NAME" where ns is a namespace prefix valid at this scope.

publish

Whether the endpoint should be published now, or whether it will be published at a later point.

serviceName

The service name this service is implementing, it maps to the wsdl:service@name. In the format of "ns:SERVICE_NAME" where ns is a namespace prefix valid at this scope.

wsdlLocation

The location of the WSDL. Can be on the classpath, file system, or be hosted remotely.

bindingUri

The URI, or ID, of the message binding for the endpoint to use. For SOAP the binding URI(ID) is specified by the JAX-WS specification. For other message bindings the URI is the namespace of the WSDL extensions used to specify the binding.

address

The service publish address

bus

The bus name that will be used in the jaxws endpoint.

implementor

The implementor of jaxws endpoint. You can specify the implementor class name here, or just the ref bean name in the format of "#REF_BEAN_NAME"

implementorClass

The implementor class name, it is really useful when you specify the implementor with the ref bean which is wrapped by using Spring AOP

createdFromAPI

This indicates that the endpoint bean was already created using jaxws API's thus at runtime when parsing the bean spring can use these values rather than the default ones. It's important that when this is true, the "name" of the bean is set to the port name of the endpoint being created in the form "{http://service.target.namespace} PortName".

publishedEndpointUrl

The URL that is placed in the address element of the wsdl when the wsdl is retrieved. If not specified, the address listed above is used. This parameter allows setting the "public" URL that may not be the same as the URL the service is deployed on. (for example, the service is behind a proxy of some sort).

It also supports many child elements:

Name

Value

jaxws:executor

A Java executor which will be used for the service. This can be supplied using the Spring <bean class="MyExecutor"/> syntax.

jaxws:inInterceptors

The incoming interceptors for this endpoint. A list of <bean>s or <ref>s. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:inFaultInterceptors

The incoming fault interceptors for this endpoint. A list of <bean>s or <ref>s. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:outInterceptors

The outgoing interceptors for this endpoint. A list of <bean>s or <ref>s. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:outFaultInterceptors

The outgoing fault interceptors for this endpoint. A list of <bean>s or <ref>s. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:handlers

The JAX-WS handlers for this endpoint. A list of <bean>s or <ref>s. Each should implement javax.xml.ws.handler.Handler or javax.xml.ws.handler.soap.SOAPHandler (Note that @HandlerChain annotations on the service bean appear to be ignored)

jaxws:properties

A properties map which should be supplied to the JAX-WS endpoint. See below.

jaxws:dataBinding

Which DataBinding to use in the endpoint. This can be supplied using the Spring <bean class="MyDataBinding"/> syntax.

jaxws:binding

You can specify the BindingFactory for this endpoint to use. This can be supplied using the Spring <bean class="MyBindingFactory"/> syntax.

jaxws:features

The features that hold the interceptors for this endpoint. A list of <bean>s or <ref>s

jaxws:invoker

The invoker which will be supplied to this endpoint. This can be supplied using the Spring <bean class="MyInvoker"/> syntax.

jaxws:schemaLocations

The schema locations for endpoint to use. A list of <schemaLocation>s

jaxws:serviceFactory

The service factory for this endpoint to use. This can be supplied using the Spring <bean class="MyServiceFactory"/> syntax

Here is a more advanced example which shows how to provide interceptors and properties:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
   xmlns:soap="http://cxf.apache.org/bindings/soap"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
      http://cxf.apache.org/bindings/soap 
      http://cxf.apache.org/schemas/configuration/soap.xsd
      http://cxf.apache.org/jaxws 
      http://cxf.apache.org/schemas/jaxws.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml"/>

  <jaxws:endpoint
     id="helloWorld"
     implementor="demo.spring.HelloWorldImpl"
     address="http://localhost/HelloWorld">
     <jaxws:inInterceptors>
        <bean class="com.acme.SomeInterceptor"/>
        <ref bean="anotherInterceptor"/>
     </jaxws:inInterceptor>
     <jaxws:properties>
        <entry key="mtom-enabled" value="true"/>
     </jaxws:properties>
  </jaxws:endpoint>

  <bean id="anotherInterceptor" class="com.acme.SomeInterceptor"/>

  <jaxws:endpoint id="simpleWithBinding"
     implementor="#greeter" 
     address="http://localhost:8080/simpleWithAddress">
     <jaxws:binding>
        <soap:soapBinding mtomEnabled="true" version="1.2"/>
     </jaxws:binding>
  </jaxws:endpoint>

  <jaxws:endpoint id="inlineInvoker" 
     address="http://localhost:8080/simpleWithAddress">
     <jaxws:implementor>
        <bean class="org.apache.hello_world_soap_http.GreeterImpl"/>
     </jaxws:implementor>
     <jaxws:invoker>
        <bean class="org.apache.cxf.jaxws.spring.NullInvoker"/>
     </jaxws:invoker>
  </jaxws:endpoint>

</beans>

If you are a Spring user, you'll notice that the jaxws:properties element follows the Spring Map syntax.

Configuring a Spring Client (Option 1)

Important

This technique lets you add a Web Services client to your Spring application. You can inject it into other Spring beans, or manually retrieve it from the Spring context for use by non-Spring-aware client code.

The easiest way to add a Web Services client to a Spring context is to use the <jaxws:client> element (similar to the <jaxws:endpoint> element used for the server side). Here's a simple example:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:jaxws="http://cxf.apache.org/jaxws"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://cxf.apache.org/jaxws 
      http://cxf.apache.org/schemas/jaxws.xsd">

   <jaxws:client id="helloClient"
      serviceClass="demo.spring.HelloWorld"
      address="http://localhost:9002/HelloWorld"/>
</beans>

The attributes available on <jaxws:client> include:

Name

Type

Description

id

String

A unique identified for the client, which is how other beans in the context will reference it

address

URL

The URL to connect to in order to invoke the service

serviceClass

Class

The fully-qualified name of the interface that the bean should implement (typically, same as the service interface used on the server side)

serviceName

QName

The name of the service to invoke, if this address/WSDL hosts several. It maps to the wsdl:service@name. In the format of "ns:SERVICE_NAME" where ns is a namespace prefix valid at this scope.

endpointName

QName

The name of the endpoint to invoke, if this address/WSDL hosts several. It maps to the wsdl:port@name. In the format of "ns:ENDPOINT_NAME" where ns is a namespace prefix valid at this scope.

bindingId

URI

The URI, or ID, of the message binding for the endpoint to use. For SOAP the binding URI(ID) is specified by the JAX-WS specification. For other message bindings the URI is the namespace of the WSDL extensions used to specify the binding.

bus

Bean Reference

The bus name that will be used in the jaxws endpoint (defaults to cxf ).

username

String

 

password

String

 

wsdlLocation

URL

A URL to connect to in order to retrieve the WSDL for the service. This is not required.

createdFromAPI

boolean

This indicates that the client bean was already created using jaxws API's thus at runtime when parsing the bean spring can use these values rather than the default ones. It's important that when this is true, the "name" of the bean is set to the port name of the endpoint being created in the form "{http://service.target.namespace} PortName".

It also supports many child elements:

Name

Description

jaxws:inInterceptors

The incoming interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:inFaultInterceptors

The incoming fault interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:outInterceptors

The outgoing interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:outFaultInterceptors

The outgoing fault interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

jaxws:features

The features that hold the interceptors for this endpoint. A list of <bean> or <ref> elements

jaxws:handlers

The JAX-WS handlers for this endpoint. A list of <bean> or <ref> elements. Each should implement javax.xml.ws.handler.Handler or javax.xml.ws.handler.soap.SOAPHandler . These are more portable than CXF interceptors, but may cause the full message to be loaded in as a DOM (slower for large messages).

jaxws:properties

A properties map which should be supplied to the JAX-WS endpoint. See below.

jaxws:dataBinding

Which DataBinding to use in the endpoint. This can be supplied using the Spring <bean class="MyDataBinding"/> syntax.

jaxws:binding

You can specify the BindingFactory for this endpoint to use. This can be supplied using the Spring <bean class="MyBindingFactory"/> syntax.

jaxws:conduitSelector

 

Here is a more advanced example which shows how to provide interceptors, JAX-WS handlers, and properties:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:jaxws="http://cxf.apache.org/jaxws"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://cxf.apache.org/jaxws 
      http://cxf.apache.org/schemas/jaxws.xsd">

   <!-- Interceptors extend 
      e.g. org.apache.cxf.phase.AbstractPhaseInterceptor -->
   <bean id="anotherInterceptor" class="..." />

   <!-- Handlers implement 
      e.g. javax.xml.ws.handler.soap.SOAPHandler -->
   <bean id="jaxwsHandler" class="..." />

   <!-- The SOAP client bean -->
   <jaxws:client id="helloClient"
      serviceClass="demo.spring.HelloWorld"
      address="http://localhost:9002/HelloWorld">
      <jaxws:inInterceptors>
         <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
         <ref bean="anotherInterceptor"/>
      </jaxws:inInterceptor>
      <jaxws:handlers>
         <ref bean="jaxwsHandler" />
      </jaxws:handlers>
      <jaxws:properties>
         <entry key="mtom-enabled" value="true"/>
      </jaxws:properties>
   </jaxws:client>
</beans>

Configuring a Spring Client (Option 2)

Important

Building a Client using this configuration is only applicable for those wishing to inject a Client into their Spring ApplicationContext.

This approach requires more explicit Spring bean configuration than the previous option, and may require more configuration data depending on which features are used. To configure a client this way, you'll need to declare a proxy factory bean and also a client bean which is created by that proxy factory. Here is an example:

<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-2.0.xsd
   http://cxf.apache.org/jaxws 
   http://cxf.apache.org/schemas/jaxws.xsd">

   <bean id="proxyFactory" 
      class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
      <property name="serviceClass" value="demo.spring.HelloWorld"/>
      <property name="address" value="http://localhost:9002/HelloWorld"/>
   </bean>

   <bean id="client" class="demo.spring.HelloWorld"
      factory-bean="proxyFactory" factory-method="create"/>

</beans>

The JaxWsProxyFactoryBean in this case takes two properties. The service class, which is the interface of the Client proxy you wish to create. The address is the address of the service you wish to call.

The second bean definition is for the client. In this case it implements the HelloWorld interface and is created by the proxyFactory <bean> by calling the create() method. You can then reference this "client" bean and inject it anywhere into your application. Here is an example of a very simple Java class which accesses the client bean:

include org.springframework.context.support.ClassPathXmlApplicationContext;

public final class HelloWorldClient {

   private HelloWorldClient() {}

   public static void main(String args[]) throws Exception {
      ClassPathXmlApplicationContext context =
         new ClassPathXmlApplicationContext(
            new String[]{"my/path/to/client-beans.xml"});

      HelloWorld client = (HelloWorld)context.getBean("client");

      String response = client.sayHi("Dan");
      System.out.println("Response: " + response);
      System.exit(0);
   }
}

The JaxWsProxyFactoryBean supports many other properties:

Name

Description

clientFactoryBean

The ClientFactoryBean used in construction of this proxy.

password

The password which the transport should use.

username

The username which the transport should use.

wsdlURL

The wsdl URL the client should use to configure itself.

wsdlLocation

Appears to be the same as wsdlURL?

serviceName

The name of the service to invoke, if this address/WSDL hosts several. It maps to the wsdl:service@name. In the format of "ns:SERVICE_NAME" where ns is a namespace prefix valid at this scope.

endpointName

The name of the endpoint to invoke, if this address/WSDL hosts several. It maps to the wsdl:port@name. In the format of "ns:ENDPOINT_NAME" where ns is a namespace prefix valid at this scope.

inInterceptors

The incoming interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

inFaultInterceptors

The incoming fault interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

outInterceptors

The outgoing interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

outFaultInterceptors

The outgoing fault interceptors for this endpoint. A list of <bean> or <ref> elements. Each should implement org.apache.cxf.interceptor.Interceptor or org.apache.cxf.phase.PhaseInterceptor

features

The features that hold the interceptors for this endpoint. A list of <bean> or <ref> elements

handlers

A list of <bean> or <ref> elements pointing to JAX-WS handler classes to be used for this client. Each should implement javax.xml.ws.handler.Handler or javax.xml.ws.handler.soap.SOAPHandler . These are more portable than CXF interceptors, but may cause the full message to be loaded in as a DOM (slower for large messages).

bindingConfig

 

bindingId

The URI, or ID, of the message binding for the endpoint to use. For SOAP the binding URI(ID) is specified by the JAX-WS specification. For other message bindings the URI is the namespace of the WSDL extensions used to specify the binding.

bus

A reference to a CXF bus bean. Must be provided if, for example, handlers are used. May require additional Spring context imports (e.g. to bring in the default CXF bus bean).

conduitSelector

 

dataBinding

Which DataBinding to use in the endpoint. This can be supplied using the Spring <bean class="MyDataBinding"/> syntax.

properties

A properties map which should be supplied to the JAX-WS endpoint.

serviceFactory

 

Using some of the properties will require additional configuration in the Spring context. For instance, using JAX-WS handlers requires that you explicitly import several CXF Spring configurations, and assign the "bus" property of the JaxWsProxyFactory bean like this:

<import resource="classpath:META-INF/cxf/cxf.xml"/>

<bean id="clientFactory" 
   class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
   <property name="serviceClass" value="demo.spring.HelloWorld"/>
   <property name="address" value="http://localhost:9002/HelloWorld"/>
   <property name="bus" ref="cxf" />
</bean>

Configuring an Endpoint/Client Proxy Using CXF APIs

JAX-WS endpoints and client proxies are implemented on top of CXF's frontend-neutral endpoint API. You can therefore use CXF APIs to enhance the functionality of a JAX-WS endpoint or client proxy, for example by adding interceptors.

To cast a client proxy to a CXF client:

GreeterService gs = new GreeterService();
Greeter greeter = gs.getGreeterPort();

org.apache.cxf.endpoint.Client client =
   org.apache.cxf.frontend.ClientProxy.getClient(greeter);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
cxfEndpoint.getOutInterceptors().add(...);

To cast a JAX-WS endpoint to a CXF server:

javax.xml.ws.Endpoint jaxwsEndpoint = 
   javax.xml.ws.Endpoint.publish(
   "http://localhost:9020/SoapContext/GreeterPort", new GreeterImpl());
org.apache.cxf.jaxws.EndpointImpl jaxwsEndpointImpl = 
   (org.apache.cxf.jaxws.EndpointImpl)jaxwsEndpoint;
org.apache.cxf.endpoint.Server server = jaxwsEndpointImpl.getServer();
org.apache.cxf.endpoint.Endpoint cxfEndpoint = server.getEndpoint();
cxfEndpoint.getOutInterceptors().add(...);
org.apache.cxf.service.Service cxfService = cxfEndpoint.getService();
cxfService.getOutInterceptors().add(...);

Configure the JAXWS Server/Client Using Spring

CXF provides <jaxws:server>, <jaxws:client> to configure the server/client side endpoint. Here are some exmples:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jaxws="http://cxf.apache.org/jaxws"
   xmlns:soap="http://cxf.apache.org/bindings/soap"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
      http://cxf.apache.org/bindings/soap 
      http://cxf.apache.org/schemas/configuration/soap.xsd
      http://cxf.apache.org/jaxws
      http://cxf.apache.org/schemas/jaxws.xsd">

   <jaxws:server id="inlineImplementor" 
      address="http://localhost:8080/simpleWithAddress">
      <jaxws:serviceBean>
         <bean class="org.apache.hello_world_soap_http.GreeterImpl"/>
      </jaxws:serviceBean>
   </jaxws:server>

   <jaxws:server id="bookServer"
      serviceClass="org.myorg.mytype.AnonymousComplexTypeImpl"
      address="http://localhost:8080/act"
      bus="cxf">
      <jaxws:invoker>
         <bean class="org.myorg.service.invoker.BeanInvoker">
            <constructor-arg>
               <bean class="org.myorg.mytype.AnonymousComplexTypeImpl"/>
            </constructor-arg>
         </bean>
      </jaxws:invoker>
      <jaxws:dataBinding>
         <bean class="org.apache.cxf.jaxb.JAXBDataBinding">
            <property name="namespaceMap">
               <map>
                  <entry>
                     <key>
                        <value>
                           http://cxf.apache.org/anon_complex_type/
                        </value>
                     </key>
                     <value>BeepBeep</value>
                  </entry>
               </map>
            </property>
         </bean>
      </jaxws:dataBinding>
   </jaxws:server>

   <jaxws:client id="bookClient"
      serviceClass="org.myorg.mytype.AnonymousComplexType"
      address="http://localhost:8080/act"/>

</beans>

Since JAX-WS frontend server and client spring configuration parser are inherited from the simple frontend, please see Simple Frontend Configuration for the attribute and element definitions.

Configure the JAXWS Server Using SpringBoot

Here is an example:

import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
 
@Configuration
@EnableAutoConfiguration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
public class Application extends SpringBootServletInitializer {
 
    @Autowired
    private ApplicationContext applicationContext;
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
    // Replaces the need for web.xml
    @Bean
 public ServletRegistrationBean servletRegistrationBean(ApplicationContext context) {
        return new ServletRegistrationBean(new CXFServlet(), "/api/*");
    }
 
    // Replaces cxf-servlet.xml
    @Bean
    // <jaxws:endpoint id="helloWorld" 
       implementor="demo.spring.service.HelloWorldImpl" 
       address="/HelloWorld"/>
    public EndpointImpl helloService() {
        Bus bus = (Bus) applicationContext.getBean(Bus.DEFAULT_BUS_ID);
        Object implementor = new HelloWorldImpl();
        EndpointImpl endpoint = new EndpointImpl(bus, implementor);
        endpoint.publish("/hello");
        return endpoint;
    }
 
  
    // Used when deploying to a standalone servlet container, i.e. tomcat
    @Override
 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
 
}

JAX-WS Providers

JAX-WS Providers allow you to create services which work at the message level - as opposed to the operation level as with annotated classes. The have a single operation "invoke" which receives either the message payload (i.e. the SOAP Body) or the whole message itself (i.e. the SOAP Envelope).

Here's a simple example:

@WebServiceProvider
public class HelloProvider {
   public Source invoke(Source request) {
      return ....;
   }
}

Services are publish via one of two means:

  • The JAX-WS standard Endpoint APIs

  • CXF's XML configuration format - i.e. <jaxws:endpoint ... />

Messaging Modes

Overview

Objects that implement the Provider interface have two messaging modes :

  • Message mode

  • Payload mode

The messaging mode you specify determines the level of messaging detail that is passed to your implementation.

Message mode

When using message mode , a Provider implementation works with complete messages. A complete message includes any binding specific headers and wrappers. For example, a Provider implementation that uses a SOAP binding would receive requests as fully specified SOAP message. Any response returned from the implementation would also need to be a fully specified SOAP message.

You specify that a Provider implementation uses message mode by providing the value java.xml.ws.Service.Mode.MESSAGE as the value to the javax.xml.ws.ServiceMode annotation.

@WebServiceProvider
@ServiceMode(value=Service.Mode.MESSAGE)
public class stockQuoteProvider implements Provider<SOAPMessage> {
   ...
}
Payload mode

In payload mode a Provider implementation works with only the payload of a message. For example, a Provider implementation working in payload mode works only with the body of a SOAP message. The binding layer processes any binding level wrappers and headers.

Note

When working with a binding that does not use special wrappers, such as the XML binding, payload mode and message mode provide the same results.

You specify that a Provider implementation uses payload mode by providing the value java.xml.ws.Service.Mode.PAYLOAD as the value to the javax.xml.ws.ServiceMode annotation.

@WebServiceProvider
@ServiceMode(value=Service.Mode.PAYLOAD)
public class stockQuoteProvider implements Provider<DOMSource> {
   ...
}

Note

If you do not provide the @ServiceMode annotation, the Provider implementation will default to using payload mode.

Data Types

Overview

Provider implementations, because they are low-level objects, cannot use the same JAXB generated types as the higher level consumer APIs. Provider implementations work with the following types of objects:

  • javax.xml.transform.Source

  • javax.xml.soap.SOAPMessage

  • javax.activation.DataSource

Using Source objects

A Provider implementation can accept and return objects that are derived from the javax.xml.transform.Source interface. Source objects are low level objects that hold XML documents. Each Source implementation provides methods that access the stored XML documents and manipulate its contents. The following objects implement the Source interface:

  • DOMSource holds XML messages as a Document Object Model(DOM) tree. The XML message is stored as a set of Node objects that can be accessed using the getNode() method. Nodes can be updated or added to the DOM tree using the setNode() method.

  • SAXSource holds XML messages as a Simple API for XML (SAX) object. SAX objects contain an InputSource object that contains the raw data and an XMLReader object that parses the raw data.

  • StreamSource holds XML messages as a data stream. The data stream can be manipulated as would any other data stream.

    Important

    When using Source objects the developer is responsible for ensuring that all required binding specific wrappers are added to the message. For example, when interacting with a service expecting SOAP messages, the developer must ensure that the required SOAP envelope is added to the outgoing request and that the SOAP envelope's contents are correct.

Using SOAPMessage objects

Provider implementations can use javax.xml.soap.SOAPMessage objects when the following conditions are true:

  • the Provider implementation is using the SOAP binding.

  • the Provider implementation is using message mode.

A SOAPMessage object, as the name implies, holds a SOAP message. They contain one SOAPPart object and zero or more AttachmentPart objects. The SOAPPart object contains the SOAP specific portions of the SOAP message including the SOAP envelope, any SOAP headers, and the SOAP message body. The AttachmentPart objects contain binary data that was passed as an attachment.

Using DataSource objects

Provider implementations can use objects that implement the javax.activation.DataSource interface when the following conditions are true:

  • the implementation is using the HTTP binding.

  • the implementation is using message mode.

DataSource objects provide a mechanism for working with MIME typed data from a variety of sources including URLs, files, and byte arrays.

Implementing a Provider Object
Overview

The Provider interface is relatively easy to implement. It only has one method, invoke(), that needs to be implemented. In addition it has three simple requirements:

  • An implementation must have the @WebServiceProvider annotation.

  • An implementation must have a default public constructor.

  • An implementation must implement a typed version of the Provider interface. In other words, you cannot implement a Provider<T> interface. You must implement a version of the interface that uses a concrete data type. For example, you can implement an instance of a Provider<SAXSource> .

The complexity of implementing the Provider interface surrounds handling the request messages and building the proper responses.

Working with messages

Unlike the higher-level SEI based service implementations, Provider implementations receive requests as raw XML data and must send responses as raw XML data. This requires that the developer has intimate knowledge of the messages used by the service being implemented. These details can typically be found in the WSDL document describing the service.

WS-I Basic Profile provides guidelines about the messages used by services including:

  • The root element of a request is based in the value of the name attribute of the wsdl:operation element that corresponds to the operation being invoked.

    Warning

    If the service uses doc/literal bare messages, the root element of the request will be based on the value of name attribute of the wsdl:part element referred to by the wsdl:operation element.

  • The root element of all messages will be namespace qualified.

  • If the service uses rpc/literal messages, the top-level elements in the messages will not be namespace qualified.

    Important

    The children of top-level elements may be namespace qualified. To be certain you will need to check their schema definitions.

  • If the service uses rpc/literal messages, none of the top-level elements can be null.

  • If the service uses doc/literal messages, the schema definition of the message determines if any of the elements are namespace qualified.

Implementing the invoke() method

The Provider interface has only one method, invoke() , that needs to be implemented. invoke() receives the incoming request packaged into the type of object declared by the type of Provider interface being implemented and returns the response message packaged into the same type of object. For example, an implementation of a Provider<SOAPMessage> interface would receive the request as a SOAPMessage object and return the response as a SOAPMessage object.

The messaging mode used by the Provider implementation determines the amount of binding specific information the request and response messages contain. Implementation using message mode receive all of the binding specific wrappers and headers along with the request. They must also add all of the binding specific wrappers and headers to the response message. Implementations using payload mode only receive the body of the request. The XML document returned by an implementation using payload mode will be placed into the body of the request message.

Examples

The following shows a Provider implementation that works with SOAPMessage objects in message mode.

import javax.xml.ws.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;

@WebServiceProvider(portName="stockQuoteReporterPort" 
   serviceName="stockQuoteReporter")
@ServiceMode(value="Service.Mode.MESSAGE")
public class  stockQuoteReporterProvider implements Provider<SOAPMessage> {
   public stockQuoteReporterProvider() {}

   public SOAPMessage invoke(SOAPMessage request) {
      SOAPBody requestBody = request.getSOAPBody();
      if (requestBody.getElementName.getLocalName.equals("getStockPrice")) {
         MessageFactory mf = MessageFactory.newInstance();
         SOAPFactory sf = SOAPFactory.newInstance();

         SOAPMessage response = mf.createMessage();
         SOAPBody respBody = response.getSOAPBody();
         Name bodyName = sf.createName("getStockPriceResponse");
         respBody.addBodyElement(bodyName);
         SOAPElement respContent = respBody.addChildElement("price");
         respContent.setValue("123.00");
         response.saveChanges();
         return response;
      }
      ...
   }
}

The code does the following:

  1. Specifies that the following class implements a Provider object that implements the service whose wsdl:service element is named stockQuoteReporter and whose wsdl:port element is named stockQuoteReporterPort .

  2. Specifies that this Provider implementation uses message mode.

  3. Provides the required default public constructor.

  4. Provides an implementation of the invoke() method that takes a SOAPMessage object and returns a SOAPMessage object.

  5. Extracts the request message from the body of the incoming SOAP message.

  6. Checks the root element of the request message to determine how to process the request.

  7. Creates the factories needed for building the response.

  8. Builds the SOAP message for the response.

  9. Returns the response as a SOAPMessage object.

The following shows an example of a Provider implementation using DOMSource objects in payload mode.

import javax.xml.ws.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;

@WebServiceProvider(portName="stockQuoteReporterPort" 
   serviceName="stockQuoteReporter")
@ServiceMode(value="Service.Mode.PAYLOAD")
public class stockQuoteReporterProvider implements Provider<DOMSource> {
   public stockQuoteReporterProvider() {}

   public DOMSource invoke(DOMSource request) {
      DOMSource response = new DOMSource();
      ...
      return response;
   }
}

The code does the following:

  1. Specifies that the class implements a Provider object that implements the service whose wsdl:service element is named stockQuoteReporter and whose wsdl:port element is named stockQuoteReporterPort .

  2. Specifies that this Provider implementation uses payload mode.

  3. Provides the required default public constructor.

  4. Provides an implementation of the invoke() method that takes a DOMSource object and returns a DOMSource object.

WebserviceContext

The WebserviceContext interface is part of the JAX-WS specification. It allows you to access several context informations the runtime has associated to your service call.

The following code fragment show how to use some parts of the WebserviceContext.

public class CustomerServiceImpl implements CustomerService {
   @Resource
   WebServiceContext wsContext;

   public List<Customer> getCustomersByName(String name) 
      throws NoSuchCustomerException {
      Principal pr = wsContext.getUserPrincipal();

      // Only joe may access this service operation
      if (pr == null || !"joe".equals(pr.getName())) {
         throw new RuntimeException("Access denied");
      }

      // Only the sales role may access this operation
      if (!wsContext.isUserInRole("sales")) {
         throw new RuntimeException("Access denied");
      }

      MessageContext mContext = wsContext.getMessageContext();

      // See which contents the message context has
      Set<String> s = mContext.keySet();

      // Using this cxf specific code you can access 
      // the CXF Message and Exchange objects
      WrappedMessageContext wmc = (WrappedMessageContext)mContext;
      Message m = wmc.getWrappedMessage();
      Exchange ex = m.getExchange();
   }
}