| By Aravilli Srinivasa Rao | Article Rating: |
|
| December 16, 2002 12:00 AM EST | Reads: |
18,281 |
The RPC mechanism enables a remote procedure call from a client to be communicated to a remote server. SOAP RPC supports three types of parameter modes - IN, OUT, and INOUT - for remote method invocation. In this article I'll explain how JAX-RPC supports SOAP RPC parameter modes and how to use JAX-RPC parameter modes with Apache Axis.
JAX-RPC
JAX-RPC provides a means for performing RPC over SOAP. It provides rules for client code generation, SOAP Binding, mapping from Java to WSDL and WSDL to Java, type mappings between Java and XML data types, and client APIs for constructing Web service invocations.
JAX-RPC defines one static model and two dynamic models for the client side to invoke a remote procedure. In the static model, stubs are used and the code-generation tools generate the stubs. One dynamic model is based on generating a proxy object dynamically using java reflection APIs and another is based on Dynamic Invocation an Interface (DII) using the Call object. The examples shown in this article use DII rather than the static model.
JAX-RPC interfaces
On the client side, JAX-RPC defines the following major interfaces:
JAX-RPC supports the following three types of invocation models:
The Synchronous Request-Response Mode and One-Way RPC Mode are achieved by the JAX-RPC DII Call interface.
JAX-RPC Parameter Modes
JAX-RPC uses pass by copy semantics for parameter passing in a remote method invocation. The JAX-RPC specification does not support the object-by-reference mode for remote method invocations. JAX-RPC specifies the following rules for the IN, OUT and INOUT parameter passing modes and return value:
Holder Classes
Holder classes enable the mapping to preserve the intended operation signature and parameter passing semantics. A holder class is simply a class that contains an instance of its type. According to the JAX-RPC specification, each Holder class provides the following methods and fields
For example, the holder for the Double class would be:
public final class DoubleHolder implements Holder {
public double value;
public DoubleHolder() { }
public DoubleHolder(double value) {
this.value = value;
}
}
In this article, I've used JAX-RPC Synchronous Request-Response Mode to explain the following parameter modes using Apache Axis.
- in parameters using simple types
- in and out parameters using simple types
- inout parameters using simple types
- out parameters using complex types
This example deals with developing a currency converter soap service (conversion from dollars to rupees). The service takes only one input parameter of simple type and returns a simple type.
Developing the SOAP Service
For example, develop a currency converter SOAP service as:
package com.mydomain.SampleService;
public class SampleService {
public double convertcurrencyin(double in) {
double res = in * 48;
return res;
}
}
Here I've used the default rate; it should be replaced by the actual value.
Deploying the SOAP Service
Create a Web Services Deployment Descriptor file (deploy.wsdd) in order to deploy the Web service (see Listing 1). Deploy the service using the deploy.wsdd file as described in the Axis documentation.
Developing the SOAP Client
Create a service using ServiceFactory in order to create the Call objects.
Service service = new Service();
Call call = (Call) service.createCall ( );
String endpointURL = http://localhost:8080/axis/servlet/AxisServlet;
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
After creating a Call object, configure the call object with the operation (method) name, parameter types, and parameter modes like IN or OUT or INOUT and return type (see Listing 2).
After setting the parameter modes, parameter types, and return types, invoke the target end point by passing the parameters and get the result. The invoke( ) method calls a specified operation using the synchronous request-response interaction mode. Use the invoke OneWay( ) method for using the one-way interaction mode. The invoke method blocks until the remote service receives the method call and return either a response or an exception, whereas invokeOneWay( ) doesn't block and this method is not allowed to propagate a remote exception to the client.
Double db = new Double (4.0);
Object ret = call.invoke( new Object[] { db} );
Use the Axis TCP Monitor tool to see the request/response message between the SOAP server and the client on the wire. The SOAP Messages look like Listing 3.
Observe the request and response message and notice that Response is appended to the name of operation i.e. convertcurrencyin. Apache Axis appends operation/ method name for the return element where as some SOAP servers don't. (See source code for this article, available at www.sys-con.com/webservices/sourcec.cfm.)
IN and OUT Parameters Using Simple Types
This example shows how to develop a service and client using in and out parameters. The out parameters are achieved using Holder classes.
Developing the SOAP Service
In this example the client sends the currency to be converted as an input parameter to the service and the client receives the converted currency as output by using the holder classes. The service looks like:
package com.mydomain.SampleService;
public class SampleService {
public int convertcurrencyout(double in, DoubleHolder dh) {
double res = in * 48;
dh.value = res;
return 1;
}
}
Deploying the SOAP Service
Add the following entries to the deploy.wsdd file as a child element of the service element and deploy the service.
<operation name="convertcurrencyout">
<parameter name="arg1" mode="IN"/>
<parameter name="result" mode="OUT"/>
</operation>
A parameter element is used to specify parameter modes and parameter names. This is one of the ways that Axis SOAP server gets the information about the parameters.
Developing the SOAP Client
Create a Call object and configure the objects with the service details (see Listing 4). Parameters of the type OUT need not be passed to the invoke method.
In order to get the output parameters from the target end point service, use the method getOutputParams( ) on the Call object as shown in Listing 5.
The messages in Listing 6 are sent and received from the SOAP server. Observe the SOAP response, it has an additional element "result" after the return element. Each output parameter will have an element in the soap response with the output value.
INOUT Parameters Using Simple Types
SOAP INOUT parameters are achieved using Holder classes.
Developing the SOAP Service
In this example the Client sends the currency as an instance of DoubleHolder. The service accesses the currency by using the holder's value field and setting the converted currency in the same field.
The service looks like:
package com.mydomain;
import javax.xml.rpc.holders.*;
public class SampleService {
public int convertcurrencyinout(DoubleHolder dh) {
dh.value = dh.value * 48;
return 1;
}
}
Developing the SOAP Client
Create the Call object and configure it with the service details in Listing 7.
Observe that code and notice that the parameter mode is ParameterMode.INOUT and the passed parameter is the holder's wrapper class, i.e., Double. There is no difference in getting the output from the service for output parameters and inout parameters. On the wire the SOAP message looks like Listing 8.
So far I've discussed simple data types only. What about complex data types? JAX-RPC specifies the semantics for Java serialization in terms of XML mapping. Axis provides default serialization and deserialization for the JavaBeans. In my next example I've used user-defined holders (AddressHolder) for the output parameter and user-defined type (Address) and used axis default bean serialization. Use Apache's Java to WSDL tool to generate a WSDL file. It generates complex data types for the user-defined types like Address Object. I have not used WSDL to invoke the remote service
OUT Parameters Using Complex Types
In this example the client sends an order ID to the remote SOAP service and the service will return the shipment address as output parameter in the response message. Since Shipment Address is an output parameter, create a holder class to hold the Address and create Address class according to the JavaBeans Specification.
SOAP Service
package com.mydomain;
public class SampleService {{
public String getShipmentDetail(String orderId, AddressHolder adrh) {
Address adr = new Address();
adr.setstreet("CunninghamRoad");
adr.setcountry("INDIA");
adrh.value = adr;
return orderId;
}
Add the following entries in the deploy.wsdd file inside the service element and register the bean mappings as shown below.
<operation name="getShipmentDetail">
<parameter name="orderId" mode="IN"/>
<parameter name="result" mode="OUT"/>
</operation>
<beanMapping qname="myNS:Address" xmlns:myNS="urn:MyService"
languageSpecificType="java:com.mydomain.Address"/>
SOAP Client
On the client side, register the serializers and deserializers for the user-defined data types, i.e., for the Address object.
QName qn = new QName( "urn:SampleService", "Address" );
call.registerTypeMapping(Address.class, qn,
new org.apache.axis.encoding.ser.BeanSerializerFactory(Address.class, qn),
new org.apache.axis.encoding.ser.BeanDeserializerFactory(Address.class, qn));
Once the type mappings are registered, pass the parameters and invoke the service as shown:
call.setOperationName( new QName("SampleService", "getShipmentDetail") );
call.addParameter( "orderId", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter( "result",qn,ParameterMode.OUT);
call.setReturnType( org.apache.axis.encoding.XMLType.XSD_STRING );
String orderId = "ORD_001";
String val = (String)call.invoke( new Object[] {orderId} );
Retrieving the output parameter is the same as for the simple types. Generating the SOAP message on the wire looks like Listing 9.
If you want to send a user-defined Holder (AddressHolder) as an INOUT parameter to the remote SOAP service, then pass the user-defined type (Address) as an INOUT parameter and register the type mappings.
References
Published December 16, 2002 Reads 18,281
Copyright © 2002 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
Related Links
More Stories By Aravilli Srinivasa Rao
Aravilli Srinivasa Rao, a software analyst at Hewlett-Packard, is technical lead for the development of HP's public UDDI Registry. He has worked with HP's e-speak and Total-e-Server (J2EE Application Server) products and is currently involved in the design and development of the projects in the mobile space to implement Web services.





































