...
Code Block | ||
---|---|---|
| ||
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:
- Create a Service Endpoint Interface (SEI) that defines the methods you wish to expose as a service.
Tip tile Tip 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.
- Add the required annotations to your code.
- Generate the WSDL contract for your service.
Tip title Tip If you intend to use the SEI as the service's contract, it is not necessary to generate a WSDL contract
- 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 title 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:- Create an SEI that contains only the operations that are going to be exposed as part of the service.
- Modify the existing Java class so that it implements the SEI.
Note title 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.
Tip | ||
---|---|---|
| ||
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. |
#Example2 shows a simple SEI for a stock updating service.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
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.
#Example3 shows a class for implementing the interface in #Example2.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
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 title Tip 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 |
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 |
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. |
portName | Specifies the name of the endpoint at which the service is published. This property is mapped to the |
Tip | ||
---|---|---|
| ||
You do not need to provide values for any of the |
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.
#Example4 shows the interface defined in #Example2 with the @WebService
annotation.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
package com.iona.demo;
import javax.jws.*;
@WebService(name="quoteUpdater",
targetNamespace="http:\\cxf.apache.org",
serviceName="updateQuoteService",
wsdlLocation="http:\\cxf.apache.org\quoteExampleService?wsdl",
portName="updateQuotePort")
public interface quoteReporter
{
public Quote getQuote(String ticker);
}
|
The @WebService
annotation in #Example4 does the following:
- Specifies that the value of the name attribute of the
wsdl:portType
element defining the service interface isquoteUpdater
. - Specifies that the target namespace of the service is
http:
.
cxf.apache.org - Specifies that the value of the name of the
wsdl:service
element defining the published service isupdateQuoteService
. - Specifies that the service will publish its WSDL contract at
http:\\cxf.apache.org\quoteExampleService?wsdl
. - Specifies that the value of the name attribute of the
wsdl:port
element defining the endpoint exposing the service isupdateQuotePort
.
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 #Example5 the property needs to be set to the full name of the SEI.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
package org.apache.cxf;
import javax.jws.*;
@WebService(endpointInterface="org.apache.cxf.quoteReporter")
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.
Tip | ||
---|---|---|
| ||
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 | | Specifies the style of the SOAP message. If |
use | | Specifies how the data of the SOAP message is streamed. |
parameterStyle | | 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 |
#Example6 shows an SEI that uses rpc/literal SOAP messages.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
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 |
action | Specifies the value of the |
exclude | Specifies if the method should be excluded from the service interface. The default is |
...
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 |
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. |
Tip | ||
---|---|---|
| ||
Only the |
...
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 |
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. |
Tip | ||
---|---|---|
| ||
Only the |
...
The @WebFault
annotation
...
The @WebFault
annotation is defined by the javax.xml.ws.WebFault
interface. It is placed on methods in the SEI that throw exceptions. 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. |
Note | ||
---|---|---|
| ||
The |
...
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
...
#Example7 shows an SEI whose methods are annotated.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
package org.apache.cxf;
import javax.jws.*;
import javax.xml.ws.*;
@WebService(name="quoteReporter")
public interface quoteReporter
{
@WebMethod(operationName="getStockQuote")
@RequestWrapper(targetNamespace="http://demo.iona.com/types",
className="java.lang.String")
@ResponseWrapper(targetNamespace="http://demo.iona.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 | Values | Description |
---|---|---|
name |
| Specifies the name of the parameter as it appears in the WSDL. For RPC bindings, this is name of the |
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. |
header | | Specifies if the parameter is passed as part of the SOAP header. |
partName |
| Specifies the value of the name attribute of the |
...
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 |
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 |
...
Example
...
#Example8 shows an SEI that is fully annotated.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
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.iona.com/types",
className="java.lang.String")
@ResponseWrapper(targetNamespace="http://demo.iona.com/types",
className="org.eric.demo.Quote")
@WebResult(targetNamespace="http://demo.iona.com/types",
name="updatedQuote")
public Quote getQuote(
@WebParam(targetNamespace="http://demo.iona.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.
Example
#Example9 shows the WSDL contract generated for the SEI shown in #Example8.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||
---|---|---|
| ||
<?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>
|