Creating Type Mappings

Apache SOAP uses type mappings to determine how Java datatypes should be marshalled to/unmarshalled from XML so that they can be transmitted on/received from the wire. The type mappings are stored in a type mapping registry, with the default registry being org.apache.soap.encoding.SOAPMappingRegistry.

Each type mapping carries several pieces of information: a URI describing the encoding style (i.e. http://schemas.xmlsoap.org/soap/encoding/,) a qualified name (QName) for the XML element (i.e. http://www.w3.org/2001/XMLSchema:int,) the Java class to be encoded from/decoded to, the name of the Java class to act as the serializer, and the name of the Java class to act as the deserializer. The Java classes acting as serializers/deserializers must implement org.apache.soap.util.xml.Serializer and org.apache.soap.util.xml.Deserializer, respectively.

To make life a little easier, a set of type mappings has been predefined and registered into the SOAPMappingRegistry for the SOAP encoding style. These include mappings for the following Java types:

The SOAPMappingRegistry also provides a type mapping to encode org.apache.soap.rpc.Parameters in the literal XML encoding style, and a set of mappings to encode types supported by the IBM XMI Framework in the XMI encoding style.

If you want to pass your own objects as parameters to SOAP RPC services, then you will need to register new type mappings (and possibly create your own serializers/deserializers.) Remember that you will need to register the new type mappings on both the server and the client sides.

Registering Type Mappings on the Server

There are two main ways to register type mapping information into an Apache SOAP server:

  1. Registering them via the deployment descriptor.
  2. Overriding the default mapping registry with a registry that has your new type mappings pre-registered.

The first way is probably the easiest to implement and manage, but it does require that you replicate the mapping information in each deployment descriptor that needs it. For more information on registering type mapping information via a deployment descriptor, look here.

The second mechanism requires a little more work, but allows you to limit the amount of additional information that you need to put into each deployment descriptor. In addition, the same mapping registry may be used on the client side, and thus may cut down on the amount of additional code that must be written for the client. The new registry must be a subclass of the SOAPMappingRegistry. For information about overriding the default mapping registry, look here.

Registering Type Mappings on the Client

As is the case with the server, on the client there are also two main ways to register type mapping information:

  1. Create an instance of the SOAPMappingRegistry and use the mapTypes(...) method to add new mappings.
  2. Create an instance of a subclass of the SOAPMappingRegistry that already has your mappings pre-registered.

The first way is probably the easiest to do, but if you have to use the same type mappings in multiple different clients or if you are also implementing the server-side as well, then the second method may save you a little bit of coding. The following code from GetAddress.java in the addressbook sample shows an example of mapping two classes that follow the Java Bean pattern.


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

    // Map the types.
    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);

    // Build the call.
    Call call = new Call();

    call.setSOAPMappingRegistry(smr);

The Bean Serializer/Deserializer

In many cases, even if there is not a default type mapping for the object that you are trying to transmit, you still may not need to create a new serializer/deserializer. Apache SOAP comes with a Java Bean Serializer/Deserializer that may suit your needs. The org.apache.soap.encoding.soapenc.BeanSerializer can be used to serialize and deserialize JavaBeans using the SOAP encoding style. The public properties of the bean will become named accessors (elements) in the XML form. To use the BeanSerializer, simply pass "org.apache.soap.encoding.soapenc.BeanSerializer" as the last two parameters when you are registering the type mapping for your object.

Note: The object that you are serializing with the BeanSerializer MUST be a JavaBean for this serializer to work:

This is NOT a general/all-purpose serializer. It WILL NOT work if the object which you are serializing/deserializing does not conform to the JavaBeans definition. It is NOT a bug if you cannot serialize/deserialize your non-Bean, Java class with this, any more than it is a bug that you can't serialize a java.awt.Panel with the java.util.Date serializer.

Creating New Serializers and Deserializers

If you need to create a new serializer/deserializer, then looking at the source code for the predefined ones will probably provide you with the best guidance. Remember that they will need to implement org.apache.soap.util.xml.Serializer and org.apache.soap.util.xml.Deserializer respectively. You can implement them both in the same class, or use two different classes, it really makes no difference.

Last updated 5/21/2001 by Bill Nagy <nagy@watson.ibm.com>.