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 André Næss <an...@pointcarbon.com> on 2005/04/15 15:18:55 UTC

Is the Axis deserializer buggy?

Hi

I'm experiencing some very strange behavior when using Axis to transfer 
some simple data objects. The problem is an object which contains two 
string fields and one double string. I have however created a simplified 
example which shows the same error. I have this simple bean:

package axistest;

/**
 * @author André Næss (an@pointcarbon.com)
 */
public class StringPackage {

    String onestring;
    String twostring;

    public StringPackage(String onestring, String twostring) {
        this.onestring = onestring;
        this.twostring = twostring;
    }

    public String getOnestring() {
        return onestring;
    }

    public void setOnestring(String onestring) {
        this.onestring = onestring;
    }

    public String getTwostring() {
        return twostring;
    }

    public void setTwostring(String twostring) {
        this.twostring = twostring;
    }

    public String toString() {
        return "onestring=" + onestring + ", twostring=" + twostring;
    }

}

And the following service:

package axistest;

/**
 * @author André Næss (an@pointcarbon.com)
 */
public class AxisTest {

    public StringPackage getStrings() {
        return new StringPackage("onestring", "twostring");
    }
   
}

My deployment file:

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" 
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

  <beanMapping
    xmlns:ns="urn:AxisTest"
    qname="ns:StringPackage"
    languageSpecificType="java:axistest.StringPackage"/>

  <service name="AxisTest" provider="java:RPC">
    <parameter name="className" value="axistest.AxisTest"/>
    <parameter name="allowedMethods" value="*"/>
  </service>

</deployment>

And finally, my test client:

package axistest;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;

import javax.xml.rpc.ServiceException;
import javax.xml.namespace.QName;
import java.rmi.RemoteException;

/**
 * @author André Næss (an@pointcarbon.com)
 */
public class AxisTestClient {

    public static void main(String[] _) {

        try {

            QName qname = new QName("urn:AxisTest", "StringPackage");

            Service service = new Service();
            Call call = (Call) service.createCall();

            call.registerTypeMapping(StringPackage.class,
                                     qname,
                                     new 
BeanSerializerFactory(StringPackage.class, qname),
                                     new 
BeanDeserializerFactory(StringPackage.class, qname));

            
call.setTargetEndpointAddress("http://localhost:4545/axistest/services/AxisTest");
            call.setOperationName(new 
QName("urn:CO2PricesServiceServer", "getStrings"));
            StringPackage result = (StringPackage) call.invoke(new 
Object[]{});
            System.out.println("Result from web service:");
            System.out.println("result = " + result);

            AxisTest local = new AxisTest();
            StringPackage localResult = local.getStrings();
            System.out.println("Result from local object:");
            System.out.println("localResult = " + localResult);

        } catch (ServiceException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

Calling the client results in this output:

Result from web service:
result = onestring=onestring, twostring=onestring
Result from local object:
localResult = onestring=onestring, twostring=twostring

Inspecting the data that actually goes over the wire shows that they are 
as expected:

HTTP/1.1 200 OK
Content-Type: text/xml;charset=utf-8
Date: Fri, 15 Apr 2005 13:09:30 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:getStringsResponse 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns1="AxisTest">
            <getStringsReturn href="#id0"/>
         </ns1:getStringsResponse>
         <multiRef id="id0" soapenc:root="0" 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns2:StringPackage" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns2="urn:AxisTest">
            <onestring xsi:type="soapenc:string">onestring</onestring>
            <twostring xsi:type="soapenc:string">twostring</twostring>
         </multiRef>
      </soapenv:Body>
   </soapenv:Envelope>

So the problem is clearly with the deserialization in the client. The 
problem seems to be that when Axis is deserializing the object it fails 
to resolve the fields correctly, and instead use the type to figure out 
what parameter it is looking at. I used a debugger to step through the 
Axis code, and it looked to me like Axis was not able to find a proper 
QName for the fields onestring and twostring, and falls back to testing 
the type. But because the type is the same in both cases (String) this 
results in the wrong value.

Even if I have configured something wrong (which is quite likely, seeing 
as I don't really understand deploy.wsdd and the qname and namespace 
concept) I still think this must be a bug in Axis because it would be 
better if it failed and threw some sort of exception rather than mangle 
my data.

I hope someone can have a look at this. It would also be great if 
someone else could try this code out and see if they experience the same 
problems.

I'm running Axis 1.2RC3 on Tomcat5. I was not able to try with Axis 1.1 
because of issues after installing JRE5.0. (As soon as I get it 
uninstalled I'll try again).

--
André Næss

Re: Is the Axis deserializer buggy?

Posted by André Næss <an...@pointcarbon.com>.
Hi

After stepping through the code some more, I realized that maybe the 
problem was that my StringPackage class declared a constructor. While 
debugging I noticed that the constructor was being called, and somewhere 
far far in the back of my head a line from CS101 was whispering "when a 
constructor is defined for a class, the default constructor is removed". 
So if I either remove the StringPackage(String, String) constructor, or 
add the StringPackage(void) constructor the problem is resolved.

But having spent something like 5 hours tracking down this very subtle 
bug I must say that I think maybe Axis should have raised some sort of 
error rather than attempt to be smart. After all, the result of this 
smartness was mangled data, and we all know that no data is better than 
wrong data.

Should I post a bug report? Or am I simply a louse java programmer that 
should have understood that I couldn't declare the constructor as I did?

André Næss