Red Hat Training
A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform
16.5. JAX-WS Web Service Clients
16.5.1. Consume and Access a JAX-WS Web Service
- Create the client artifacts.
- Construct a service stub.
Before you can create client artifacts, you need to create your WSDL contract. The following WSDL contract is used for the examples presented in the rest of this topic.
ProfileMgmtService.wsdl
file.
Example 16.16. Example WSDL Contract
<definitions name='ProfileMgmtService' targetNamespace='http://org.jboss.ws/samples/retail/profile' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:ns1='http://org.jboss.ws/samples/retail' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://org.jboss.ws/samples/retail/profile' xmlns:xsd='http://www.w3.org/2001/XMLSchema'> <types> <xs:schema targetNamespace='http://org.jboss.ws/samples/retail' version='1.0' xmlns:xs='http://www.w3.org/2001/XMLSchema'> <xs:complexType name='customer'> <xs:sequence> <xs:element minOccurs='0' name='creditCardDetails' type='xs:string'/> <xs:element minOccurs='0' name='firstName' type='xs:string'/> <xs:element minOccurs='0' name='lastName' type='xs:string'/> </xs:sequence> </xs:complexType> </xs:schema> <xs:schema targetNamespace='http://org.jboss.ws/samples/retail/profile' version='1.0' xmlns:ns1='http://org.jboss.ws/samples/retail' xmlns:tns='http://org.jboss.ws/samples/retail/profile' xmlns:xs='http://www.w3.org/2001/XMLSchema'> <xs:import namespace='http://org.jboss.ws/samples/retail'/> <xs:element name='getCustomerDiscount' nillable='true' type='tns:discountRequest'/> <xs:element name='getCustomerDiscountResponse' nillable='true' type='tns:discountResponse'/> <xs:complexType name='discountRequest'> <xs:sequence> <xs:element minOccurs='0' name='customer' type='ns1:customer'/> </xs:sequence> </xs:complexType> <xs:complexType name='discountResponse'> <xs:sequence> <xs:element minOccurs='0' name='customer' type='ns1:customer'/> <xs:element name='discount' type='xs:double'/> </xs:sequence> </xs:complexType> </xs:schema> </types> <message name='ProfileMgmt_getCustomerDiscount'> <part element='tns:getCustomerDiscount' name='getCustomerDiscount'/> </message> <message name='ProfileMgmt_getCustomerDiscountResponse'> <part element='tns:getCustomerDiscountResponse' name='getCustomerDiscountResponse'/> </message> <portType name='ProfileMgmt'> <operation name='getCustomerDiscount' parameterOrder='getCustomerDiscount'> <input message='tns:ProfileMgmt_getCustomerDiscount'/> <output message='tns:ProfileMgmt_getCustomerDiscountResponse'/> </operation> </portType> <binding name='ProfileMgmtBinding' type='tns:ProfileMgmt'> <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http'/> <operation name='getCustomerDiscount'> <soap:operation soapAction=''/> <input> <soap:body use='literal'/> </input> <output> <soap:body use='literal'/> </output> </operation> </binding> <service name='ProfileMgmtService'> <port binding='tns:ProfileMgmtBinding' name='ProfileMgmtPort'> <soap:address location='SERVER:PORT/jaxws-samples-retail/ProfileMgmtBean'/> </port> </service> </definitions>
Note
wsconsume.sh
or wsconsume.bat
tool is used to consume the abstract contract (WSDL) and produce annotated Java classes and optional sources that define it. The command is located in the EAP_HOME/bin/
directory of the JBoss EAP 6 installation.
Example 16.17. Syntax of the wsconsume.sh
Command
[user@host bin]$ ./wsconsume.sh --help WSConsumeTask is a cmd line tool that generates portable JAX-WS artifacts from a WSDL file. usage: org.jboss.ws.tools.cmd.WSConsume [options] <wsdl-url> options: -h, --help Show this help message -b, --binding=<file> One or more JAX-WS or JAXB binding files -k, --keep Keep/Generate Java source -c --catalog=<file> Oasis XML Catalog file for entity resolution -p --package=<name> The target package for generated source -w --wsdlLocation=<loc> Value to use for @WebService.wsdlLocation -o, --output=<directory> The directory to put generated artifacts -s, --source=<directory> The directory to put Java source -t, --target=<2.0|2.1|2.2> The JAX-WS specification target -q, --quiet Be somewhat more quiet -v, --verbose Show full exception stack traces -l, --load-consumer Load the consumer and exit (debug utility) -e, --extension Enable SOAP 1.2 binding extension -a, --additionalHeaders Enable processing of implicit SOAP headers -n, --nocompile Do not compile generated sources
.java
files listed in the output, from the ProfileMgmtService.wsdl
file. The sources use the directory structure of the package, which is specified with the -p
switch.
[user@host bin]$ wsconsume.sh -k -p org.jboss.test.ws.jaxws.samples.retail.profile ProfileMgmtService.wsdl
output/org/jboss/test/ws/jaxws/samples/retail/profile/Customer.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountRequest.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountResponse.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/ObjectFactory.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmt.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtService.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/package-info.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/Customer.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountRequest.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountResponse.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/ObjectFactory.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmt.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtService.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/package-info.class
.java
source files and compiled .class
files are generated into the output/
directory within the directory where you run the command.
Table 16.2. Descriptions of Artifacts Created by wsconsume.sh
File | Description |
---|---|
ProfileMgmt.java
|
Service endpoint interface.
|
Customer.java
|
Custom data type.
|
Discount*.java
|
Custom data types.
|
ObjectFactory.java
|
JAXB XML registry.
|
package-info.java
|
JAXB package annotations.
|
ProfileMgmtService.java
|
Service factory.
|
wsconsume.sh
command generates all custom data types (JAXB annotated classes), the service endpoint interface and a service factory class. These artifacts are used to build web service client implementations.
Web service clients use service stubs to abstract the details of a remote web service invocation. To a client application, a WS invocation looks like an invocation of any other business component. In this case the service endpoint interface acts as the business interface, and a service factory class is not used to construct it as a service stub.
Example 16.18. Constructing a Service Stub and Accessing the Endpoint
wsconsume.sh
command to build the service stub. Finally, the stub can be used just as any other business interface would be.
import javax.xml.ws.Service; [...] Service service = Service.create( new URL("http://example.org/service?wsdl"), new QName("MyService") ); ProfileMgmt profileMgmt = service.getPort(ProfileMgmt.class); // Use the service stub in your application
16.5.2. Develop a JAX-WS Client Application
Service
- Overview
- A
Service
is an abstraction which represents a WSDL service. A WSDL service is a collection of related ports, each of which includes a port type bound to a particular protocol and a particular endpoint address.Usually, the Service is generated when the rest of the component stubs are generated from an existing WSDL contract. The WSDL contract is available via the WSDL URL of the deployed endpoint, or can be created from the endpoint source using thewsprovide.sh
command in theEAP_HOME/bin/
directory.This type of usage is referred to as the static use case. In this case, you create instances of theService
class which is created as one of the component stubs.You can also create the service manually, using theService.create
method. This is referred to as the dynamic use case. - Usage
- Static Use Case
- The static use case for a JAX-WS client assumes that you already have a WSDL contract. This may be generated by an external tool or generated by using the correct JAX-WS annotations when you create your JAX-WS endpoint.To generate your component stubs, you use the
wsconsume.sh
orwsconsume.bat
script which is included inEAP_HOME/bin/
. The script takes the WSDL URL or file as a parameter, and generates multiple of files, structured in a directory tree. The source and class files representing yourService
are namedCLASSNAME_Service.java
andCLASSNAME_Service.class
, respectively.The generated implementation class has two public constructors, one with no arguments and one with two arguments. The two arguments represent the WSDL location (ajava.net.URL
) and the service name (ajavax.xml.namespace.QName
) respectively.The no-argument constructor is the one used most often. In this case the WSDL location and service name are those found in the WSDL. These are set implicitly from the@WebServiceClient
annotation that decorates the generated class.Example 16.19. Example Generated Service Class
@WebServiceClient(name="StockQuoteService", targetNamespace="http://example.com/stocks", wsdlLocation="http://example.com/stocks.wsdl") public class StockQuoteService extends javax.xml.ws.Service { public StockQuoteService() { super(new URL("http://example.com/stocks.wsdl"), new QName("http://example.com/stocks", "StockQuoteService")); } public StockQuoteService(String wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName); } ... }
- Dynamic Use Case
- In the dynamic case, no stubs are generated automatically. Instead, a web service client uses the
Service.create
method to createService
instances. The following code fragment illustrates this process.Example 16.20. Creating Services Manually
URL wsdlLocation = new URL("http://example.org/my.wsdl"); QName serviceName = new QName("http://example.org/sample", "MyService"); Service service = Service.create(wsdlLocation, serviceName);
- Handler Resolver
- JAX-WS provides a flexible plug-in framework for message processing modules, known as handlers. These handlers extend the capabilities of a JAX-WS runtime system. A
Service
instance provides access to aHandlerResolver
via a pair ofgetHandlerResolver
andsetHandlerResolver
methods that can configure a set of handlers on a per-service, per-port or per-protocol binding basis.When aService
instance creates a proxy or aDispatch
instance, the handler resolver currently registered with the service creates the required handler chain. Subsequent changes to the handler resolver configured for aService
instance do not affect the handlers on previously created proxies orDispatch
instances. - Executor
Service
instances can be configured with ajava.util.concurrent.Executor
. TheExecutor
invokes any asynchronous callbacks requested by the application. ThesetExecutor
andgetExecutor
methods ofService
can modify and retrieve theExecutor
configured for a service.
A dynamic proxy is an instance of a client proxy using one of the getPort
methods provided in the Service
. The portName
specifies the name of the WSDL port the service uses. The serviceEndpointInterface
specifies the service endpoint interface supported by the created dynamic proxy instance.
Example 16.21. getPort
Methods
public <T> T getPort(QName portName, Class<T> serviceEndpointInterface) public <T> T getPort(Class<T> serviceEndpointInterface)
wsconsume.sh
command, which parses the WSDL and creates Java classes from it.
Example 16.22. Returning the Port of a Service
@WebServiceClient(name = "TestEndpointService", targetNamespace = "http://org.jboss.ws/wsref", wsdlLocation = "http://localhost.localdomain:8080/jaxws-samples-webserviceref?wsdl") public class TestEndpointService extends Service { ... public TestEndpointService(URL wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName); } @WebEndpoint(name = "TestEndpointPort") public TestEndpoint getTestEndpointPort() { return (TestEndpoint)super.getPort(TESTENDPOINTPORT, TestEndpoint.class); } }
@WebServiceRef
The @WebServiceRef
annotation declares a reference to a Web Service. It follows the resource pattern shown by the javax.annotation.Resource
annotation defined in http://www.jcp.org/en/jsr/summary?id=250.
Use Cases for @WebServiceRef
- You can use it to define a reference whose type is a generated
Service
class. In this case, the type and value element each refer to the generatedService
class type. Moreover, if the reference type can be inferred by the field or method declaration the annotation is applied to, the type and value elements may (but are not required to) have the default value ofObject.class
. If the type cannot be inferred, then at least the type element must be present with a non-default value. - You can use it to define a reference whose type is an SEI. In this case, the type element may (but is not required to) be present with its default value if the type of the reference can be inferred from the annotated field or method declaration. However, the value element must always be present and refer to a generated service class type, which is a subtype of
javax.xml.ws.Service
. ThewsdlLocation
element, if present, overrides the WSDL location information specified in the@WebService
annotation of the referenced generated service class.Example 16.23.
@WebServiceRef
Examplespublic class EJB3Client implements EJB3Remote { @WebServiceRef public TestEndpointService service4; @WebServiceRef public TestEndpoint port3;
XML Web Services use XML messages for communication between the endpoint, which is deployed in the Java EE container, and any clients. The XML messages use an XML language called Simple Object Access Protocol (SOAP). The JAX-WS API provides the mechanisms for the endpoint and clients to each be able to send and receive SOAP messages. Marshalling is the process of converting a Java Object into a SOAP XML message. Unmarshalling is the process of converting the SOAP XML message back into a Java Object.
Dispatch
class provides this functionality. Dispatch
operates in one of two usage modes, which are identified by one of the following constants.
javax.xml.ws.Service.Mode.MESSAGE
- This mode directs client applications to work directly with protocol-specific message structures. When used with a SOAP protocol binding, a client application works directly with a SOAP message.javax.xml.ws.Service.Mode.PAYLOAD
- This mode causes the client to work with the payload itself. For instance, if it is used with a SOAP protocol binding, a client application would work with the contents of the SOAP body rather than the entire SOAP message.
Dispatch
is a low-level API which requires clients to structure messages or payloads as XML, with strict adherence to the standards of the individual protocol and a detailed knowledge of message or payload structure. Dispatch
is a generic class which supports input and output of messages or message payloads of any type.
Example 16.24. Dispatch
Usage
Service service = Service.create(wsdlURL, serviceName); Dispatch dispatch = service.createDispatch(portName, StreamSource.class, Mode.PAYLOAD); String payload = "<ns1:ping xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>"; dispatch.invokeOneWay(new StreamSource(new StringReader(payload))); payload = "<ns1:feedback xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>"; Source retObj = (Source)dispatch.invoke(new StreamSource(new StringReader(payload)));
The BindingProvider
interface represents a component that provides a protocol binding which clients can use. It is implemented by proxies and is extended by the Dispatch
interface.
BindingProvider
instances may provide asynchronous operation capabilities.Asynchronous operation invocations are decoupled from the BindingProvider
instance at invocation time. The response context is not updated when the operation completes. Instead, a separate response context is made available using the Response
interface.
Example 16.25. Example Asynchronous Invocation
public void testInvokeAsync() throws Exception { URL wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-samples-asynchronous?wsdl"); QName serviceName = new QName(targetNS, "TestEndpointService"); Service service = Service.create(wsdlURL, serviceName); TestEndpoint port = service.getPort(TestEndpoint.class); Response response = port.echoAsync("Async"); // access future String retStr = (String) response.get(); assertEquals("Async", retStr); }
@Oneway
Invocations
The @Oneway
annotation indicates that the given web method takes an input message but returns no output message. Usually, a @Oneway
method returns the thread of control to the calling application before the business method is executed.
Example 16.26. Example @Oneway
Invocation
@WebService (name="PingEndpoint") @SOAPBinding(style = SOAPBinding.Style.RPC) public class PingEndpointImpl { private static String feedback; @WebMethod @Oneway public void ping() { log.info("ping"); feedback = "ok"; } @WebMethod public String feedback() { log.info("feedback"); return feedback; } }
Two different properties control the timeout behavior of the HTTP connection and the timeout of a client which is waiting to receive a message. The first is javax.xml.ws.client.connectionTimeout
and the second is javax.xml.ws.client.receiveTimeout
. Each is expressed in milliseconds, and the correct syntax is shown below.
Example 16.27. JAX-WS Timeout Configuration
public void testConfigureTimeout() throws Exception { //Set timeout until a connection is established ((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", "6000"); //Set timeout until the response is received ((BindingProvider) port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", "1000"); port.echo("testTimeout"); }