Sun ONE logo     Previous      Contents      Index      Next     
Sun ONE Connector Builder 2.0 Developer's Guide



Adding SOAP Services to the Resource Adapter

This module describes the following topics:

Basic Concepts

This section explains the key concepts of the SOAP layer generated by Connector Builder.

Connector Builder can selectively expose resource adapter JIOs as XML-RPC based SOAP services. The SOAP services generated by Connector Builder can be used only with the Apache SOAP 2.2 runtime.

What is SOAP?

SOAP, the Simple Object Access Protocol, allows the exchange of structured data between peers in a decentralized, distributed environment. The structure of the data being exchanged is specified by an XML schema. The fact that SOAP messages are encoded in XML makes SOAP messages portable, because XML is a portable, system-independent way of representing data. By representing data using XML, you can access data from legacy systems as well as share your data with other enterprises. The data integration offered by XML also makes this technology a natural for web-based computing such as web services. Firewalls can recognize SOAP packets based on their content type (text/xml-SOAP) and can filter messages based on information exposed in the SOAP message header.

The SOAP specification describes a set of conventions for exchanging XML messages. As such, it forms a natural foundation for web services that also need to exchange information encoded in XML. Having a standard such as SOAP allows developers to build the generic pieces that support this exchange. Once this support is put in place, other developers can focus on creating the web services themselves.

The SOAP protocol is fully described at

http://www.w3.org/TR/SOAP/.

How Does SOAP Work?

At some level, a SOAP service is eventually implemented as a method invocation on a Java class. To respond to a SOAP service request, then, a SOAP server must:

  • accept a SOAP service request from a client application
  • convert the XML representation of the data in the request into Java datatypes,
  • invoke a Java method that implements the specific service identified in the request, passing the converted input data as parameters, and then
  • convert the output and return data from that Java method back into XML for return in the response message.

The SOAP server uses following components to perform above tasks.

SOAP Client

A SOAP client application is any code that can compose an HTTP or HTTPS request containing a proper SOAP request, send the request message to the URL of a listening SOAP server, and accept the response and interpret the contents.

Deployment Descriptor

The SOAP deployment descriptor contains all the information that the SOAP run-time needs to recognize a SOAP service, map the service to a Java class and method, and to serialize and deserialize its datatypes.

Service Provider

Each SOAP service corresponds to a Java class and method that is the service provider for that service. This class contains the logic that performs the actual work of the service. By performing message handling and data conversions before invoking the service provider, the SOAP architecture allows the service provider class itself to remain independent of the fact that it is invoked as a SOAP service. This simplifies the job of building service provider classes and can allow pre-existing classes to be offered as SOAP services without changing them.

Serializers and Deserializers

SOAP requires a serializer and deserializer for each datatype that appears in a request or response. The Apache implementation of SOAP works with three categories of serializers and deserializers:

  • internally-supported - These handle many of the common Java datatypes and are provided with the Apache SOAP server.
  • JavaBean - These serializers support custom datatypes such as an Order class, as long as the class implements the JavaBean pattern with get and set methods for its fields. This support is also provided with the Apache SOAP server.
  • custom - These additional serializers and deserializers handle datatypes that are neither the common Java datatypes nor follow the JavaBean pattern. The SOAP server requires the developer to implement custom classes to serialize and deserialize any parameters of these datatypes.

SOAP requires a serializer and deserializer for each datatype that appears in a request or response.

The Supported Apache SOAP Data Types table lists the data types that the Apache SOAP run-time supports internally.

   Supported Apache SOAP Data Types

Data type

All Java primitive types (except char), such as int, float, boolean, byte, etc. and their corresponding wrapper classes (i.e. java.lang.Integer, java.lang.Float, etc.)

 

Java arrays

 

java.lang.String

 

java.util.Date

 

java.util.GregorianCalendar

 

java.util.Vector

 

java.util.Hashtable

 

java.util.Map (under Java editions in which this is supported)

 

java.math.BigDecimal

 

javax.mail.internet.MimeBodyPart

 

java.io.InputStream

 

javax.activation.DataSource

 

javax.activation.DataHandler

 

java.lang.Object (a deserializer for null objects only)

 

Java beans (through org.apache.soap.encoding.soapenc.BeanSerializer)

 

Participating Classes

Some SOAP services may deal with complex nested structures, such as objects that have fields that are themselves references to other objects, and so on. Each of these classes is said to participate in the SOAP service, regardless of how deeply-nested the class might be within the structure. SOAP needs the serializers and deserializers for all participating classes in a service.

SOAP Processing

The following figure illustrates how Apache's SOAP server operates at a high level.

   SOAP Overview
Figure shows SOAP Overview

  1. A client application sends a SOAP service request containing input data expressed in XML to a Web container that is hosting the SOAP service. The Web container forwards the request to a component of the SOAP run-time, called rpcrouter.
  2. Using information in the deployment descriptor for the SOAP service, rpcrouter sends the XML-encoded data to one or more deserializers.
  3. Each deserializer converts a particular category of XML-encoded data into the corresponding Java datatype and returns the Java data to the rpcrouter.
  4. The rpcrouter may send different parts of the XML input data to different deserializers, depending on the various datatypes in the SOAP request.

  5. The rpcrouter locates a Java class that is the service provider for the SOAP service identified in the incoming request, again guided by the SOAP service deployment descriptor. It invokes a method on the service provider, passing the Java data representing the input parameters.
  6. The service provider performs the work of the actual requested service, providing any output values back to the rpcrouter as modified Java object parameters or a return value.
  7. The rpcrouter sends each output data item to the correct serializer.
  8. Each serializer converts the value of a particular category of Java datatype into XML-encoded data and returns it to the rpcrouter.As before, rpcrouter may call on several different serializers to transform different Java datatypes into the corresponding XML encoding.
  9. The rpcrouter composes a full response message that contains the XML encoding for all output data and sends the response message to the client application.

Generating SOAP Services for Connector Builder Resource Adapters

The Connector Builder can generate the following elements of SOAP services:

  • SOAP service deployment descriptor
  • template serializers and deserializers - The adapter developer can customize these classes to handle datatypes that the SOAP server cannot handle itself.
  • service providers (in the form of the JIOs for the resource adapter)
  • utility classes used by the client application for invoking the SOAP services.

To Add SOAP Services to an Adapter

  1. Configure the SOAP services, using the adapter's contextual menu within the Explorer area of the IDE.
  2. Select the JIOs for which you want to add SOAP services using the SOAP Layer Editor (The service names are based on JIO names).
  3. Edit the serializers and participating classes for the selected JIOs.

This completes the SOAP service definition and closes the SOAP Layer Editor.

The Participating Classes table in the SOAP Layer Editor displays the parameters for the method the SOAP service is based on. The data type of the parameter and the name of the serializer/deserializer class for that parameter are displayed for each parameter. Although the table displays both scalar and class parameters, only the class parameters that are not supported by the Apache SOAP runtime, can be modified.

Editing the Serializer

See the Supported Apache SOAP Data Types table for more information on what serializer to use.

The following three options are available for serializers/deserializers:

  • Use Java Bean
  • Selecting this option uses the bean serializer/deserializer provided by Apache SOAP

  • Generate Template (default option)
  • Selecting this option causes the Sun ONE Connector Builder to generate a template serializer/deserializer. The implementation of this class needs to be provided by the adapter developer.

  • Custom
  • Selecting this option allows you to select a preexisting serializer/deserializer that can be used by the Apache SOAP runtime. Note that the class supplied is expected to implement org.apache.soap.util.xml.Serializer and org.apache.soap.util.xml.Deserializer interfaces.

Editing the Participating Classes

The Participating Classes table in the SOAP Layer Editor displays the parameters for the method the SOAP service is based on. The data type of the parameter and the name of the serializer/deserializer class for that parameter are displayed for each parameter. Although the table displays both scalar and class parameters, only the class parameters that are not supported by the Apache SOAP runtime, can be modified.



Note

If you have any template interaction specs and selected an Interface as a custom input/output record for that template interaction spec, you need to add the implementation class as a participating class for that input/output record while configuring it as a SOAP service.



To Use the SOAP Layer Editor

  1. Right-click on the adapter node to open the contextual menu. Select Configure SOAP Services. The following screen displays the contextual menu for configuring SOAP services.
  2. Configure SOAP Services


    Figure shows Contextual Menu for Configure SAP Services
    .

The following screen displays the SOAP Layer Editor.

   SOAP Layer Editor


Figure shows SOAP Layer Editor

Editing a Serializer

  1. Select the class from the Working JIO Set.
  2. Highlight the Participating Class.
  3. The Edit Serializer and Edit Participating Class boxes are activated.

  4. Click Edit Serializer, the Customize Serializer Screen is displayed.

   Customize Serializer Screen


Figure shows Customize Serializer Screen

  1. Select one of the following options:
    1. Use JavaBean
    2. The serializer for that class is the BeanSerializer serializer class provided by Apache SOAP.

    3. Generate Template
    4. A template serializer for that class is generated in the resource adapter's soap/serializers subdirectory.

    5. Custom
    6. You must select the class containing the implementation of the serializer/deserializer to be used using the Browse button (This class must be mounted in the IDE file system).



      Note

      Serializers cannot be modified for datatypes that are supported by the Apache runtime.



Editing a Participating Class

  1. Select the class from the Working JIO Set.
  2. Highlight the Particiapting Class.
  3. The Edit Serializer and Edit Participating Class boxes are activated.

  4. Click Edit Participating Class. The Edit Participating Class Screen is displayed.

   Edit Participating Class Screen


Figure shows Customize Serializer Screen

  1. Click Add Class to add a participating class.
  2. A browser of the IDE repository opens. (The class must be in a directory mounted in the IDE file system.).The Add Class screen is displayed.

   Add Class


Figure shows Add Class Screen

  1. Click OK. The class is added.

The following screen displays the Edit Participating Class screen after modification.

   Edit Participating Class


Figure shows Edit Participating Class Screen

To Remove a Participating Class

  1. Select the row containing the class you want to remove.
  2. Click Remove Class to remove the class.

To Edit a Serializer for a Participating Class

  1. Select the row containing the participating class and Click Edit Serializer.
  2. The Customize Serializer Screen is displayed.

  3. Follow the same procedure as previously described in Editing a Serializer.

When you finish editing the participating classes and serializers, click OK. The SOAP Layer Editor window is displayed.

  1. Click OK in the SOAP Layer Editor window.
  2. Choose the Save context menu option to save your changes.
  3. Choose the Generate menu option.

Alternatively, you can directly choose the Generate option as generation always saves the definition first. The Adapter and the SOAP Services generation begins. On completion, a generation report is displayed in IDE's Output window.

In the generated code directory, a soap directory is created which contains the following three subdirectories:

clients

The clients directory contains one HTTP client class for each exposed SOAP service.

deployment

The deployment directory contains a deployment descriptor XML document for each SOAP service.

serializers

The serializers directory contains a serializer class for each of the participating classes for which you chose the Generate Template option.

Customizing the SOAP Layer

This section describes various components of the SOAP layer that is generated on top of the resource adapter.

The following topics are described:

SOAP Service Generation Naming Scheme

The Connector Builder provides default names for all the SOAP service related entities. The names related to the SOAP service framework are constructed from several values as listed in Names for SOAP Service Generation table below. The left column lists the SOAP service entity and the right column lists the naming scheme.

   Names for SOAP Service Generation

SOAP service entity

Naming scheme

Service Name

 

urn:[Adapter Logical Name]:[JIO Name]

JIO Name Scheme is [EIS API class name][EIS API method name]

 

Deployment descriptor

 

[JIO Name]DD.xml

 

HTTP Client

 

[JIOName]client.java

 

Serializer/Deserializer

 

[Data type name]Serializer.java

 

Generated SOAP Framework - Code Samples

Template Serializer/Deserializer

A template serializer/deserializer is generated for the data types as specified by user input through the SOAP layer editor. The template source code contains the marshall and unmarshall methods that need to be implemented.

Service Deployment Descriptor

Connector Builder generates a deployment descriptor for each SOAP service.

The following code shows the Connector Builder generated deployment descriptor for COTSAPIGetCustomer service

.

   Deployment Descriptor for COTSAPIGetCustomer Service Code Example


<?xml version="1.0" encoding="UTF-8" ?>
<!--Generated by Sun ONE Connector Builder 2.0, a product of Sun Microsystems, Inc. -->
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:COTS:COTSAPIGetCustomer" >
<isd:provider type="java" scope="Application" methods="execute executeAPI">
<isd:java class="com.sun.appinteg.samples.cots.jio.COTSAPIGetCustomer" static="false" />
</isd:provider>
<isd:faultListener>org.apache.soap.server.DOMFaultListener</isd: faultListener>
<isd:mappings>
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="urn:xml-soap-j2eeca-COTS-COTSAPIGetCustomer"
qname="x:COTSAPIGetCustomerInputRecord"
javaType="com.sun.appinteg.samples.cots.cci.COTSAPIGetCustomerIn putRecord"
java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializ er"
xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializ er" />
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="urn:xml-soap-j2eeca-COTS-COTSAPIGetCustomer"
qname="x:COTSAPIGetCustomerOutputRecord"
javaType="com.sun.appinteg.samples.cots.cci.COTSAPIGetCustomerOu tputRecord"
java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializ er"
xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializ er" />
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="urn:xml-soap-j2eeca-COTS-COTSAPIGetCustomer"
qname="x:Customer"
javaType="com.sun.appinteg.samples.eis.Customer"
java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializ er"
xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializ er" />
</isd:mappings>
</isd:service>

HTTP Client

For each SOAP service of the resource adapter, Connector Builder generates a java class utility to access it via HTTP. This class is named using the JIO name. For example, if the JIO name is COTSAPIGetCustomer, the generated client class name is COTSAPIGetCustomerClient.java. This class uses the Apache SOAP provided facilities for preparing, sending, receiving and processing the SOAP encoded XML message.

The following code example shows a part of the COTSAPIGetCustomerClient class for accessing COTSAPIGetCustomer service.



   COTSAPIGetCustomerClient class for Accessing COTSAPIGetCustomer Service Code Example


public void initClient() throws Exception{
//local type mapping registry
theRegistry = new SOAPMappingRegistry();
//register all the data type serializer/deserializer info with the registry
// Set the Apache SOAP router servlet URL. Change the name as per the deployment
theURL = new URL("http://localhost:80/soap/servlet/rpcrouter");
// Set the Service URN. This URN should match the URN in the deployment descriptor
theURN = "urn:COTS:COTSAPIGetCustomer";
}
//Method to populate the input data. If the input data needs to be supplied externally, please change this method signature.
private Vector populateInputData(){
}
// Method to make the RPC Call to the SOAP Service - The code in this method makes the calls to prepare the SOAP XML message, send it to the URL and receive the response XML and create objects out of it.
public Parameter execute() throws Exception {
// Prepare Call object with URL, method name, encoding, registry and the parameter values
// Invoke the method through the URL

Mandatory Customizations

This section describes the customizations you must perform on the resource adapter that was generated using the Connector Builder.

Implementing the Serializers

The serializer/deserializer templates generated for certain data types as per the SOAP service configuration need to be implemented. Refer to the source samples shipped along with the Apache SOAP runtime. Since the deployment descriptors and HTTP Client program where the data type is used, already map the generated template serializer class to its data type, no other code changes are necessary.

HTTP Client Modifications

The generated HTTP Client for each service provides place holders for preparing input data. You need to customize this code to tie with the UI or other applications to populate the input data for sending to SOAP service. In addition, if the service is deployed at a different URL, the corresponding change needs to be made in the HTTP Client source code.

The clients are generated to use the execute method of the SOAP service which operates using the inputRecord. If the client needs to use the executeAPI method of the service (in order to use the APIs parameters directly), the generated code needs to be modified. The line, call.setMethodName("execute") in the client's execute method, should be changed to call.setMethodName("executeAPI");

Advanced Customizations (Optional)

Service URN Modifications

Connector Builder generates the service URN for each service as per the naming scheme described in "Names for SOAP Service Generation". If a service by the same URN of the generated SOAP service exists in the SOAP registry, you have to be careful in deploying the service. The deployment procedure by default overwrites the existing service. To change the service URN, the service name in the `id' attribute of `isd:service' tag needs to be changed to the service name of choice. The corresponding change should be made in the service's HTTP Client code.

Using HTTPS with SOAP Clients

The generated SOAP clients use HTTP protocol to talk to the deployed SOAP services. If you deploy the SOAP services on a secure server, you need to use HTTPS protocol to talk to those services and enable the SOAP clients to use secure communication.

To Enable SOAP Clients to Use Secure Communication

  1. Download the JSSE package if using JDK version earlier than 1.4.
  2. To use secure communication from the SOAP clients, you need the Java Secure Sockets Extension (JSSE) package. This is bundled with JDK1.4. If you are using an earlier version of JDK, you need to download the JSSE package available at:

    http://java.sun.com/products/jsse/.

  3. Copy the following three jar files
    • jsse.jar
    • jnet.jar
    • jcert.jar

    into the adapter's lib/ext directory.

    When using JDK1.4, you only jsse.jar is required.

  4. Modify the generated SOAP client code to use secure communication by adding the following two import statements to the client code:
  5. import javax.net.ssl.SSLSocketFactory;

    import java.security.Security;

  6. Add the following code to the initClient() method.


  7.    Additional code for the initClient() method


    // specify the location of where to find key material for the default TrustManager

    //(specify the correct location of the keystore file)

    System.setProperty("javax.net.ssl.trustStore","C:\\jdk1.3.1\\bin \\client.keystore");
    // use Sun's reference implementation of a URL handler for the "https" URL protocol type.
    System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl .internal.www.protocol");
    // dynamically register sun's ssl provider
    Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

    // Specify the correct value for URL.
    theURL = new URL("https://
    <your-server>:<secure-port>/soap/servlet/rpcrouter");

Refer to http://xml.apache.org/soap/docs/install/FAQ_Tomcat_SOAP_SSL.html for more information on setting up the clients for secure communication.

Propagating Adapter Internal Exceptions to SOAP Clients

The SOAP Service reports all the resource adapter internal exceptions as Server errors in executing the JIOs.

The following is a sample error that is displayed when you try to access the SOAP services of the COTS adapter while the COTS EIS System is not running:

Generated fault when invoking : http://localhost:80/soap/servlet/rpcrouterurn:COTS:COTSAPIGetAllCus tomers

Generated fault Code is :SOAP-ENV:Server

Generated fault String is :Exception from service object: Exception in the execution of JIO: COTSAPIGetAllCustomers::

To know the exact reason for the failure look in the Server log files. You can give the SOAP Clients a distinct message with the exact exception (in the SOAP fault String), by customizing the generated JIO code.

To Customize the JIO To Propagate the Error to the SOAP Clients

  1. Locate the following code line in the generated JIO:
  2. ResourceException finalException = new ResourceException(AdapterUtil.getI18NMessage(AdapterUtil.getDefault RB(), "jioExceptionReason", new Object [] {"COTSAPIGetAllCustomers"})+":"+firstException.getMessage()+":");

The firstException.getMessage() is appended to the error message that is sent to the SOAP Clients as the fault String. You need to check if the firstException is a ResourceException. If it is, instead of just getting the message, you need to get it's LinkedException's message as well.

  1. Replace the above code line with:
  2. String errMsg = firstException.getMessage();

    if (firstException instanceof ResourceException){

    errMsg = getErrorMessage((ResourceException)firstException);

    }

    ResourceException finalException = new ResourceException(AdapterUtil.getI18NMessage(AdapterUtil.getDefault RB(), "jioExceptionReason", new Object [] {"COTSAPIGetAllCustomers"})+":"+errMsg+":");

Note that the use of the String errMsg is in place of the firstException.getMessage().

The following is the code for the getErrorMessage method used to get the linked exception's messages.



   getErrorMessage method


private String getErrorMessage(ResourceException re) {
String errMsg = re.getMessage();
if (re.getErrorCode() != null) {
errMsg += "Error Code: " + re.getErrorCode();
}

while (re != null) {
Exception e = re.getLinkedException();
if (e != null) {
if (e instanceof ResourceException) {
re = (ResourceException)e;
errMsg += re.getMessage();
if (re.getErrorCode() != null) {
errMsg += "Error Code: " + re.getErrorCode();
}

} else {
errMsg += e.toString();
re = null;
}
} else {
re = null;
}
}
return errMsg;
}

With this customization to the JIO, the SOAP Client reports the following exception when accessing the SOAP Service while the EIS System is down.



  

Generated fault when invoking :http://localhost:80/soap/servlet/rpcrouterurn:COTS:COTSAPIGetAl lCustomers
Generated fault Code is :SOAP-ENV:Server
Generated fault String is :Exception from service object: Exception in the execution of JIO: COTSAPIGetAllCustomers:Error in getting the physical connectionError in getting COTS connectionjava.rmi.ConnectException: Connection refused to host: localhost; nested exception is: java.net.ConnectException: Connection refused: connect:

Preserving Customizations

All SOAP accessibility framework generated code components can be customized. If you never change the resource adapter definition - for example, by changing the serializer type or changing the participating classes information - then the generated customizable classes are never overwritten thus preserving the customizations. However, if you change the adapter definition that necessitates a change in the generated code, the affected files are regenerated. The old file which you customized is available to you as a .bak (or .bak, .bak2 etc.) file so that you can copy your customizations to the new file. The regeneration report contains details of what files are re-written and what files are preserved. Refer to "General Approach to Customizing Java Classes" for more details on the regeneration.

Note, Connector Builder checks every SOAP framework component individually. If you selectively delete certain files, only those files are generated as part of subsequent generations. The remaining files are left undisturbed provided you have not altered the adapter definition in a way that requires the files to be regenerated.


Previous      Contents      Index      Next     
Copyright 2002 Sun Microsystems, Inc. All rights reserved.