axis-java-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Thad Humphries <t...@mindwrap.com>
Subject stumped on deserializer problem
Date Tue, 02 Aug 2005 21:10:24 GMT
I've been through the archives and seen numerous references to this same 
problem.  No suggestions have helped or clarified any of this for me.  
(Judging from the frequency of this question, most other folks are stumped, 
too.)  Can someone clear this up?  I promise to write this up for the Axis 
docs if I ever getting it figured out.  Maybe that will close this thread.

Recently I've read to start/restart Tomcat (I'm using TC 5.5.9) but that 
hasn't worked.  I'm using Axis 1.2.1.

I have a large set of Java classes that talk to a Sun RPC legacy application.  
I want to access the legacy app via SOAP.  The Java classes were written 
without much (if any) thought to Beans (the Java API was to mimic the C/C++ 
API as closely as possible).  Hence BeanSerialization is not appropriate 
(methods like isFoo() or getFoo() often do not have an underlying foo 
member).  With the user's guide to custom serialization TBD, I have been 
using samples/encoding and Google finds as a guide.  When I adapt 
samples/encoding/TestSer.java to test my class, it works perfectly but when I 
try to call client-server via Axis, I get the exception:

"Caught RemoteException: org.xml.sax.SAXException: Deserializing parameter 
'pObjectID':  could not find deserializer for type 
{urn:oasSoapNamespace}ObjectID"

Here (in summary) are my files classes:

// deploy.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <service name="OASService" provider="java:RPC">
    <parameter name="className" value="com.optix.soap.OASService"/>
    <parameter name="allowedMethods" value="*"/>
    <parameter name="scope" value="Session"/>
    <typeMappings>
      <typeMapping qname="ns:oasSoapNamespace" xmlns:ns="urn:oasSoapNamespace"
          languageSpecificType="java:com.optix.database.ObjectID"
          type="java:com.optix.database.ObjectID"
          serializer="com.optix.soap.encoding.ObjectIDSerFactory"
          deserializer="com.optix.soap.encoding.ObjectIDDeserFactory"
          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      <typeMapping qname="ns:oasSoapNamespace" xmlns:ns="urn:oasSoapNamespace"
          languageSpecificType="java:com.optix.database.OSType"
          type="java:com.optix.database.OSType"
          serializer="com.optix.soap.encoding.OSTypeSerFactory"
          deserializer="com.optix.soap.encoding.OSTypeDeserFactory"
          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </typeMappings>
  </service>
</deployment>

// The server application, OASService.java
public class OASService 
{
    OAS oas;
    public String getFileObjectPathname ( ObjectID pObjectID ) {
        try {
            return oas.getFileObjectPathname( pObjectID );
        } catch ( OptixException e ) {
            return e.getMessage();
        }
    }
}

// OASQNames.java
public interface OASQNames
{
    public static final QName objectIDQName = new 
QName( "urn:oasSoapNamespace", "ObjectID" );
    public static final QName osTypeQName   = new 
QName( "urn:oasSoapNamespace", "OSType" );
}

// ObjectIDSer.java
public class ObjectIDSer implements Serializer, OASQNames
{
    public static final String hostNumberMember     = "hostNumber";
    public static final String typeIDMember         = "typeID";
    public static final String objectNumberMember   = "objectNumber";
    public static final String revisionNumberMember = "revisionNumber";

    public void serialize ( QName name, Attributes attributes, Object value, 
        SerializationContext context )
    throws IOException
    {
        if (!(value instanceof ObjectID))
            throw new IOException( "Can't serialize a " + 
value.getClass().getName() + " with ObjectIDSer.");
        ObjectID objID = (ObjectID)value;

        context.startElement( name, attributes );
        context.serialize( new QName("", hostNumberMember), null, new 
Integer(objID.hostNumber) );

        TypeMappingRegistry reg = context.getTypeMappingRegistry();
        TypeMapping tm = (TypeMapping) 
reg.getOrMakeTypeMapping(Constants.URI_SOAP11_ENC);
        tm.register( OSType.class, osTypeQName, 
            new OSTypeSerFactory(), new OSTypeDeserFactory() );
        context.serialize( new QName("", typeIDMember), null, objID.typeID );

        context.serialize( new QName("", objectNumberMember), null, new 
Integer(objID.objectNumber) );
        context.serialize( new QName("", revisionNumberMember), null, new 
Integer(objID.revisionNumber) );
        context.endElement();
    }
...
}

// ObjectIDDeser.java
public class ObjectIDDeser extends DeserializerImpl implements OASQNames
{
    public static final String hostNumberMember     = "hostNumber";
    public static final String typeIDMember         = "typeID";
    public static final String objectNumberMember   = "objectNumber";
    public static final String revisionNumberMember = "revisionNumber";
    
    private Hashtable typesByMemberName = new Hashtable();  
    
    public ObjectIDDeser()
    {
        typesByMemberName.put( hostNumberMember,     Constants.XSD_INT );
        typesByMemberName.put( typeIDMember,         osTypeQName );
        typesByMemberName.put( objectNumberMember,   Constants.XSD_INT );
        typesByMemberName.put( revisionNumberMember, Constants.XSD_INT );
        value = new ObjectID();
    }

    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 ObjectID 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;
    }
}

The factory classes exist for the serializer/deserializer and look like 
samples/encoding/DataSerFactory.java and 
samples/encoding/DataDeserFactory.java.  I've also written the necessary 
serializer/deserializer classes for the type OSType.

What gives here?  Is there some deep magic with the QNames and/or namespaces 
that I am missing?  Is there some way they have to match up between the 
classes and the deploy.wsdd?  Would any more code help?  I'd like to review 
my errors/misunderstandings here but I will send my phone number or AIM ID 
(privately) if we need to talk to get this resolved.  I seriously want to 
write up a solution for the user's manual but I need to understand this and 
recreate it.

Thanks, folks.

Mime
View raw message