Oracle® Application Server Web Services Developer's Guide 10g Release 3 (10.1.3) B14434-01 |
|
![]() Previous |
![]() Next |
This chapter provides information on developing a Web services client for the J2SE platform. This chapter has the following sections.
The J2SE client, unlike the J2EE client, is responsible for much of the underlying work of looking up the service, and creating and maintaining the instances of classes that access the Web service. Since developers cannot rely on the container, they must create and manage their own services, and ensure the availability of all runtime environments needed to access the Web service.
The following sections describe static stub clients and Dynamic Invocation Interface (DII) clients.
The WebServicesAssembler command genProxy
generates static stubs from a supplied WSDL document. The generated stubs implement the javax.xml.rpc.Stub
interface and a service endpoint interface. Additionally, the generated stubs are specifically bound to the HTTP transport and SOAP protocol. You can instantiate the generated stubs and invoke their methods directly to send requests to the associated Web service.
In addition, WebServicesAssembler generates a client utility class that demonstrates how a client leverages the static stubs to interact with a Web service. The name of the utility client class is <WSDL_port_name
>Client.java
. This class handles all steps necessary for creating a stub instance. You may want to instantiate the utility client and use it to invoke the remote service's operations.
Note: The client utility class file is regenerated every time WebServicesAssembler is executed, it is strongly recommended that you place your own code in a separate file. Otherwise, you will lose your changes. |
The JAX-RPC Dynamic Invocation Interface supports the invocation of a remote Web service operation even if the name of the service or the signature of the remote method is unknown prior to runtime.
Support for DII is provided through OC4J's implementation of the javax.xml.rpc.Call
interface. The javax.xml.rpc.Service
class acts as a factory for Call
instances by using the overloaded javax.xml.rpc.Service.createCall()
method. Once created, the various getters and setters that the Call
interface provides are used to configure the port type, the operation name, the service endpoint address, and other attributes required for executing the remote method.
For examples of using DII clients to invoke Web services, see "Using Dynamic Invocation Interface to Invoke Web Services".
Before you begin, provide the following files and information.
Supply the URI to the WSDL you want to employ to generate the client. This chapter uses the WSDL file described in "Sample WSDL File".
Decide on the destination location for generated artifacts.
Decide on a package name for the client files.
You can use WebServicesAssembler to create a J2SE Web service client using static stubs. To create the static stub, follow these steps.
Provide the URI to the WSDL, the name of the output directory, the package name, and the other information and files described in the Prerequisites section as input to the WebServicesAssembler genProxy
command. For example:
java -jar wsa.jar -genProxy -output build/src/client/ -wsdl http://localhost:8888/hello/HelloService?WSDL -packageName oracle.demo.hello
This command generates the client proxies and stores them in build/src/client
. The client application uses the stub to invoke operations on a remote service. For more information on the required and optional arguments to genProxy
, see "genProxy".
Use the client utility class file created by genProxy
as your application client, or use it as a template to write your own client code. The client utility class file is one of a number of files created by genProxy
.
You can also use the client utility class file to test your endpoint. Example 14-2, "HelloInterfacePortClient.java Listing", illustrates the client utility class file created in this example. For more information about this file, see "Writing Web Service Client Applications".
Compile the client files and put them in the classpath.
List the appropriate JARs on the classpath before compiling the client. Table A-2, "Classpath Components for a Client Using a Client-Side Proxy" lists all of the JAR files that can possibly be used on the client classpath. As an alternative to listing individual JARs, you can include the client-side JAR, wsclient_extended.jar
on the client classpath. This JAR file contains all the classes necessary to compile and run a Web service client. The classes are from the individual JAR files listed in Table A-2. See "Setting the Web Service Proxy Client Classpath" for more information on wsclient_extended.jar
and the client classpath.
Run the J2SE client from the command line.
The current release provides Ant tasks for Web services development. The following code sample shows how the WebServicesAssembler genProxy
command can be rewritten as an Ant task.
<oracle:genProxy wsdl="http://localhost:8888/hello/HelloService?WSDL" output="build/src/client" packageName="oracle.demo.hello"/>
Example 14-1 contains a partial listing of the HelloService.wsdl
used to generate the client. One of the files generated from this WSDL is the client utility class file listed in Example 14-2.
This partial listing illustrates a number of entries in the WSDL file that are employed in the generation of the client utility class file. For example:
The name of the client utility class file, HelloInterfacePortClient.java
, is derived from the value of the <port name>
element.
The operation name, sayHello
, which appears under the <portType>
element, becomes a method in the client utility class file.
The parameter and data type belonging to sayHello
is defined by the complexType
defining the sayHello
request:
<complexType name="sayHello"> <sequence> <element name="name" nillable="true" type="string"/> </sequence> </complexType>
The preceding elements appear in bold in the partial listing of HelloService.wsdl
.
Example 14-1 WSDL Fragment, With Elements Used in the Client Utility Class File
<definitions ... > <types> <schema targetNamespace="http://hello.demo.oracle/" ... xmlns="http://www.w3.org/2001/XMLSchema" ... <complexType name="sayHello"> <sequence> <element name="name" nillable="true" type="string"/> </sequence> </complexType> <complexType name="sayHelloResponse"> <sequence> <element name="result" nillable="true" type="string"/> </sequence> </complexType> <element name="sayHelloElement" type="tns:sayHello"/> <element name="sayHelloResponseElement" type="tns:sayHelloResponse"/> </schema> </types> <message name="HelloInterface_sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponseElement"/> </message> <message name="HelloInterface_sayHello"> <part name="parameters" element="tns:sayHelloElement"/> </message> <portType name="HelloInterface"> <operation name="sayHello"> <input message="tns:HelloInterface_sayHello"/> <output message="tns:HelloInterface_sayHelloResponse"/> </operation> </portType> <binding name="HelloInterfacePortBinding" type="tns:HelloInterface"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="sayHello"> <soap:operation soapAction="http://hello.demo.oracle/:sayHello"/> <input> <soap:body use="literal" parts="parameters"/> </input> <output> <soap:body use="literal" parts="parameters"/> </output> </operation> </binding> <service name="HelloService"> <port name="HelloInterfacePort" binding="tns:HelloInterfacePortBinding"> <soap:address location="HelloService"/> </port> </service> </definitions>
The genProxy
command generates a client utility class file that enables you to invoke Web service methods. You can use this file as your application client, or use it as a template to write your own application client code.
Note: The client utility class file is regenerated each time you rungenProxy . If you add code to this file for testing purposes, then your changes will be lost if you regenerate the proxy. For production code, your client code should exist outside of this utility class. |
The command derives the name of the file by appending the suffix Client
to the port name. For example, for the HelloInterfacePort
port name, genProxy
generates the HelloInterfacePortClient.java
file. Example 14-2, "HelloInterfacePortClient.java Listing" illustrates the sample client utility class file generated by genProxy
.
The client utility class serves as a proxy to the Web service implementation. The client-side proxy code constructs a SOAP request and marshals and unmarshals parameters for you. Using the proxy classes saves you the work of creating SOAP requests and data marshalling for accessing a Web service or processing Web service responses.
The most important part of the client utility class file is the factory code for creating javax.xml.rpc.Service
objects and obtaining the operations available on the service. The Service
object acts as an instance of the generated stub class.
Note the following lines of code in the client utility class file:
public HelloInterfaceClient() throws Exception { ServiceFactory factory = ServiceFactory.newInstance(); _port = ((HelloService)factory.loadService (HelloService.class)).getHelloInterfacePort(); }
If you write your own application client, you must supply this code. The following steps describe the code.
Instantiate a new javax.xml.rpc.ServiceFactory
instance or use an existing instance.
ServiceFactory factory = ServiceFactory.newInstance();
Load the service for a particular service endpoint interface using the loadService
method. This returns an object of type Service
that also implements the requested service endpoint interface.
(HelloService)factory.loadService(HelloService.class)
In this example, the returned Service
is cast to the service endpoint interface HelloService
.
Use the get
...()
method to get the desired port. The ellipsis ("...") represents the value of the port name
element in the WSDL.
HelloService.getHelloInterfacePort();
In this example, the method name is getHelloInterfacePort()
, where HelloInterfacePort
is the port name
in the WSDL. The method returns a Java implementation for HelloInterfacePort
.
Example 14-2 displays the client utility class file, HelloInterfacePortClient.java
, which was generated from the HelloService.wsdl
in Example 14-1 by the genProxy
command. The lines of code that create the Service
objects and obtain the operations available on the service appear in bold.
Also note the presence of the SESSION_MAINTAIN_PROPERTY
in this example. This property is used to alert the client that the Web service is stateful. You will want to maintain the session when the client is operating in conjunction with a server side, stateful Web service. By maintaining the session, subsequent requests to the service are faster.
Example 14-2 HelloInterfacePortClient.java Listing
import oracle.webservices.transport.ClientTransport; import oracle.webservices.OracleStub; import javax.xml.rpc.ServiceFactory; import javax.xml.rpc.Stub; public class HelloInterfacePortClient { private HelloInterface _port; public HelloInterfacePortClient() throws Exception { ServiceFactory factory = ServiceFactory.newInstance(); _port =((HelloService)factory.loadService( HelloService.class)).getHelloInterfacePort(); } /** * @param args */ public static void main(String[] args) { try { HelloInterfacePortClient myPort = new HelloInterfacePortClient(); System.out.println("calling " + myPort.getEndpoint()); // Add your own code here } catch (Exception ex) { ex.printStackTrace(); } } /** * delegate all operations to the underlying implementation class. */ // sayHello public String sayHello(String name) throws java.rmi.RemoteException { return _port.sayHello(name); } /** * used to access the JAX-RPC level APIs * returns the interface of the port instance */ public oracle.demo.hello.HelloInterface getPort() { return _port; } public String getEndpoint() { return (String) ((Stub) _port)._getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY); } public void setEndpoint(String endpoint) { ((Stub) _port)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, endpoint); } public String getPassword() { return (String) ((Stub) _port)._getProperty(Stub.PASSWORD_PROPERTY); } public void setPassword(String password) { ((Stub) _port)._setProperty(Stub.PASSWORD_PROPERTY, password); } public String getUsername() { return (String) ((Stub) _port)._getProperty(Stub.USERNAME_PROPERTY); } public void setUsername(String username) { ((Stub) _port)._setProperty(Stub.USERNAME_PROPERTY, username); } public void setMaintainSession(boolean maintainSession) { ((Stub) _port)._setProperty(Stub.SESSION_MAINTAIN_PROPERTY, new Boolean(maintainSession)); } public boolean getMaintainSession() { return ((Boolean) ((Stub) _port)._getProperty(Stub.SESSION_MAINTAIN_PROPERTY)).booleanValue(); } /** * returns the transport context */ public ClientTransport getClientTransport() { return ((OracleStub) _port).getClientTransport(); } }
OracleAS Web Services permits the chunked transfer encoding of messages when the protocol is HTTP 1.1. Chunked data transfer can be invoked on J2SE stub, J2EE stub and DII Web service clients.
For more information on how to enable this feature, see "Enabling Chunked Data Transfer for HTTP 1.1".
By default, a client assembled under Oracle Application Server Web Services sends a request message with a SOAP envelope encoded with UTF-8 characters. To override this behavior, you can set the following Oracle proprietary property:
oracle.webservices.ClientConstants.CHARACTER_SET_ENCODING
This property can be used to set the character encoding for a J2SE client or a J2EE client. For more information on how to use this property, see "Setting a Character Encoding for a SOAP Message".
A client stub can be used to set the cookies used in an HTTP request.
To do this, follow these general steps:
Construct a cookie, using the Cookie
class from the Oracle Applications Server 10g HTTPClient
package.
The Cookie
class represents an HTTP cookie. Cookie
has the following constructor:
Cookie (java.lang.String
name
, java.lang.String
value
, java.lang.String
domain
,
java.lang.String
path
, java.util.Date
expires
, boolean
secure
)
All parameters except expires
are required to the Cookie
constructor.
Set the property oracle.webservices.ClientConstants.COOKIE_MAP
.
The value of the property is a java.util.Map
object that contains items and keys of type HTTPClient.Cookie
.
Set the javax.xml.rpc.session.SESSION_MAINTAIN_PROPERTY
runtime property set to true
.
This property alerts the client that the Web service is stateful. If this property is not set to true
, then the cookies will be ignored.
Example 14-3 illustrates stub code that sets the value of two cookies. The cookieMap
variable is declared to be of type java.util.Map
and obtains its contents from a HashMap
. The Cookie
constructor is used to define two cookies, cookie
and cookie2
. The cookieMap.put
lines add the cookies to the hashmap. The Stub.SESSION_MAINTAIN_PROPERTY
is present and set to true
and the ClientConstants.COOKIE_MAP
is set to cookieMap
.
Example 14-3 Setting a Cookie in a Client Stub
import HTTPClient.Cookie; Map cookieMap = new HashMap(); Cookie cookie = new Cookie("name", "value", "oracle.com", "/", null, false); Cookie cookie2 = new Cookie("name2", "value2", "oracle.com", "/", null, false); cookieMap.put(cookie, cookie); cookieMap.put(cookie2, cookie2); ((Stub) port)._setProperty(ClientConstants.COOKIE_MAP, cookieMap); ((Stub) port)._setProperty(Stub.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE); ...
Oracle JDeveloper enables you to build client applications that use Web services. It supports OC4J J2SE Web service clients by allowing you to create Java stubs from Web service WSDL descriptions. You can use these stubs to access existing Web services. For more information, see the JDeveloper on-line help.
For more information on:
assembling Web services from a WSDL, see Chapter 5, "Assembling a Web Service from a WSDL".
assembling stateful Web services, see Chapter 6, "Assembling a Web Service with Java Classes".
assembling Web services from EJBs, see Chapter 7, "Assembling a Web Service with EJBs".
assembling Web services from a JMS queue or topic, see Chapter 8, "Assembling Web Services with JMS Destinations".
assembling Web services from database resources, see Chapter 9, "Developing Database Web Services".
assembling Web services with J2SE 5.0 Annotations, see Chapter 10, "Assembling Web Services with Annotations".
building J2EE clients, see Chapter 13, "Assembling a J2EE Web Service Client".
improving performance by data chunking, see "Enabling Chunked Data Transfer for HTTP 1.1".
using the WebServicesAssembler tool to assemble Web services, see Chapter 17, "Using WebServicesAssembler".
packaging and deploying Web services, see Chapter 18, "Packaging and Deploying Web Services".
JAR files that are needed to assemble a client, see Appendix A, "Web Service Client APIs and JARs".
Web services interoperability, see "Ensuring interoperable Web Services" in the Oracle Application Server Advanced Web Services Developer's Guide.
using quality of service features in Web service clients, see "Managing Web Services" in the Oracle Application Server Advanced Web Services Developer's Guide.
adding security to a Web service, see the Oracle Application Server Web Services Security Guide.
how to write clients to access Web services secured on the transport level, see "Adding Transport-level Security for Web Services Based on EJBs" and "Accessing Web Services Secured on the Transport Level" in the Oracle Application Server Web Services Security Guide.
adding reliability to a Web service, see "Ensuring Web Service Reliability" in the Oracle Application Server Advanced Web Services Developer's Guide.
adding an auditing and logging configuration to a Web service, see "Auditing and Logging Messages" in the Oracle Application Server Advanced Web Services Developer's Guide.
processing nonstandard data types, see "Custom Serialization of Java Value Types" in the Oracle Application Server Advanced Web Services Developer's Guide.
the JAX-RPC mapping file, see "JAX-RPC Mapping File Descriptor" in the Oracle Application Server Advanced Web Services Developer's Guide.
data types supported by OracleAS Web Services, see "Mapping Java Types to XML and WSDL Types" in the Oracle Application Server Advanced Web Services Developer's Guide.
JDeveloper tool support for Web service development, see the JDeveloper on-line help.