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