Oracle9i Application Server Oracle9iAS SOAP Developer's Guide
Release 1 (v1.0.2.2)

Part Number A90297-01
Go To Documentation Library
Library
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

3
SOAP Parameters and Encodings

This chapter describes the procedures you use to write a SOAP Java service, to deploy the service, and to write a SOAP Java client for a service that uses arrays and other nonscalar types for parameters or return values (Table 2-1 lists the scalar types). In addition, this chapter provides information on SOAP encodings. You should be familiar with the information in Chapter 2, "Using Oracle SOAP with Java Services" before reading this chapter.

This chapter covers the following topics:

Writing a SOAP Java Service Using User-Defined Types

Developing a SOAP Java service involves building a Java class that includes one or more methods that generate responses to incoming calls. This section describes the procedures for developing an AddressBook service that provides methods to get an address, save a new address, and list all addresses in an AddressBook (the AddressBook data is stored in memory). These methods take arguments and expand on the basic SOAP Java service functionality shown in Chapter 2, "Using Oracle SOAP with Java Services".

The complete Address Book service is supplied in the directory $SOAP_HOME/samples/addressbook on UNIX or %SOAP_HOME%\samples\addressbook on Windows NT.

To develop a SOAP Java service that includes user-defined types as parameters or return values, you must complete the following steps:

Specifying a Package Name for the Service

Create a SOAP Java service by writing a class containing methods that are deployed as a SOAP service. When looking at the AddressBook service supplied with Oracle SOAP, note that the single jar file, samples.jar contains a samples package, that includes several samples (the jar file is in the directory $SOAP_HOME/webapps/soap/WEB-INF/lib). The first line of AddressBook.java specifies the package name for the service, addressbook, which is added to samples.jar.

package samples.addressbook;

Defining Java Methods Using Parameters with User-Defined Types

The Addressbook service is implemented with a public class AddressBook and defines the following public methods:

  public void addEntry(String name, Address address)
  public Address getAddressFromName(String name)
  public Element getAllListings()
  public int putListings(Element el)

When SOAP Java methods take scalar arguments or return scalar types, and use the standard SOAP v1.1 encoding, the Oracle SOAP Request Handler Servlet performs serialization and encoding internally. For services implemented as Java methods that take user-defined types as parameters or return user-defined types as results, the application programmer needs to provide support classes to handle serialization. With the AddressBook service, a user supplied serialization routine is required for the Address type that addEntry() takes as a parameter and getAddressFromName() returns. The Address user-defined type contains a PhoneNumber type that also requires a user-supplied serialization routine.

Serializing Java Parameters and Results Using BeanSerializer

For types not found in Table 2-1, you can provide a JavaBean that supports serialization and deserialization, using the standard SOAP v1.1 encoding. The BeanSerializer class within Oracle SOAP uses JavaBeans to serialize and deserialize user-defined types with the SOAP-ENC encoding style. This technique enables handling of Java user-defined types for a SOAP service on both the client and server-side.

Perform the following steps to use a JavaBean and the BeanSerializer:

  1. Write the JavaBean to support the user-defined types that the service uses. The following section, "Writing JavaBean Support Routines for User-Defined Types" describes this step.

  2. Add the compiled JavaBean class to the appropriate CLASSPATH (on the server-side and the client-side). The section, "Adding Compiled JavaBean Classes to the CLASSPATH" describes this step.

  3. Deploy the JavaBean on the SOAP server by specifying a map element in a service deployment descriptor. The section, "Deploying a SOAP Java Service Using User-Defined Types" describes this step.

Writing JavaBean Support Routines for User-Defined Types

The AddressBook sample provides several JavaBeans that the SOAP BeanSerializer uses to support serialization in the AddressBook service. The files Address.java and PhoneNumber.java provide the JavaBean serialization support that allows SOAP to process and pass an address and a phone number between the SOAP client and the SOAP server. These routines are JavaBeans for the Address and PhoneNumber types. JavaBeans conform to the JavaBeans specification and have the following characteristics:

Example 3-1 shows the conforming setCity() set method and getCity() get method from the Address JavaBean that supports the AddressBook SOAP service (see Address.java for the complete JavaBean sample).

Example 3-1 Sample Set and Get Methods from the Address JavaBean

  public void setCity(String city)
  {
    this.city = city;
  }

  public String getCity()
  {
    return city;
  }

Adding Compiled JavaBean Classes to the CLASSPATH

After creating and compiling the JavaBean, add the generated support class to the CLASSPATH. Note, this code has to be made available to both the SOAP service on the server-side and to the SOAP client code on the client-side.

On the server-side add the class to the CLASSPATH for the SOAP Request Handler Servlet routine (the routine that invokes the Java service). There are two ways to add the service class to the CLASSPATH, depending on the mode the Oracle SOAP Request Handler Servlet is running in, either auto mode or non-auto mode.

After modifying the CLASSPATH, restart the SOAP Request Handler Servlet.

See Also:

"Using Auto Start Mode" 

Returning Results to the Request Handler Servlet

The getAddressFromName() code segment shown in Example 3-2 gets the address from memory and returns an Address. The getAddressFromName() method returns its result to the Oracle SOAP Java Provider.

Example 3-2 Generate Data and Return Result for Date

public Address getAddressFromName(String name)
    throws IllegalArgumentException
{
  if (name == null)
  {
     throw new IllegalArgumentException("The name must not be " +  "null.");
  }
   return (Address)name2AddressTable.get(name);
 }

Encoding Java Parameters and Results

Oracle SOAP supports two types of XML encoding for user-defined parameters and results:

For Java service parameters and results, the map element of the service descriptor deployment file sets the encoding style, and the XML to Java and Java to XML serialization and deserialization routines for user-defined types.

See Also:

 

Deploying a SOAP Java Service Using User-Defined Types

To deploy a SOAP service with user-defined types, you need to create a service deployment descriptor file and include a mappings element with map elements for each user-defined type. Example 3-3 shows the mappings element from the AddressBook service descriptor ServiceDescriptor.xml. This descriptor is included in the directory $SOAP_HOME/samples/addressbook on UNIX or %SOAP_HOME%\samples\addressbook on Windows NT. The service descriptor file should conform to the service descriptor schema defined in service.xsd in the directory $SOAP_HOME/schemas on UNIX or in %SOAP_HOME%\schemas on Windows NT. Table 3-1 describes the attributes of the map element.


Note:

The SOAP Service Manager does not currently validate the deployment descriptor file using the schema service.xsd.  


After creating the deployment descriptor file, deploy the service using the SOAP Service Manager utility.

Example 3-3 Java Service Descriptor File for AddressBook Service

<isd:mappings>
    <isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
         xmlns:x="urn:xml-soap-address-demo" 
         qname="x:address"
         javaType="samples.addressbook.Address"
         java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializer"
         xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializer"/>
    <isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
         xmlns:x="urn:xml-soap-address-demo" 
         qname="x:phone"
         javaType="samples.addressbook.PhoneNumber"
         java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializer"
         xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializer"/>
</isd:mappings>   

See Also:

"Using the Service Manager to Deploy and Undeploy Java Services" 

Table 3-1  Service Deployment Descriptor Map Element Attributes
Attribute  Description 

qname 

Specifies the qualified name of the serialized object. This is the XML type of the serialized object. 

javaType 

Establishes the relationship between qname and the corresponding Java type (the Java type that gets serialized or deserialized). 

java2XMLClassName 

Specifies the names of the classes that marshal user-defined parameters or return values, mentioned in the javaType attribute. The BeanSerializer class is delivered with the SOAP server, and uses the JavaBean for mapping. If the javaType specified is not a JavaBean, interfaces are supplied that allow you to write your own java2XML classes. 

xml2JavaClassName 

Specifies the name of the classes that unmarshal user-defined parameters or return values, mentioned in the javaType attribute. The BeanSerializer class is delivered with the SOAP server, and uses the JavaBean for mapping. If the javaType specified is not a JavaBean, interfaces are supplied that allow you to write your own xml2java classes. 

Developing a SOAP Java Client Using Parameters

After creating and deploying one or more SOAP services, client-side applications request service invocations. For details on the basic components of a client-side application that makes a SOAP service request, see Chapter 2, "Using Oracle SOAP with Java Services". This section shows additional SOAP client-side techniques that allow you to use parameters to make service requests. The topics covered include:

Creating Parameters to Pass to a Service

This section describes the procedure for using the PutAddress client to make an addEntry() method request of the AddressBook service. The AddressBook service is supplied with Oracle SOAP in samples.jar. For complete details on the code for this section, refer to PutAddress.java in the directory $SOAP_HOME/samples/addressbook.

The command line arguments specify the address and phone number for the Address parameter to pass to the SOAP method, addEntry(). Example 3-4 shows the instantiation for the Address object. The new Address is used as a parameter in the addEntry() service when the service runs on the SOAP server. PutAddress obtains the args[] values from the command line.

Example 3-4 Building an Address Object to Send as a SOAP Parameter

String nameToRegister = args[1];
PhoneNumber phoneNumber = 
               new PhoneNumber( Integer.parseInt(args[7]), args[8],    args[9]);
Address address = new Address(Integer.parseInt(args[2]),
                                  args[3],
                                  args[4],
                                  args[5],
                                  Integer.parseInt(args[6]),
                                  phoneNumber);

Handling Encoding, Serialization, and Mapping with Parameters

Using the standard SOAP encoding, the SOAP Java client-side API handles serialization and encoding for primitive types internally. The PutAddress class makes a request for the SOAP addEntry() method from the AddressBook SOAP service. The addEntry() method takes an Address parameter, which is not a primitive type. To pass an address, the SOAP client needs to handle serialization and mapping for the Address and the PhoneNumber objects. Example 3-5 shows the SOAPMappingRegistry, the BeanSerializer, and the encoding style flags that allow the SOAP client to serialize these user-defined objects. Note that the mapTypes() method takes a QName argument. The QName is defined when a service is deployed on the SOAP server.

Example 3-5 SOAP Client-Side Call Serialization and Mapping

    SOAPMappingRegistry smr = new SOAPMappingRegistry();
    BeanSerializer beanSer = new BeanSerializer();

    String  encodingStyleURI = Constants.NS_URI_SOAP_ENC;

    // create the type mapping

    smr.mapTypes(Constants.NS_URI_SOAP_ENC,
                 new QName("urn:xml-soap-address-demo", "address"),
                 Address.class, beanSer, beanSer);
    smr.mapTypes(Constants.NS_URI_SOAP_ENC,
                 new QName("urn:xml-soap-address-demo", "phone"),
                 PhoneNumber.class, beanSer, beanSer);

See Also:

 

Setting Up a Call to Request a Service with Parameters

The package org.apache.soap.rpc contains the SOAP Call object. A SOAP client-side request uses a Call object to build a request for a SOAP service. After the request is created, it is invoked to request that the client API pass the request on to the SOAP server. Example 3-6 shows the code that builds a request for a service invocation, including name and address that are sent to addEntry().

Example 3-6 Building a SOAP RPC Call with Parameters

Call call = new Call();
call.setSOAPMappingRegistry(smr);
String serviceId = "urn:www-oracle-com:AddressBook";
call.setTargetObjectURI(serviceId);
call.setMethodName("addEntry");
call.setEncodingStyleURI(encodingStyleURI);
Vector params = new Vector();
params.addElement(new Parameter("name", String.class,
                                    nameToRegister, null));
params.addElement(new Parameter("address", Address.class,
                                    address, null));
call.setParams(params);

This code does the following:

In addition, the setTimeout() method sets the timeout, an integer representing seconds. The default Call timeout, implicitly set in this example, specifies no timeout. Setting a timeout value of 0 also specifies no timeout.

Invoking a Call to Request a Service with Parameters

In Example 3-7 the Call object's invoke() method makes a SOAP request and invokes the service at the specified URL. The Response object handles the response. The URL that you provide on the command line should be the URL for the SOAP Request Handler Servlet. This value depends on where SOAP is deployed. For example, the URL could be composed as follows:

http://machineName:port/soap/servlet/soaprouter

Example 3-7 Making the SOAP RPC Call Invocation

Response resp;
    try
    {
      resp = call.invoke(url, SOAPactionURI);
    }
    catch (SOAPException e)
    {
      System.err.println("Caught SOAPException (" +
                         e.getFaultCode() + "): " +
                         e.getMessage());
      return;
    }


Note:

The second argument to invoke(), the actionURI is not used. The Oracle SOAP server currently does not use this argument. 


Running a Client with Parameters

After writing a SOAP client using parameters, and setting the SOAP environment, run the client as you would any Java program:

cd $SOAP_HOME/bin
source clientenv.csh
java ${JAXP} samples.addressbook.PutAddress ${SOAP_URL} "John Doe" 123 "Main 
Street" AnyTown SS 12345 800 555 1212

Writing a SOAP Service Using Arrays as Parameters

Consider a SOAP Java service that returns the sum of the elements of an integer array. Example 3-8 shows the SOAPArrayCalculator service that takes an array parameter and returns the sum. The getSum() method returns the sum of the input elements of the integer array, array1.

This section covers the following:

Server-Side Adjustments for Using Arrays as Parameters

For a SOAP Java service, passing arrays on the server-side is no different than passing other parameters, as shown in Example 3-8.

Example 3-8 SOAP Java Service Using an Array Parameter

package SOAPServices;
public class SOAPArrayCalculator extends Object
{
  public SOAPArrayCalculator()
  {
  }
  public static int getSum(int[] array1)
  {
    int result = 0;
    for (int i=0; i<array1.length; i++)
      result += array1[i];
    return result;
  }
}

Client-Side Adjustments for Using Arrays as Parameters

On the client-side, making a request for a SOAP Java service and passing arrays is slightly different than passing other parameters. Example 3-9 shows that the Java client-side application must send an array of Integer for the corresponding array of int in the service on the server-side. SOAP handles the encoding and decoding of the array using a reflection mechanism implemented at the SOAP server level. This mechanism allows SOAP to know what to receive and how to stream it in the requests and responses.

Example 3-9 SOAP Request Using an Array Parameter

Integer[] array = getIntegerArray();
Vector prms = new Vector();
prms.addElement(new Parameter("integerArray", Integer[].class, array, null));
call.setParams(prms);


Note:

From the client-side, all parameters sent as components of an array must use an Object type. 


Writing a SOAP Service Using Literal XML Encoding

This section uses the getAllListings() method in the AddressBook service to describe the procedure for writing a SOAP service using literal XML encoding. The getAllListings() method returns a list of all AddressBook listings as a literal XML element. The SOAP client application GetAllListings.java is included in the directory $SOAP_HOME/samples/addressbook. This section describes the changes you need to make on both the client and server sides to support passing parameters or results using a literal XML encoding.

This section covers the following topics:

Server-Side Adjustments for Using Literal XML Encoding

When writing a Java SOAP service that uses a literal XML encoding for a parameter or for a return value, add the following imports to support working in XML:

import java.util.*;
import org.w3c.dom.*;
import org.apache.soap.util.xml.*;
import oracle.soap.util.xml.XmlUtils;

Creating a Return Value with Literal XML Encoding

The SOAP Request Handler Servlet uses literal XML encoding for all parameters that specify this encoding in a client request, and for return values when the default encoding style set for the call specifies XML encoding. Use the Call method, setEncodingStyleURI() with a value of Constants.NS_URI_LITERAL_XML to set the default encoding style for a call to literal XML.

The Java service implementation provides either the appropriate literal XML parameters or a literal XML return value. For example, when literal XML encoding is specified as the default encoding in the SOAP request, the return value sent back to the client from the Java service should be a valid XML element, as defined by org.w3c.dom.Element. Thus, the client call specifies the default encoding that is used for a return value, and for all parameters that do not explicitly set an encoding style. The service provides a valid object that conforms to the encoding. The AddressBook method getAllListings() shows how a Java service could build an Element that SOAP could encode literally in XML. Oracle SOAP supplies XmlUtils methods that support working with XML documents.

Client-Side Adjustments for Using Literal XML Encoding

On the client-side, a SOAP service that passes a literal XML argument or returns a literal XML value is very similar to the services using the basic SOAP Java functionality shown in Chapter 2, "Using Oracle SOAP with Java Services".

Minor changes are required to support literal XML encoding, including:

Specifying a Call with Literal XML Encoding

To specify a call using literal XML encoding for all parameters and results, use the setEncodingStyleURI() method, with the value Constants.NS_URI_LITERAL_XML. Example 3-10 shows the Java that builds the call for getAllListings().

Example 3-10 Making a SOAP Call Using Literal XML Encoding

Call call = new Call();
String serviceId = "urn:www-oracle-com:AddressBook";
call.setTargetObjectURI(serviceId);
call.setMethodName("getAllListings");
call.setEncodingStyleURI(Constants.NS_URI_LITERAL_XML);

Invoking a Call with Literal XML Encoding

After setting up the client to receive a literal XML encoded result, invoke the service on the SOAP server as you would any service. Using GetAllListings, the result is sent in the response return value. Example 3-11 shows how the return value is placed in a SOAP client API Parameter object, which is then cast to an Element using the getValue() method.

Example 3-11 Invoking and Processing with Literal XML Results

Response resp;

try
{
   resp = call.invoke(url, "");
}
catch (SOAPException e)
{
      System.err.println("Caught SOAPException (" +
                         e.getFaultCode() + "): " +
                         e.getMessage());
      return;
}
Check value    // check the response

if (!resp.generatedFault())
{
      Parameter ret = resp.getReturnValue();
      Element bookEl = (Element)ret.getValue();

      System.out.println(DOM2Writer.nodeToString(bookEl));
}
else
{
      Fault fault = resp.getFault();

      System.err.println("Generated fault: ");
      System.out.println ("  Fault Code   = " + fault.getFaultCode());
      System.out.println ("  Fault String = " + fault.getFaultString());
    }
}


Go to previous page Go to next page
Oracle
Copyright © 2001 Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Library
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index