How to write a RPC Literal Top-Down Service

Date: 19-Sep-2003

After reading this how-to document you should be able to:

  • Understand what is a JAX-RPC Web Service
  • Write a RPC literal Web Service using a top down approach

Introduction

This document demonstrates how to develop an RPC Literal Web Service for Oracle Application Server 10g using the Top-Down paradigm i.e. start with the WSDL and generate all the classes and service artifacts using the definition of types and operations in the WSDL. Web Services Description Language (WSDL) is an XML-based language used to define Web services and describe how to access them. WSDL file describes the operations (i.e. methods) exposed by the service, the parameters taken by these operations, the request and response messages associated with each operation call. WSDL also specifies the location from where the Web Service can be accessed.

RPC Literal webservices are services that are invoked by clients in the same way that remote objects are invoked in the Java language using Remote Procedure Calls. Oracle Application Server 10g provides the marshalling support and location transparency so methods, method data, and return data are translated into SOAP messages and the remote endpoint is invoked even though the client appears to be calling a local object. The Top-Down paradigm implies that you are starting with a WSDL and will write the implementation classes after the WSDL has been processed and the necessary service classes and interfaces are generated. Once the generation process is complete the Web Service implementation class can be compiled and included into the Web Service archive (EAR file) to be deployed to OC4J

Software Requirements

  • Oracle Application Server Containers for J2EE 10g or later. You can download the OC4J from Oracle Technology Network. 

  • JDK1.4.x or above This can be downloaded here .

  • Apache Ant v1.5 or later.

  • How To Example source code zip.

Description

Overview of JAX-RPC Web Services

The Java API for XML-based remote procedure calls (JAX-RPC) provides standard way of building portable and interoperable SOAP based Web Services. It simplifies the process of building Web services that incorporate XML-based RPC . It defines mappings between XML types and Java types that attempt to hide the details of XML and provide a familiar method-call paradigm. Read more on JAX-RPC Web Services here.

The How-To Example

This how-to explains how to create a simple JAX-RPC Web Service using a WSDL file and a client to access the Web Service. The Web Service provides various methods that show different types of input parameters and return types that JAX -RPC Web Services can handle. On each method call of Web Service, the server echoes out the data type and values of the input parameter to the method.

The how to uses Oracle's Web Services Assembler tool to generate the service artifacts. The Web Service assembler tool takes an XML config file that describes the service as input, generates service artifacts, compiles all the classes and produces an Enterprise Archive file that can be deployed to an application server to run the Web Service.

Here is the WSDL file that will be used to generate the Web Service artifacts. Listing 1 shows the part of WSDL definition required to define a method named echoStringArray that takes a String array as input and return a String array.

<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://soapbuilders.org/rpc-lit-test/types">
<!-- define a complex type for array of string -->
<element name="stringItem" type="xsd:string" />
<complexType name="ArrayOfstring">
<sequence>
<element ref="types:stringItem" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>

</schema>
</types>

<!--define request and response message for echoStringArray rpc operation -->
<message name="echoStringArrayRequest">
<part name="inputStringArray" type="types:ArrayOfstring"/>
</message>
<message name="echoStringArrayResponse">
<part name="return" type="types:ArrayOfstring"/>
</message> <portType name="SoapTestPortTypeRpc">
<!-- define echoStringArray rpc operation using input and output message-->
<operation name="echoStringArray" parameterOrder="inputStringArray">
<input message="tns:echoStringArrayRequest"/>
<output message="tns:echoStringArrayResponse"/>
</operation>
</portType>

<binding name="Soap11TestRpcLitBinding" type="tns:SoapTestPortTypeRpc">
<soap11:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

<!-- bind echoStringArray rpc operation -->
<operation name="echoStringArray">
<soap11:operation soapAction="http://soapinterop.org/"/>
<input>
<soap11:body use="literal" namespace="http://soapbuilders.org/rpc-lit-test" />
</input>
<output>
<soap11:body use="literal" namespace="http://soapbuilders.org/rpc-lit-test" />
</output>
</operation>
</binding>
<service name="WhiteMesaSoapRpcLitTestSvc">
<port name="Soap11TestRpcLitPort" binding="tns:Soap11TestRpcLitBinding">
<soap11:address location="http://localhost:8888/test-rpc-lit"/>
</port>
</service>

Listing 1

Listing 2 shows the part of Web Service implementation class, that defines echoStringArray method.

public class RpcLitTopdownImpl implements SoapTestPortTypeRpc{
  private Logger m_logger;
  
  public RpcLitTopdownImpl(){
    // create an anonymous logger
m_logger = Logger.getAnonymousLogger ("oracle.demo.topdownrpc.service.RpcLitTopdownImpl"); // Set the log level specifying which message levels will // be logged by this logger
m_logger.setLevel(Level.ALL); // create the formatter
SimpleFormatter formatter = getFormatter(); // parent handler for logging messages should not be used
m_logger.setUseParentHandlers(false); // Add a log Handler to receive logging messages.
m_logger.addHandler(new StreamHandler(System.out,formatter){
public synchronized void publish(LogRecord record){ // Format and publish a LogRecord.
super.publish(record);
flush();
}
});
} public ArrayOfstring echoStringArray(ArrayOfstring inputStringArray) throws RemoteException {
//get the string array
String array[] = inputStringArray.getStringItem(); // log the value of each element in String array
for(int i = 0; i < array.length;i++){
m_logger.log(Level.INFO, "demo.stringarraydata.msg",new Object[]{"String",
"" + i,
array[i]});
} // return the ArrayofString type to client
return inputStringArray;
}
....
....
}

Listing 2

The class implements the SoapTestPortTypeRpc interface that declares the methods exposed by the Web Service. The method echoStringArray takes input parmeter of user defined type ArrayOfString. The method iterates through the string array and logs the values of each String element to the console. The class ArrayOfString, the interface SoapTestPortTypeRpc and other similar artifacts are generated by the Web Services Assembler tool using the information provided in the WSDL.

The implementation class methods use java.util.logging.Logger class to log the values of parameters to the OC4J console. The complete code can be seen here.

Listing 3 shows the part of client code that calls the echoStringArray() method of the Web Service.

Public SoapTestPortTypeRpc initializeService() throws Exception{
  WhiteMesaSoapRpcLitTestSvc service = (WhiteMesaSoapRpcLitTestSvc)
m_factory.loadService(new URL(m_serviceURL),
WhiteMesaSoapRpcLitTestSvc.class, null); SoapTestPortTypeRpc port = service.getSoap11TestRpcLitPort();
((Stub)port)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,m_serviceURL); return port;
} private void demoEchoStringArray() throws Exception{
m_logger.log(Level.INFO,"demo.echoStringArray.enter");

//initialize Service and get the handle of remote Web Service
SoapTestPortTypeRpc port = initializeService();

// create object of user defined type containing String // array as an attribute
ArrayOfstring aos = new ArrayOfstring(new String[]{ VAL_STRING1,VAL_STRING2});

// call method on Web Service
aos = port.echoStringArray(aos);
// log the values of elements in String array return by the Service
m_logger.log(Level.INFO,"demo.echoStringArray.msg",new Object[]{
new String() + aos.getStringItem()[0],
new String() + aos.getStringItem()[1]}); m_logger.log(Level.INFO,"demo.echoStringArray.exit");
}

Listing 3

The complete client code can be seen here.

Preparing and Running the Example

Extract the rpc-lit.zip file. This will create rpc-lit directory containing documentation and source code of the how-to.

In the following steps <OC4J> refers to directory where OC4J is installed.

Step a:

Start OC4J from <OC4J>/j2ee/home directory on a command promt as follows:

java -jar oc4j.jar

Step b:

Navigate to rpc-lit, the sample home directory on new command window . Include ANT_HOME/bin in the PATH environment variable. Set the following properties required by the ant build script

  • Set the ORACLE_HOME environment variable to your <OC4J> root directory.
    Example:

    Windows : set ORACLE_HOME=c:\oc4j10g
    Unix    : export ORACLE_HOME=/home/oc4j10g 
  • Set the J2EE_HOME environment variable to your <OC4J>/j2ee/home directory.
    Example:

    Windows : set J2EE_HOME=c:\oc4j10g\j2ee\home
    UNIX    : export J2EE_HOME=/home/oc4j10g/j2ee/home 
  • Set the JAVA_HOME environment variable to your Java installation directory.
    Example:

    Windows : set JAVA_HOME=c:\j2sdk1.4
    UNIX    : export JAVA_HOME=/home/j2sdk1.4
Quick Start

Once you have the server configured and running, execute the following command from the prompt in Step b:

>ant

The service artifacts and implementation class will be compiled and placed into a WAR which is then placed into an EAR.

The EAR will be deployed to OC4J. Next the stubs and client will be compiled. Finally the service will be invoked by the client and you should see the output both in the server's message output and on the stdout of the client.

Step by Step
Step 1:

Generate the service artifacts. Execute the following command:

This step will generate the service artifacts which include interfaces and Tie classes. Examine the rpc-lit/config/service-config.xml file. Notice that the implementation-class-name element is filled in with the implementation class provided by the demo. This class is not compiled yet so WSA will generate the artifacts and use the class name as a place holder. Once the artifacts are generated, the implementation class will have to be compiled and WSA will have to be run again with the same config file.

To generate the service artifacts type: ant gen-service.

The source code for the service-artifacts will be placed in the build/src/service directory using the package name oracle.demo.topdownrpc.service. Examine the type-mapping.xml file. This file is used to instruct WSA how to map types to package name. A namespace URI is mapped to a specific package name. Notice that this example maps its types to the package oracle.demo.topdownrpc.types. So for service artifacts the types are generated in rpc-lit/src/oracle/demo/topdownrpc/types.

Step 2:

Generate the stubs (client artifacts)

This step will generate the stubs for the service. A client application uses a stub to invoke operations on a remote service. Examine the file rpc-lit/config/client-config.xml. This is the configuration file that the WebServices Assembler (WSA) tool uses to generate the stubs.

To generate the stubs type: ant gen-stubs

The source for the stubs will be placed in rpc-lit/build/src/client.

Step 3:

Update the implementation.

This step will compile the implementation classes and regenerate the EAR file that will now contain both service artifacts and the implementation class. Examine the file RpcLitTopdownImpl.java under rpc-lit/src/service/oracle/demo/topdowndoclit/service. Notice that the class implements SoapTestPortTypeRpc which is a service artifact and thus generated by the tool. Before the first step there were no generated files so compiling this class would have failed. Now that you have already ran the gen-service task you are ready to compile the class and update the EAR.

To update the implementation type: ant update-impl

Step 4:

Deploy the Service

The service is now ready to be deployed. Examine the rpclit_topdown.ear in the rpc-lit/dist directory using WinZip or any zip file browser. It should contain a WAR file named rpclit_topdown-web.war. This WAR file contains all the service artifacts, implementation classes, as well as the web deployment descriptor (web.xml) and the jaxrpc deployment descriptor (jaxrpc-ri-runtime.xml).

To deploy this ear to a running instance of oc4j type: ant deploy-demo

After this task is complete you can check your application by typing in the following url into a web browser: http://localhost:8888/rpclit_topdown/rpclit_topdown

You should be able to invoke some of the methods on this service from the web browser. Currently, invoking services using the browser is restricted to simple types.

Step 5:

Run the demo.

You are now ready to run the client. Examine the file RpcLitTopdownClient.java in rpc-lit/src/client/oracle/demo/topdownrpc/ . Notice that this class uses the stubs to set an endpoint address and to invoke methods on the remote service.

To run the client type: ant run-demo

You should see some sample output on both the oc4j and client output screens.

To undeploy the Web Service execute the command : ant teardown-demo

Resources

Summary

This how-to document explained how write a RPC literal Web Service from the WSDL using the top down approach.


E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy