Given an set of requirements, design and develop a Web sevice client, such as a J2EE client and a stand-alone Java client, using the appropriate JAX-RPC client connection style.

JAX-RPC Client Environment:

There are three Web Service Client programming models:

  1. Stub-based (least dynamic)

    Both interface (WSDL) and implementation (stub) created at compile time.

  2. Dynamic proxy

    Interface (WSDL) created at compile time. Implementation (dynamic proxy) created at runtime.

  3. Dynamic invocation interface (DII)

    Both interface (WSDL) and implementation created at runtime.

Stub-based Invocation Model

Steps for Stub-Based Invocation Client:

  1. Generate Stubs

  2. Create Client code

  3. Compile the Client code with remote interface and stubs in CLASSPATH

  4. Run the Client with JAX-RPC generated code and runtime

Stand-alone Stub-based Client example:

package com.example;

import javax.xml.rpc.Stub;

public class HelloClient {
	public static void main(String[] args) {
		try {
			Stub stub = (Stub) (new MyHelloService_Impl().getHelloIFPort());
			stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, args[0]);
			HelloIF hello = (HelloIF) stub;
			println(hello.sayHello("Duke!"));
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}					
					

J2EE Stub-based Client example:

package com.example;

import javax.xml.rpc.Stub;

public class HelloClient {
	public void callSayHello {
		try {
			Context ic = new InitialContext();
			Service service = (Service) ic.lookup("java:comp/env/service/HelloService");
			HelloIF hello = (HelloIF) service.getHelloServiceProviderPort();
			println(hello.sayHello("Duke!"));
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}
					

Dynamic Proxy-based Invocation Model

Dynamic Proxy Client example:

package com.example;

import java.net.URL;
import javax.xml.rpc.Service;
import javax.xml.rpc.JAXRPCException;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceFactory;

public class HelloClient {
	public static void main(String[] args) {
		try {
			String UrlString = "http://localhost:8080/ProxyHelloWorld.wsdl";
			String nameSpaceUri = "http://sample.proxy.org/wsdl";
			String serviceName = "HelloWorld"; // maps to service name in WSDL
			String portName = "HelloIFPort";   // maps to port name in WSDL
			URL helloWsdlUrl = new URL(UrlString);
			
			ServiceFactory serviceFactory = ServiceFactory.newInstance();
			
			// Create a Service object named helloService
			Service helloService = serviceFactory.createService(helloWsdlUrl, new QName(nameSpaceUri, serviceName));
			
			// Destination for service endpoint retrieval
			QName qn = new QName(nameSpaceUri, portName);
			
			// Create a proxy with type of interface 'com.example.HelloIF'
			HelloIF myProxy = (HelloIF) helloService.getPort(qn, com.example.HelloIF.class);
			
			System.out.println(myProxy.sayHello("Duke"));
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}
					
WSDL:

...
<service name="HelloWorld">
	<port name="HelloIFPort" binding="tns:HelloWorldBinding">
		<soap:address location="http://example.com/HelloWorld"/>
	</port>
</service>
...
										
					

The javax.xml.rpc.Service interface :


package javax.xml.rpc;

import javax.xml.namespace.QName;
import javax.xml.rpc.encoding.TypeMappingRegistry;
import javax.xml.rpc.handler.HandlerRegistry;

public interface Service {

    /**
     * The getPort method returns either an instance of a generated
     * stub implementation class or a dynamic proxy. A service client
     * uses this dynamic proxy to invoke operations on the target
     * service endpoint. The <code>serviceEndpointInterface</code>
     * specifies the service endpoint interface that is supported by
     * the created dynamic proxy or stub instance.
     */
    public java.rmi.Remote getPort(QName portName, Class serviceEndpointInterface)
            throws ServiceException;

    /**
     * The getPort method returns either an instance of a generated
     * stub implementation class or a dynamic proxy. The parameter
     * <code>serviceEndpointInterface</code> specifies the service
     * endpoint interface that is supported by the returned stub or
     * proxy. In the implementation of this method, the JAX-RPC
     * runtime system takes the responsibility of selecting a protocol
     * binding (and a port) and configuring the stub accordingly.
     * The returned <code>Stub</code> instance should not be
     * reconfigured by the client.
     */
    public java.rmi.Remote getPort(Class serviceEndpointInterface)
        throws ServiceException;

    public Call[] getCalls(QName portName) throws ServiceException;
    public Call createCall(QName portName) throws ServiceException;
    public Call createCall(QName portName, QName operationName)
        throws ServiceException;
    public Call createCall(QName portName, String operationName)
        throws ServiceException;
    public Call createCall() throws ServiceException;
    public QName getServiceName();
    public java.util.Iterator getPorts() throws ServiceException;
    public java.net.URL getWSDLDocumentLocation();
    public TypeMappingRegistry getTypeMappingRegistry();
    public HandlerRegistry getHandlerRegistry();
}
				    			
				    

Dynamic Invocation Interface (DII) Model

Dynamic Invocation Interface (DII) Client example:

package com.example;

import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import javax.xml.rpc.JAXRPCException;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.ParameterMode;

public class HelloClient {
	private static String endpoint = "http://localhost:8080/dynamic-jaxrpc/dynamic";
	private static String qnameService = "Hello";
	private static String qnamePort = "HelloIF";
	private static String BODY_NAMESPACE_VALUE = "http://dynamic.org/wsdl";
	private static String ENCODING_STYLE_PROPERTY = "javax.xml.rpc.encodingstyle.namespace.uri";
	private static String NS_XSD = "http://www.w3.org/2001/XMLSchema";
	private static String URI_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
	
	public static void main(String[] args) {
		try {
			ServiceFactory factory = ServiceFactory.newInstance();
			Service service = factory.createService(new QName(qnameService));
			
			QName port = new QName(qnamePort);
			
			//create JAX-RPC Call using JAX-RPC Service's createCall() method.
			Call call = service.createCall(port);
			
			// Configure your Call instance with its setter methods
			call.setTargetEndpointAddress(endpoint);
			call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(true));
			call.setProperty(Call.SOAPACTION_URI_PROPERTY, "");
			call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING);			
			QName QNAME_TYPE_STRING = new QName(NS_XSD, "string");
			call.setReturnType(QNAME_TYPE_STRING);
			call.setOperationName(new QName(BODY_NAMESPACE_VALUE "sayHello"));
			call.addParameter("String_1", QNAME_TYPE_STRING, ParameterMode.IN);
			String[] params = { "Duke!" };
			
			// Invoke the WS operation using the JAX-RPC Call's invoke method
			String result = (String) call.invoke(params);
			
			System.out.println(result);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}
					

The javax.xml.rpc.Call interface:

					
package javax.xml.rpc;

import javax.xml.namespace.QName;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * The <code>javax.xml.rpc.Call</code> interface provides support
 * for the dynamic invocation of a service endpoint. The
 * <code>javax.xml.rpc.Service</code> interface acts as a factory
 * for the creation of <code>Call</code> instances.
 */
public interface Call {

    /**
     * Standard property: User name for authentication
     */
    public static final String USERNAME_PROPERTY = "javax.xml.rpc.security.auth.username";

    /**
     * Standard property: Password for authentication
     */
    public static final String PASSWORD_PROPERTY = "javax.xml.rpc.security.auth.password";

    /**
     * Standard property for operation style. This property is
     * set to "rpc" if the operation style is rpc; "document"
     * if the operation style is document.
     */
    public static final String OPERATION_STYLE_PROPERTY = "javax.xml.rpc.soap.operation.style";

    /**
     * Standard property for SOAPAction. This boolean property
     * indicates whether or not SOAPAction is to be used. The
     * default value of this property is false indicating that
     * the SOAPAction is not used.
     */
    public static final String SOAPACTION_USE_PROPERTY = "javax.xml.rpc.soap.http.soapaction.use";

    /**
     * Standard property for SOAPAction. Indicates the SOAPAction
     * URI if the <code>javax.xml.rpc.soap.http.soapaction.use</code>
     * property is set to <code>true</code>.
     */
    public static final String SOAPACTION_URI_PROPERTY = "javax.xml.rpc.soap.http.soapaction.uri";

    /**
     * Standard property for encoding Style:  Encoding style specified
     * as a namespace URI. The default value is the SOAP 1.1 encoding
     * <code>http://schemas.xmlsoap.org/soap/encoding/</code>
     */
    public static final String ENCODINGSTYLE_URI_PROPERTY = "javax.xml.rpc.encodingstyle.namespace.uri";

    /**
     * Standard property: This boolean property is used by a service
     * client to indicate whether or not it wants to participate in
     * a session with a service endpoint. If this property is set to
     * true, the service client indicates that it wants the session
     * to be maintained. If set to false, the session is not maintained.
     * The default value for this property is <code>false</code>.
     */
    public static final String SESSION_MAINTAIN_PROPERTY = "javax.xml.rpc.session.maintain";

    /**
     * Indicates whether <code>addParameter</code> and
     * <code>setReturnType</code> methods
     * are to be invoked to specify the parameter and return type
     * specification for a specific operation.
     */
    public boolean isParameterAndReturnSpecRequired(QName operationName);

    /**
     * Adds a parameter type and mode for a specific  operation.
     * Note that the client code may not call any
     * <code>addParameter</code> and <code>setReturnType</code>
     * methods before calling the <code>invoke</code> method. In
     * this case, the Call implementation class determines the
     * parameter types by using reflection on parameters, using
     * the WSDL description and configured type mapping registry.
     */
    public void addParameter(String paramName, QName xmlType, ParameterMode parameterMode);

    /**
     * Adds a parameter type and mode for a specific  operation.
     * This method is used to specify the Java type for either
     * OUT or INOUT parameters.
     *
     * @param paramName Name of the parameter
     * @param xmlType XML datatype of the parameter
     * @param javaType The Java class of the parameter
     * @param parameterMode Mode of the parameter-whether
     *                ParameterMode.IN, OUT or INOUT
     */
    public void addParameter(String paramName, QName xmlType, Class javaType, ParameterMode parameterMode);

    /**
     * Gets the XML type of a parameter by name.
     */
    public QName getParameterTypeByName(String paramName);

    /**
     * Sets the return type for a specific operation. Invoking
     * <code>setReturnType(null)</code> removes the return
     * type for this Call object.
     */
    public void setReturnType(QName xmlType);

    /**
     * Sets the return type for a specific operation.
     */
    public void setReturnType(QName xmlType, Class javaType);

    /**
     * Gets the return type for a specific operation.
     */
    public QName getReturnType();

    /**
     * Removes all specified parameters from this <code>Call</code> instance.
     * Note that this method removes only the parameters and not
     * the return type. The <code>setReturnType(null)</code> is
     * used to remove the return type.
     */
    public void removeAllParameters();

    /**
     * Gets the name of the operation to be invoked using this Call instance.
     */
    public QName getOperationName();

    /**
     * Sets the name of the operation to be invoked using this
     * <code>Call</code> instance.
     */
    public void setOperationName(QName operationName);

    /**
     * Gets the qualified name of the port type.
     */
    public QName getPortTypeName();

    /**
     * Sets the qualified name of the port type.
     */
    public void setPortTypeName(QName portType);

    /**
     * Sets the address of the target service endpoint.
     * This address must correspond to the transport specified
     * in the binding for this <code>Call</code> instance.
     */
    public void setTargetEndpointAddress(String address);

    /**
     * Gets the address of a target service endpoint.
     */
    public String getTargetEndpointAddress();

    /**
     * Sets the value for a named property. JAX-RPC specification
     * specifies a standard set of properties that may be passed
     * to the <code>Call.setProperty</code> method.
     */
    public void setProperty(String name, Object value);

    /**
     * Gets the value of a named property.
     */
    public Object getProperty(String name);

    /**
     * Removes a named property.
     */
    public void removeProperty(String name);

    /**
     * Gets the names of configurable properties supported by
     * this <code>Call</code> object.
     */
    public Iterator getPropertyNames();

    // Remote Method Invocation methods

    /**
     * Invokes a specific operation using a synchronous request-response
     * interaction mode.
     */
    public Object invoke(Object[] inputParams) throws java.rmi.RemoteException;

    /**
     * Invokes a specific operation using a synchronous request-response
     * interaction mode.
     */
    public Object invoke(QName operationName, Object[] inputParams)
        throws java.rmi.RemoteException;

    /**
     * Invokes a remote method using the one-way interaction mode. The
     * client thread does not block waiting for the completion of the
     * server processing for this remote method invocation. This method
     * must not throw any remote exceptions. This method may throw a
     * <code>JAXRPCException</code> during the processing of the one-way
     * remote call.
     */
    public void invokeOneWay(Object[] params);

    /**
     * Returns a <code>Map</code> of {name, value} for the output parameters of
     * the last invoked operation. The parameter names in the
     * returned Map are of type <code>java.lang.String</code>.
     */
    public Map getOutputParams();

    /**
     * Returns a <code>List</code> values for the output parameters
     * of the last invoked operation.
     */
    public List getOutputValues();
}

					

Table 4.1. Usage scenarios of the three Web Service service client styles.

Static stubDynamic proxyDynamic Invocation Interface (DII)
Web service not expected to change Some changes to the Web Service expected, such as the location of the service Considerable changes to the Web service expected, such as:
  • Location of the service

  • Request/response format

  • Data types

Most common scenarioLess commonLess common
You can generate a stub class either from WSDL (using WSDL2Java) or from a service endpoint interface. A generated stub class is required to implement both javax.xml.rpc.Stub and the service endpoint interface. This stub interface provides APIs to configure stubs by setting properties like endpoint address, session, user name, password, etc. The client at runtime creates dynamic proxy stubs using the javax.xml.rpc.Service interface. The client has a priori knowledge of the WSDL and the service it is going to invoke. It uses the javax.xml.rpc.ServiceFactory classes to create the service and get the proxy. This software pattern eliminates the need for clients to know in advance a service's exact name and parameters. A DII client can discover this information at runtime using a service broker that can look up the service's information. This flexibility in service discovery enables the run-time system to use service brokers, which can adopt varying service discovery mechanisms - ebXML registries, UDDI, etc.

Professional hosting     Belorussian informational portal         Free SCWCD 1.4 Study Guide     Free SCBCD 1.3 Study Guide     SCDJWS 1.4 Quiz     Free IBM Certified Associate Developer Study Guide     Free SCJP 5.0 (Tiger) Study Guide     Free Mock Exam Engine     IBM Test 000-287. Enterprise Application Development with IBM WebSphere Studio, V5.0 Study Guide     IBM Test 000-255. Developing with IBM Rational Application Developer for WebSphere Software V6 Study Guide