Supported datatypes  Chapter 4: Web Services Administration

Chapter 3: Components, Datatypes, and Type Mappings

Custom datatypes and mappings

Theoretically, any object or datatype that can be described by a valid snippet of XML can be used as a parameter within a SOAP call. Current support of advanced datatypes in Web services is based on the serialization framework specified by the JAX-RPC 1.0/1.1 specification. See the JAX-RPC Web site for more information.


Creating custom type mappings

This section describes how to use the WST development tool to create type mappings and associate a Web service with a type mapping.

StepsCreating a Web service type mapping

  1. Select File | New | Other | Sybase Web Services | Type Mapping.

  2. Follow the wizard instructions to create the type mapping. Table 3-2 describes the Web service type mapping properties.

Table 3-2: Web service type mapping wizard

Window

Property

Description

Type Mapping Classes Selection

Type Class

A user defined structure or Java class whose mapping to XML is not standard. For example java.sql or resultsets.

Serializer Class

The fully qualified name of the serialization class used to convert the new datatype to XML.

Deserializer Class

The fully qualified name of the deserialization class used to convert the serialized XML data into application data.

SerializerFactory Class

An instance of the serialization class.

DeserializerFactory Class

An instance of the deserializer class.

Type Mapping WSDL Definition

Use Web Service Target NameSpace as Type Mapping’s NameSpace

Each type mapping can have its own namespace or have the same namespace as the Web service’s target namespace. If this property is selected, then “Type Mapping Namespace” is disabled.

Type Mapping NameSpace

The type mapping namespace (if not using the Web service’s target namespace).

Local Part

The local part of a qualified name (QName) which consists of a namespace plus “:” plus a local part serves as a pointer to a WSDL definition part.

Encoding Style

The encoding style used by the XML parser to apply when transforming a SOAP message to a Java object. Use “SOAP” unless you have defined an alternative encoding style for this class.

Store the Created Type Mapping to Local Store

Select Local Store or Create New Store

You can select an existing store for this type mapping or create a new one. Normally, a type mapping store consists of a description file and a list of JAR files. The description file contains the information of the first two windows, the JAR contains the serializer, deserializer, serializer factory, and deserializer factory classes. You can select “Sybase Web Service View,” and select type mappings to import them into the desired local store.

Undefined Type Mapping Found in Class

Please Define the Undefined Type Mapping Found for This

When you click “Select a Java file,” and create a Web service from it, this wizard displays if the selected Java file contains an undefined type mapping.

Click Add to launch the Web Service Type Mapping creation wizard to create a type mapping for this datatype.

NoteJava coding standards Web Services Toolkit follows Java coding standards. When you use any Java class name in your Web service, or user defined types in the IDL, the name must start with an upper case letter. If the names or types start with a lower case letter, you might see a “class not found” error.


Creating serializers and deserializers

There might be instances where the existing serializers and deserializers provided with the WST are not adequate to expose a class or component through SOAP. In this case, you must create custom serializer and deserializer classes to perform the necessary actions to convert the class to and from XML.

A new serializer and deserializer requires a new Java class that implements the javax.xml.rpc.encoding.Serializer for the serializer and javax.xml.rpc.encoding.DeSerializer for the deserializer.

The following nonbeansample example illustrates various aspects of creating a serializer and deserializer for a user-defined datatype.

Description

The following listing contains these files:

Listing

 /*
*/
package nonbeansample;

import org.apache.axis.encoding.DeserializerImpl;
import org.apache.axis.Constants;
import org.apache.axis.encoding.DeserializationContext;
import org.apache.axis.encoding.Deserializer;
import org.apache.axis.encoding.FieldTarget;
import org.apache.axis.message.SOAPHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import javax.xml.namespace.QName;
import java.util.Hashtable;

/**
 *
 *
 */
public class BookDeserializer extends DeserializerImpl {
		 public static final String NAMEMEMBER = "name";
		 public static final String AUTHORMEMBER = "author";
		 public static final QName myTypeQName = new QName("typeNS", "Book");

		 private Hashtable typesByMemberName = new Hashtable();  

		 public BookDeserializer()
		 {
		 		 typesByMemberName.put(NAMEMEMBER, Constants.XSD_STRING);
		 		 typesByMemberName.put(AUTHORMEMBER, Constants.XSD_STRING);
		 		 value = new Book("","");
		 }

		 /** DESERIALIZER - event handlers
		  */

		 /**
		  * This method is invoked when an element start tag is encountered.
		  * @param namespace is the namespace of the element
		  * @param localName is the name of the element
		  * @param prefix is the element's prefix
		  * @param attributes on the element...used to get the type
		  * @param context is the DeserializationContext
		  */
		 public SOAPHandler onStartChild(String namespace,
		 		 		 		 				 String localName,
		 		 		 		 	 			 String prefix,
		 		 		 		 	 		 	 Attributes attributes,
		 		 		 		 		 		 DeserializationContext context)
		 		 throws SAXException
		 {
		 QName typeQName = (QName)typesByMemberName.get(localName);
		 if (typeQName == null)
	 	 throw new SAXException("Invalid element in Book struct - " + localName);
        
		 		 // These can come in either order.
		 		 Deserializer dSer = context.getDeserializerForType(typeQName);
		 		 try {
		 		 dSer.registerValueTarget(new FieldTarget(value, localName));
		 		 } catch (NoSuchFieldException e) {
		 		 		 throw new SAXException(e);
		 		 }
    
		 		 if (dSer == null)
		 		 		 throw new SAXException("No deserializer for a " + typeQName + "???");
       
		 		 return (SOAPHandler)dSer;
		 }

}
/*
 *
 *
 * package nonbeansample;

import org.apache.axis.encoding.DeserializerFactory;

import org.apache.axis.Constants;
import java.util.Iterator;
import java.util.Vector;

/**
 * *
 *
 */
public class BookDeserFactory implements DeserializerFactory {
		 private Vector mechanisms;

		 public BookDeserFactory() {
		 }
		 public javax.xml.rpc.encoding.Deserializer getDeserializerAs(String mechanismType) {
		 		 return new BookDeserializer();
		 }
		 public Iterator getSupportedMechanismTypes() {
		 		 if (mechanisms == null) {
		 		 		 mechanisms = new Vector();
		 		 		 mechanisms.add(Constants.AXIS_SAX);
		 		 }
		 		 return mechanisms.iterator();
		 }
}
/*
 * 
 *
 * */
package nonbeansample;


/**
 *
 *
 * */
public class Book {
    /** book name */
    public String name;

    /** book author */
    public String author;

    /**
     * Constructor.
     * @param name book name
     * @param author book author
     * @throws IllegalArgumentException name or author is null
     */
    public Book(String name, String author) {
        if (name == null) {
            throw new IllegalArgumentException("Name is null!");
        }

        if (author == null) {
            throw new IllegalArgumentException("Author is null!");
        }

        this.name = name;
        this.author = author;
    }

    /**
     * Test for equality.
     * @param object any object
     * @return true if books are equal
     */
    public boolean equals(Object object) {
        if (!(object instanceof Book)) {
            return false;
        }

        Book secondBook = (Book) object;

        return name.equals(secondBook.name) &&
        author.equals(secondBook.author);
    }
}
/*
 * */
package nonbeansample;

import java.util.Iterator;
import java.util.Vector;
import org.apache.axis.Constants;

import org.apache.axis.encoding.SerializerFactory;

/**
*/
public class BookSerFactory implements SerializerFactory {
		 private Vector mechanisms;

		 public BookSerFactory() {
		 }
		 public javax.xml.rpc.encoding.Serializer getSerializerAs(String mechanismType) {
		 		 return new BookSerializer();
		 }
		 public Iterator getSupportedMechanismTypes() {
		 		 if (mechanisms == null) {
		 		 		 mechanisms = new Vector();
		 		 		 mechanisms.add(Constants.AXIS_SAX);
		 		 }
		 		 return mechanisms.iterator();
		 }
}
*/
package nonbeansample;

import java.io.IOException;

import javax.xml.namespace.QName;

import org.apache.axis.encoding.SerializationContext;
import org.apache.axis.encoding.Serializer;
import org.apache.axis.wsdl.fromJava.Types;
import org.w3c.dom.Element;
import org.xml.sax.Attributes;
import org.apache.axis.Constants;

/**
*/
public class BookSerializer implements Serializer {
		 public static final String NAMEMEMBER = "name";
		 public static final String AUTHORMEMBER = "author";
		 public static final QName myTypeQName = new QName("nonBeanTypes", "Book");

		 /** SERIALIZER 
		  */
		 /**
		  * Serialize an element named name, with the indicated attributes
		  * and value.
		  * @param name is the element name
		  * @param attributes are the attributes...serialize is free to add more.
		  * @param value is the value
		  * @param context is the SerializationContext
		  */
		 public void serialize(
		 		 QName name,
		 		 Attributes attributes,
		 		 Object value,
		 		 SerializationContext context)
		 		 throws IOException {
		 		 if (!(value instanceof Book))
		 		 		 throw new IOException(
		 		 		 		 "Can't serialize a "
		 		 		 		 		 + value.getClass().getName()
		 		 		 		 		 + " with a BookSerializer.");
		 		 Book data = (Book) value;

		 		 context.startElement(name, attributes);
		 		 context.serialize(new QName("", NAMEMEMBER), null, data.name);
		 		 context.serialize(new QName("", AUTHORMEMBER), null, data.author);
		 		 context.endElement();
		 }
		 public String getMechanismType() {
		 		 return Constants.AXIS_SAX;
		 }

		 /* (non-Javadoc)
		  * @see org.apache.axis.encoding.Serializer#writeSchema(java.lang.Class, org.apache.axis.wsdl.fromJava.Types)
		  */
		 public Element writeSchema(Class arg0, Types types) throws Exception {
		 		 //  Auto-generated method stub
		 		 Element complexType = types.createElement("complexType");
		 		 types.writeSchemaElement(myTypeQName, complexType);
		 		 complexType.setAttribute("name", myTypeQName.getLocalPart());
		 		 Element seq = types.createElement("sequence");
		 		 complexType.appendChild(seq);

		 		 Element element = types.createElement("element");
		 		 element.setAttribute("name", "name");
		 		 element.setAttribute("type", "xsd:string");
		 		 seq.appendChild(element);
		 		 Element element2 = types.createElement("element");
		 		 element2.setAttribute("name", "author");
		 		 element2.setAttribute("type", "xsd:string");
		 		 seq.appendChild(element2);

		 		 return complexType;
		 }
}

Deployment

The deployment of custom type mappings requires serializer and deserializer classes and the associated factories, the SOAP encoding, and the qualifying name (Qname). The Qname helps reduce the chance of collisions of elements that use the same name (description, item, and other entities), by adding an additional element, which makes it more likely to produce a unique element:

Qname = namespace identifier + local name

The deployment of type mappings occurs as part of Web service creation and deployment. Type mappings are deployed at the Web service level.


Scope of type mappings

A type mapping can be deployed only as part of a Web service, or when exposing a component. Even though a type mapping is deployed as only part of a service, a client can look up all the service mappings installed on a server.

Once a type mapping is deployed, it is associated with a Web service. But the same type mapping can be used with other Web services as well.


Exporting

From the Web service Server view, you can select a Type Mapping and export. You can then specify the local store, and import the JAR and additional information (Type Mapping Namespace, Local Part, and Encoding Style) to the selected local store.





Copyright © 2005. Sybase Inc. All rights reserved. Chapter 4: Web Services Administration