Oracle TopLink as a Custom Serializer in a JAX-RPC 1.1 Web Service

How-To Document

January 2006

After reading this How-To document, you will be able to:

Software Requirements

Conventions

The following conventions are used in this document:

Introduction

This How-To document will show you how to use OC4J's Web services utilities to assemble a JAX RPC 1.1 compliant Web service that uses a custom serializer. It will also show you how to use OC4J's Web services utilities to generate a client that uses a custom serializer to interact with the Web service. The custom serializer will make use of the TopLink O-X mapped project created in the TopLink O-X How-To to convert Customer objects to and from XML. In this How-To, both the Web service and the client that accesses it will use the same model classes and serializer class. However, since the client and service are completely separate entities, each could have their own model and serializer.

Using TopLink as a Custom Serializer in a JAX-RPC 1.1 Web Service

In this section, you will use the OC4J Web services assembler tool to assemble a JAX-RPC 1.1 compliant Web service and generate JAX-RPC 1.1 compliant client proxy classes. Next, a custom serializer will be created that makes use of the TopLink O-X mapped project created in the TopLink O-X How-To.

The Web service will have one method – findCustomer – that returns a Customer. The client will call the findCustomer method on the Web service, and the Web service will create and return a new Customer object. The new Customer object will be converted to XML by the serializer and sent to the client. The client receives the new Customer in XML format and uses it's serializer to deserialize the XML and create a Customer object. The serializer uses the TopLink O-X mapped project to convert the objects to XML and vice versa.

Step 1: Folder Setup

Create the <DEMO_HOME> folder and copy the Customer.xsd file and the Customer.xml deployment descriptor file (created in the TopLink O-X How-To) to its root level.

Also copy the Customer.xml deployment descriptor file to the root level of the <DEMO_HOME>/classes folder.

Step 2: Compile the Customer Model Classes

Extract the Java source files from CustomerModel.zip to the <DEMO_HOME>/src folder and compile them to the <DEMO_HOME>/classes folder.

Create a model.jar file that contains the compiled model class files Customer.class, Address.class, and PhoneNumber.class. Copy the model.jar file to the <DEMO_HOME> folder. The model.jar file is used by the client.

Step 3: Create the Web Service Interface and Implementation Classes

Create a <DEMO_HOME>/src/examples/jaxrpc/jaxrpc11/service folder and create a CustomerLocatorService.java interface and CustomerLocatorServiceImpl.java class file in it. The Web service for this How-To will have a single method with signature public Customer findCustomer(). This method simply returns a newly created Customer object (see Example: Implementation for the findCustomer Web Service Method).

Implementation for the findCustomer Web Service Method

public Customer findCustomer(String firstName, String lastName) throws java.rmi.RemoteException {
    System.out.println("[SERVICE] Customer '" + firstName + " " + lastName + "' requested");
 
    // create a customer to return to the client
    Address billingAddress = new Address();
    billingAddress.setStreet("123 Any St.");
    billingAddress.setSuite("Suite 1");
    billingAddress.setCity("Ottawa");
    billingAddress.setProvince("ON");
    billingAddress.setPostalCode("A1B 2C3");
 
    Address shippingAddress = new Address();
    shippingAddress.setStreet("456 Another Street");
    shippingAddress.setCity("Raleigh");
    shippingAddress.setProvince("NC");
    shippingAddress.setPostalCode("12345");
 
    PhoneNumber workPhoneNumber = new PhoneNumber();
    workPhoneNumber.setType("work");
    workPhoneNumber.setNumber("(613) 555-1111");
 
    PhoneNumber cellPhoneNumber = new PhoneNumber();
    cellPhoneNumber.setType("cell");
    cellPhoneNumber.setNumber("(613) 555-2222");
 
    java.util.Calendar dob = java.util.Calendar.getInstance();
    dob.clear();
    dob.set(1975, 02, 21);
 
    Customer customer = new Customer();
    customer.setFirstName(firstName);
    customer.setLastName(lastName);
    customer.setDateOfBirth(dob);
    customer.setBillingAddress(billingAddress);
    customer.setShippingAddress(shippingAddress);
    customer.getPhoneNumbers().add(workPhoneNumber);
    customer.getPhoneNumbers().add(cellPhoneNumber);
 
    return customer;
}

Compile the Web service interface and implementation classes to the <DEMO_HOME>/classes folder.

Step 4: Create the Custom Serializer

Create a <DEMO_HOME>/src/examples/jaxrpc/jaxrpc11 folder and create a CustomerSerialzer.java file in it. The custom serializer class must implement the oracle.webservices.databinding.SOAPElementSerializer interface and include the following SOAPElementSerializer methods:

The serialize method is responsible for converting a Customer object to XML. Example: Implementation for the serialize Method shows an implementation of the serialize method that uses TopLink.

Implementation for the serialize Method

public SOAPElement serialize(QName qname, Object object) {
    SOAPElement soapElement = null;
    try {
        soapElement = soapFactory.createElement(qname.getLocalPart(), qname.getPrefix(), qname.getNamespaceURI());
        marshaller.marshal(object, soapElement);
    } catch (SOAPException ex) {
        // Handle the exception
        ex.printStackTrace();
    }
    return soapElement;
}

Note how this method creates a SOAPElement to marshal the Customer object to.

The deserialize method is responsible for converting XML into a Customer object. Example: Implementation for the deserialize Method shows an implementation of the deserialize method that uses TopLink.

Implementation for the deserialize Method

public Object deserialize(SOAPElement soapElement) {
    Object unmarshalledObject = unmarshaller.unmarshal(soapElement, Customer.class);
    return unmarshalledObject;
}

Note that in the unmarshall call, the Customer.class argument identifies the class that the complex type customer-type is to be unmarshalled to.

The primary function of the init method is to initialize a SOAPFactory instance, XMLMarshaller and XMLUnmarshaller. Add the following instance variables to your class:

Example: Implementation for the init Method shows an implementation of the init method.

Implementation for the init Method

public void init(Map prop) {
    try {
      XMLProjectReader reader = new XMLProjectReader();
      Project project = reader.read("Customer.xml", this.getClass().getClassLoader());
      XMLContext xmlContext = new XMLContext(project);
      marshaller = xmlContext.createMarshaller();
      unmarshaller = xmlContext.createUnmarshaller();
      soapFactory = SOAPFactory.newInstance();
  
    } catch (SOAPException e) {
        e.printStackTrace();
    }
}

Before compiling the custom serializer classes, ensure that the following archives are on your classpath:

Compile the custom serializer to the <DEMO_HOME>/classes folder.

Step 5: Create the Oracle Web Services Type Mapping Configuration XML File

In the <DEMO_HOME> folder create a file called custom_type_schema_pdd.xml. The purpose of this file is to associate an XML type with a Java class and to specify a custom serializer to convert instances of the Java classes to/from XML. An entry should be added for each Java class that corresponds to a global XML type.

Example: The custom_type_schema_pdd.xml File shows the custom_type_schema_pdd.xml file for this How-To.

The custom_type_schema_pdd.xml File

<oracle-webservices 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/oracle-webservices-10_0.xsd">
    <webservice-description name="CustomerLocatorService">
        <type-mappings xmlns:typens="urn:customer-example">
            <type-mapping java-class="examples.ox.model.Customer" xml-type="typens:customer-type">
                    <serializer class="examples.jaxrpc.jaxrpc11.CustomerSerializer"/>
            </type-mapping>
            <type-mapping java-class="examples.ox.model.Address" xml-type="typens:address-type">
                    <serializer class="examples.jaxrpc.jaxrpc11.CustomerSerializer"/>
            </type-mapping>
        </type-mappings>
    </webservice-description>
</oracle-webservices>

Here we see that no type classes are to be generated by the assembler for Customer or Address and that the CustomerSerializer is to be used for each of these classes.

Step 6: Assemble the JAX-RPC 1.1 Web Service

In this How-To, we will use the OC4J Web services assembler tool to create the necessary artifacts for deploying the Web service to OC4J. Change directories to the <DEMO_HOME> directory and run the tool by executing the following on the command line:

java -jar ${OC4J_HOME}/webservices/lib/wsa.jar –assemble –targetNamespace urn:customer-locator-service –typeNamespace urn:customer-locator-service –input <DEMO_HOME>/classes –classpath <DEMO_HOME>/classes –output ./ –ddFileName <DEMO_HOME>/custom_type_schema_pdd.xml –interfaceName examples.jaxrpc.jaxrpc11.service.CustomerLocatorService –className examples.jaxrpc.jaxrpc11.service.CustomerLocatorServiceImpl –serviceName CustomerLocatorService –appName customer-locator –schema <DEMO_HOME>/Customer.xsd

The options used in this command line are as follows:

The result of executing the above command will be a customer-locator.ear file in your <DEMO_HOME> folder.

Step 7: Deploy the Web Service

Start your OC4J server and deploy the customer-locator.ear file generated in "Step 6: Assemble the JAX-RPC 1.1 Web Service". Set the deployment name for the application to customer-locator. When binding the web app, set the application name to customer-locator and the default-web-site value to /jaxrpc-demo.

Step 8: Create the Oracle Web Services Type Mapping Configuration Client XML File

In the <DEMO_HOME> folder create a file called custom_type_schema_client_pdd.xml. The purpose of this file is to associate an XML type with a Java class and to specify a custom serializer to convert instances of the Java classes to/from XML. An entry should be added for each Java class that corresponds to a global XML type.

Example: The custom_type_schema_pdd.xml File shows the custom_type_schema_client_pdd.xml file for this How-To.

The custom_type_schema_client_pdd.xml File

<oracle-webservices 
    <webservices-client> 
      <service-qname namespaceURI="http://oracle.com/ws/bottomup_customtype" localpart="CustomTypesService" />
      <type-mappings xmlns:typens="urn:customer-example">
            <type-mapping java-class="examples.ox.model.Customer" xml-type="typens:customer-type">
                  <serializer class="examples.jaxrpc.jaxrpc11.CustomerSerializer"/>
            </type-mapping>
            <type-mapping java-class="examples.ox.model.Address" xml-type="typens:address-type">
                  <serializer class="examples.jaxrpc.jaxrpc11.CustomerSerializer"/>
            </type-mapping>
        </type-mappings>
    </webservice-description>
    </webservices-client> 
</oracle-webservices>

Step 9: Generate the Client

In this How-To, we will use the OC4J Web services assembler tool to create the client proxy classes. Change directories to the <DEMO_HOME> directory and run the tool by executing the following on the command line:

java –jar ${OC4J_HOME}/webservices/lib/wsa.jar –genProxy –wsdl http://localhost:8888/jaxrpc-demo/customer-locator?WSDL –packageName examples.jaxrpc.jaxrpc11.client –output src –ddFileName custom_type_schema_client_pdd.xml –classpath custom_type_schema_pdd.xml;<DEMO_HOME>/classes

The options used in this command line are as follows:

The result of executing the above command will be client Java source files in your <DEMO_HOME>/src folder.


Note:

Ignore the warning from the OC4J Web services assembler.

Step 10: Modify the Generated Client

In the <DEMO_HOME>/src folder, locate the generated file examples.jaxrpc.jaxrpc11.client.HttpSoap11Client.java. Locate the line in the main method that says //Add your code here and add the following lines of code:

System.out.println("[CLIENT] Requesting customer 'Jane Doe' from service...");
examples.ox.model.Customer result = myPort.findCustomer("Jane", "Doe");
System.out.println("[CLIENT] Customer returned from service: \n" + result.toString());

Before compiling the client classes, ensure that the following archives are on your classpath:

Compile the client classes to the <DEMO_HOME>/classes folder.

Step 11: Build the Client JAR File

Create a JAR file named customer-locator-client.jar that includes the custom serializer class, generated proxy classes, binding XML, and deployment XML. For example:

Step 12: Run the Client

Before running the client, ensure that the following archives are on your classpath (in the order specified):

To run the client, run the examples.jaxrpc.jaxrpc11.client.HttpSoap11Client class.

Summary

Oracle TopLink includes support for mapping your existing Java objects to XML. TopLink O-X projects can be used in a Web services environment to convert objects to and from XML.


Oracle TopLink, 10g Release 3 (10.1.3)

The Programs (which include both the software and documentation) contain proprietary information; they are provided under a license agreement containing restrictions on use and disclosure and are also protected by copyright, patent, and other intellectual and industrial property laws. Reverse engineering, disassembly, or decompilation of the Programs, except to the extent required to obtain interoperability with other independently created software or as specified by law, is prohibited.

The information contained in this document is subject to change without notice. If you find any problems in the documentation, please report them to us in writing. This document is not warranted to be error-free. Except as may be expressly permitted in your license agreement for these Programs, no part of these Programs may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose.

If the Programs are delivered to the United States Government or anyone licensing or using the Programs on behalf of the United States Government, the following notice is applicable:

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the Programs, including documentation and technical data, shall be subject to the licensing restrictions set forth in the applicable Oracle license agreement, and, to the extent applicable, the additional rights set forth in FAR 52.227-19, Commercial Computer Software—Restricted Rights (June 1987). Oracle Corporation, 500 Oracle Parkway, Redwood City, CA 94065

The Programs are not intended for use in any nuclear, aviation, mass transit, medical, or other inherently dangerous applications. It shall be the licensee's responsibility to take all appropriate fail-safe, backup, redundancy and other measures to ensure the safe use of such applications if the Programs are used for such purposes, and we disclaim liability for any damages caused by such use of the Programs.

Oracle, JD Edwards and PeopleSoft are registered trademarks of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

The Programs may provide links to Web sites and access to content, products, and services from third parties. Oracle is not responsible for the availability of, or any content provided on, third-party Web sites. You bear all risks associated with the use of such content. If you choose to purchase any products or services from a third party, the relationship is directly between you and the third party. Oracle is not responsible for: (a) the quality of third-party products or services; or (b) fulfilling any of the terms of the agreement with the third party, including delivery of products or services and warranty obligations related to purchased products or services. Oracle is not responsible for any loss or damage of any sort that you may incur from dealing with any third party.