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 Thad Humphries <th...@mindwrap.com> on 2005/08/12 22:34:31 UTC

deserialzing an array in a complex type

I'm having trouble deserializing a class that includes an array member.

I have two class that look like

public class ACLRec {
  public int        aclID;
  public String      aclName;
}

public class ACLList {
  public ACLRec  []    acls;
  public int          defaultACL;
}

Using TCP Monitor, the response seems okay (see below) but I'm getting an 
exception when I try to deserialize the response:

java.lang.IllegalArgumentException
  at 
sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
  at java.lang.reflect.Field.set(Field.java:656)
  at org.apache.axis.encoding.FieldTarget.set(FieldTarget.java:52)
  at 
org.apache.axis.encoding.DeserializerImpl.valueComplete(DeserializerImpl.java:249)
...

The problem seems that FieldTarget.set is looking for an object in the 'acls' 
field but seeing an array.  How do I properly register my array?  Right now 
I'm using:

  typesByMemberName.put( aclsMember,       OASQNames.aclRecQName );
  ...
  // Map (de)serializers for internal types here.
  TypeMappingRegistry reg = context.getTypeMappingRegistry();
  TypeMapping tm = (TypeMapping) 
reg.getOrMakeTypeMapping(Constants.URI_SOAP11_ENC);
  tm.register( ACLRec.class, OASQNames.aclRecQName,
    new org.apache.axis.encoding.ser.ArraySerializerFactory(ACLRec.class,
        OASQNames.aclRecQName),        
    new 
org.apache.axis.encoding.ser.ArrayDeserializerFactory(OASQNames.aclRecQName));        

  Deserializer dSer = context.getDeserializerForType( typeQName );
  try 
  {
      dSer.registerValueTarget( new FieldTarget(value, localName) );

This is the same as my serialization which is working.

Any ideas?

Axis Response:

<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>
      <listACLsResponse 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <listACLsReturn href="#id0"/>
      </listACLsResponse>
      <multiRef id="id0" soapenc:root="0" 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns1:oasSoapNamespace" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns1="urn:oasSoapNamespace">
         <acls soapenc:arrayType="ns2:ACLRec[2]" xsi:type="soapenc:Array" 
xmlns:ns2="oasSoapNamespace">
            <acls href="#id1"/>
            <acls href="#id2"/>
         </acls>
         <defaultACL xsi:type="soapenc:int">0</defaultACL>
      </multiRef>
      <multiRef id="id1" soapenc:root="0" 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns3:ACLRec" xmlns:ns3="oasSoapNamespace" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
         <aclID xsi:type="soapenc:int">1</aclID>
         <aclName xsi:type="soapenc:string">Example ACL</aclName>
      </multiRef>
      <multiRef id="id2" soapenc:root="0" 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns4:ACLRec" xmlns:ns4="oasSoapNamespace" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
         <aclID xsi:type="soapenc:int">0</aclID>
         <aclName xsi:type="soapenc:string">Disable ACLs</aclName>
      </multiRef>
   </soapenv:Body>
</soapenv:Envelope>

Re: deserialzing an array in a complex type

Posted by Thad Humphries <th...@mindwrap.com>.
Success!

I found that on my deserializer side, it is a two stop process:  One must 
register the deserializer for the class in the array and for the array 
itself.  Oddly, this does not appear necessary on the serializer side:  TCP 
Monitor shows the same soapenv:Envelope regardless.  So, in my serialzer's 
serialize() method, I have

  TypeMappingRegistry reg = context.getTypeMappingRegistry();
  TypeMapping tm = (TypeMapping)   
       reg.getOrMakeTypeMapping(Constants.URI_SOAP11_ENC);
  tm.register( ACLRec.class, OASQNames.aclRecQName,
       new ArraySerializerFactory(ACLRec.class, OASQNames.aclRecQName),        
       new ArrayDeserializerFactory(OASQNames.aclRecQName));

while in my deserializer I have

  TypeMappingRegistry reg = context.getTypeMappingRegistry();
  TypeMapping tm = (TypeMapping)   
       reg.getOrMakeTypeMapping(Constants.URI_SOAP11_ENC);
  tm.register( ACLRec.class, OASQNames.aclRecQName, 
       new ACLRecSerFactory(), new ACLRecDeserFactory() );
  tm.register( ACLRec[].class, OASQNames.aclRecArrQName,
       new ArraySerializerFactory(ACLRec.class, OASQNames.aclRecQName),        
       new ArrayDeserializerFactory(OASQNames.aclRecQName));

I believe this is because ArrayDeserializerFactory initializes only with a 
QName, not a class and QName.  Why not?  Is that an oversight in the API?

On Friday 12 August 2005 16:34, Thad Humphries wrote:
> I'm having trouble deserializing a class that includes an array member.