Hello:
I'm trying to understand how to write custom serializers and
deserializers. So created a user type called Book.java and has a
BookList as webservice that has a methods called getBookList that will
return a List that can 2 elements of type Book.
pubic class BookList{
......
public Vector getBookList(){
}
}
I wanted to serialize the Book.java to byte[] and then send that byte[]
as xsd:hexBinary. So the BookSerializer converts the Book.java to byte[]
to xsd:hexbinary and the BookDesrializer desrializes the xsd:hexbinary
to byte[] to Book.
Interestingly, at the client side, the SOAP Message has 2 Books but the
Vector that is deserialized from the client has only one Book. When I
debugged the Deserializer, I do see that both the books byte[] has been
converted to Book.
Not sure what I'm doing wrong.
Could someone give any suggestion.
Thanks,
Ravi
package samples.testing.usertype;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.Constants;
import org.apache.axis.encoding.ser.ElementDeserializerFactory;
import org.apache.axis.encoding.ser.ElementSerializerFactory;
import org.apache.axis.enum.Style;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.ParameterMode;
import java.net.URL;
import java.util.Vector;
public class Client {
static String tns = "booklist";
//static String tns = "http://www.xmethods.net/sd/CATrafficService.wsdl";
static String endpoint = "http://127.0.0.1:8415/axis/services/BookList"; //
tcpmon
//static String endpoint = "http://127.0.0.1:6415/axis/services/BookList";
// tomcat
static String wsdlUrl = endpoint + "?WSDL";
public static void main(String[] args) {
call1();
//call2();
}
public static void call1(){
try{
Service service = new Service();
Call _call = (Call)(service.createCall());
_call.setSOAPActionURI("");
_call.setOperationStyle(Style.RPC);
_call.setTargetEndpointAddress( new java.net.URL(endpoint) );
_call.setOperationName(new QName("booklist","getList"));
_call.registerTypeMapping(Book.class, new QName("booklist","book"),
BookSerFactory.class,
BookDeserFactory.class);
Vector result = (Vector)( _call.invoke(new Object[] {}));
for(int i = 0; i < result.size(); i++){
Book book = (Book)result.get(i);
System.out.println(" author is " + book.author + " name is " +
book.name);
}
}catch (Exception ex){
ex.printStackTrace();
}
}
public static void call2(){
try{
Service service = new Service(new URL(wsdlUrl), new
QName(tns,"VectorTestService"));
Call _call = (Call)(service.createCall(new
QName(tns,"VectorTest"),
new QName(tns,"setList")));
_call.setSOAPActionURI("");
Vector v = new Vector();
v.add("one");
v.add("two");
System.out.println(" Response from traffic is " + _call.invoke(new
Object[] {v}));
}catch (Exception ex){
ex.printStackTrace();
}
}
}
package samples.testing.usertype;
/**
*
*
* */
public class Book implements java.io.Serializable{
/** book name */
public String name;
/** book author */
public String author;
static final long serialVersionUID = 6795703128413131084L;
/**
* 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);
}
public String toString(){
return ("name is " + name + " author is " + author);
}
}
package samples.testing.usertype;
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.MethodTarget;
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.io.InputStream;
import java.util.*;
import org.apache.axis.message.MessageElement;
/**
*
*
*/
public class BookDeser extends DeserializerImpl {
public static final String NAMEMEMBER = "name";
public static final String AUTHORMEMBER = "author";
public static final String BOOKBYTES = "bookbytes";
public static final QName myTypeQName = new QName("booklist", "Book");
private Hashtable typesByMemberName = new Hashtable();
public BookDeser()
{
typesByMemberName.put(BOOKBYTES, Constants.XSD_HEXBIN);
value = new Book("","");
}
static public Object convertToObject(byte[] b) {
java.io.ObjectInputStream objStream = null;
try {
objStream = new java.io.ObjectInputStream(new
java.io.ByteArrayInputStream(b));
Object obj = objStream.readObject();
System.out.println(" from convert to object: " +
obj.toString());
return obj;
} catch (java.io.StreamCorruptedException sce){
return null;
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try{
if(objStream != null) objStream.close();
}catch (Exception ex1) {}
}
throw new RuntimeException(" from deserializer");
}
public void onEndChild(String namespace,
String localName,
DeserializationContext context) throws SAXException{
try {
if(!("bookbytes".equals(localName)))
return;
MessageElement ele = context.getCurElement();
byte[] content = (byte[])ele.getObjectValue();
System.out.println(" byte[] result is : " + content);
value = convertToObject(content);
} catch (Exception e) {
throw new SAXException(e);
}
}
}
package samples.testing.usertype;
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 BookDeser();
}
public Iterator getSupportedMechanismTypes() {
if (mechanisms == null) {
mechanisms = new Vector();
mechanisms.add(Constants.AXIS_SAX);
}
return mechanisms.iterator();
}
}
package samples.testing.usertype;
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 BookSer implements Serializer {
public static final String NAMEMEMBER = "name";
public static final String AUTHORMEMBER = "author";
public static final QName myTypeQName = new QName("booklist", "Book");
public void serialize(
QName name,
Attributes attributes,
Object value,
SerializationContext context)
throws IOException{
System.out.println(" entering serialize");
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);
System.out.println("QNAME during serialization is " + name);
context.serialize(new QName("","bookbytes"), null,
convertToBytes(data));
context.endElement();
System.out.println(" exiting serialize");
}
public String getMechanismType() {
return Constants.AXIS_SAX;
}
public Element writeSchema(Class arg0, Types types) throws Exception {
return null;
}
final static public byte[] convertToBytes(Object obj) {
java.io.ByteArrayOutputStream byteStream = null;
java.io.ObjectOutputStream objStream = null;
try {
byteStream = new java.io.ByteArrayOutputStream();
objStream = new java.io.ObjectOutputStream(byteStream);
objStream.writeObject(obj);
return byteStream.toByteArray();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if (objStream != null) objStream.close();
} catch(Exception ex1) {}
}
throw new RuntimeException("exception happened in convertToBytes");
}
}
package samples.testing.usertype;
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 BookSer();
}
public Iterator getSupportedMechanismTypes() {
if (mechanisms == null) {
mechanisms = new Vector();
mechanisms.add(Constants.AXIS_SAX);
}
return mechanisms.iterator();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="booklist"
xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="booklist"
xmlns:intf="booklist" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.2
Built on May 03, 2005 (02:20:24 EDT)-->
<wsdl:types>
<schema targetNamespace="http://xml.apache.org/xml-soap"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="Vector">
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="item"
type="xsd:anyType"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="setListRequest">
<wsdl:part name="in0" type="apachesoap:Vector"/>
</wsdl:message>
<wsdl:message name="getListResponse">
<wsdl:part name="getListReturn" type="apachesoap:Vector"/>
</wsdl:message>
<wsdl:message name="getListRequest">
</wsdl:message>
<wsdl:message name="setListResponse">
</wsdl:message>
<wsdl:portType name="BookList">
<wsdl:operation name="getList">
<wsdl:input message="impl:getListRequest" name="getListRequest"/>
<wsdl:output message="impl:getListResponse" name="getListResponse"/>
</wsdl:operation>
<wsdl:operation name="setList" parameterOrder="in0">
<wsdl:input message="impl:setListRequest" name="setListRequest"/>
<wsdl:output message="impl:setListResponse" name="setListResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BookListSoapBinding" type="impl:BookList">
<wsdlsoap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getList">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getListRequest">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://usertype.testing.samples" use="encoded"/>
</wsdl:input>
<wsdl:output name="getListResponse">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="booklist"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="setList">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="setListRequest">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://usertype.testing.samples" use="encoded"/>
</wsdl:input>
<wsdl:output name="setListResponse">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="booklist"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="BookListService">
<wsdl:port binding="impl:BookListSoapBinding" name="BookList">
<wsdlsoap:address
location="http://127.0.0.1:6415/axis/services/BookList"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
POST /axis/services/BookList HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.2
Host: localhost:8415
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 362
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getList
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="booklist"/>
</soapenv:Body>
</soapenv:Envelope>HTTP/1.1 200 OK
Content-Type: text/xml;charset=utf-8
Date: Thu, 16 Jun 2005 01:46:09 GMT
Server: Apache-Coyote/1.1
Connection: close
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getListResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="booklist">
<getListReturn href="#id0"/>
</ns1:getListResponse>
<multiRef id="id0" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Vector" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="http://xml.apache.org/xml-soap">
<item href="#id1"/>
<item href="#id2"/>
</multiRef>
<multiRef id="id1" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns3:book" xmlns:ns3="booklist"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<bookbytes
xsi:type="soapenc:base64">rO0ABXNyAB1zYW1wbGVzLnRlc3RpbmcudXNlcnR5cGUuQm9va15PL/14E1FMAgACTAAGYXV0aG9ydAASTGphdmEvbGFuZy9TdHJpbmc7TAAEbmFtZXEAfgABeHB0AAVhdXRoMXQABWJvb2sx</bookbytes>
</multiRef>
<multiRef id="id2" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns4:book" xmlns:ns4="booklist"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<bookbytes
xsi:type="soapenc:base64">rO0ABXNyAB1zYW1wbGVzLnRlc3RpbmcudXNlcnR5cGUuQm9va15PL/14E1FMAgACTAAGYXV0aG9ydAASTGphdmEvbGFuZy9TdHJpbmc7TAAEbmFtZXEAfgABeHB0AAVhdXRoMnQABWJvb2sy</bookbytes>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>