You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-user@axis.apache.org by Greg Adams <ga...@gmail.com> on 2005/12/12 21:36:54 UTC

Custom serializer for xml-aware classes

I've got a situation where I need to write a custom serializer for classes
that are able to give the XML representations of themselves via toString().
I've messed around with writing a custom serializer in various ways,
following the examples of BeanSerializer, DocumentSerializer, etc.. just
trying thing out and can't seem to come up with any encouraging leads.

Here's my current serializer factory:


package grega.encoding.ser;

import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;

import org.apache.axis.encoding.Serializer;
import org.apache.axis.encoding.ser.BaseSerializerFactory;

public class MySerializerFactory extends BaseSerializerFactory {

    public MySerializerFactory(Class javaType, QName xmlType) {
        super(MySerializer.class, xmlType, javaType);
    }

    public javax.xml.rpc.encoding.Serializer getSerializerAs(String
mechanismType)
            throws JAXRPCException {
        return (Serializer) super.getSerializerAs(mechanismType);
    }

    /**
     * Optimize construction of a BeanSerializer by caching the type and
property
     * descriptors.
     */
    protected Serializer getGeneralPurpose(String mechanismType) {
        return new MySerializer();
    }
}

and here's my current serializer:

package grega.encoding.ser;

import java.io.IOException;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

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

import grega.SaxContainer;


public class MySerializer implements Serializer {

    public void serialize(QName qName, Attributes attribs, Object value,
            SerializationContext ctx) throws IOException {
        if (value instanceof SaxContainer) {
            ctx.startElement(qName, attribs);
            DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
            try {
                DocumentBuilder builder = factory.newDocumentBuilder();
                Document doc = builder.parse(value.toString());
                ctx.writeDOMElement(doc.getDocumentElement());
                ctx.endElement();
            } catch (SAXException e) {
                throw new IOException(e.getMessage());
            } catch (ParserConfigurationException e) {
                throw new IOException(e.getMessage());
            }
        } else {
            throw new IOException("value is a " + value.getClass() + ", not
a SaxContainer");
        }

    }

    public Element writeSchema(Class clazz, Types types) throws Exception {
        return null;
    }

    public String getMechanismType() {
        return Constants.AXIS_SAX;
    }
}


Now what's confusing to me is that if I have a server-config.wsdd containing
this:

<typeMapping qname="typens:Country"
        type="java:grega.CountryXml"
        serializer="grega.encoding.ser.MySerializerFactory"
        deserializer="grega.ser.MyDeserializerFactory"
    />

in the MySerializer.serialize method, the QName argument has a value of
"multiRef". I don't want to serialize to a multiref element, I want to
serialize directly into the place where the type is used in the SOAP
message, right? So I figure that Axis is trying to do some kind of multi-ref
SOAP encoding, and I remember reading somewhere (this whole Axis thing is
kind of a haze), about using encodingStyle="" on the typemapping when using
document or wrapped style services, which I am, so I changed it to:

<typeMapping qname="typens:Country"
        type="java:grega.CountryXml"
        serializer="grega.encoding.ser.MySerializerFactory"
        deserializer="grega.ser.MyDeserializerFactory"
        encodingStyle=""
    />

but then I get the following AxisFault at serialization time:

AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode:
 faultString: java.io.IOException: No serializer found for class
grega.CountryXml in registry
org.apache.axis.encoding.TypeMappingDelegate@f9e48


so apparently setting encodingStyle="" causes my typeMapping to not register
MySerializer as valid for the type I'm configuring. Why?

Any pointers on how to get the serializer to work would be greatly
appreciated. There's so little documentation on how custom serialization
works in Axis.

Thanks,
Greg Adams