In the process of investigating AXIS1.1b for feasibility of a migration from
the ApacheSOAP2.2/2.3 we're using, I noticed some unexpected (to me at least
:-) behavior with deserialization of an XSD hexBinary response value.
The Default TypeMapping implementation registers the known XSD simple types
with their corresponding serializers/deserializers, and the TypeMapping
implementation has last-one-in-wins behavior.
I was attempting to call some SOAP Interop Round2a services with my own
client code, to make sure I understood how and if everything was working as
expected (and how it differs form how we're using ApacheSOAP2.2/3) when I
noticed that if I send an org.apache.types.HexBinary object to an
echoHexBinary method, I got back a byte[] instead of the expected (by me)
HexBinary class (since byte[] typically maps to XSD base64)
The following code from org.apache.axis.encoding.DefaultTypeMappingImpl
effectively overrides the mapping from XSD_HEXBIN to the HexBinary.class
with its subsequent mapping of XSD_HEXBIN to the byte[].class.
ONE of those two DeserializerFactory arguments should be null, to make it
clear that the other type is what's intended - which is it? Is it correct
the way it is? (if so, I suggest making the deser factory arg in the first
register below null to make it obvious that's the case - otherwise, the
deser factory arg in the second register call below should be null, no?)
// HexBinary binary data needs to use the hex binary
serializer/deserializer
myRegister(Constants.XSD_HEXBIN, HexBinary.class,
new HexSerializerFactory(
HexBinary.class, Constants.XSD_HEXBIN),
new HexDeserializerFactory(
HexBinary.class, Constants.XSD_HEXBIN));
myRegister(Constants.XSD_HEXBIN, byte[].class,
new HexSerializerFactory(
byte[].class, Constants.XSD_HEXBIN),
new HexDeserializerFactory(
byte[].class, Constants.XSD_HEXBIN));
Then I got curious as to how the AXIS SOAP Interop test itself was working -
turns out that it converts the results to byte[] for both input and output
(if either is HexBinary) before doing the comparison, so it won't notice if
the two classes (input vs output) are different. Not sure if that was
intentional because of the default mismatched behavior or whether the
mismatched behavior (have to send HexBinary class by default because byte[]
would map to Base64, but by default receive byte[] back if hexBinary
returned) has just not been noticed because of the way the test happens to
do its comparisons...
>From AXIS samples.echo.TestClient.java
protected boolean equals(Object obj1, Object obj2) {
if (obj1 == null || obj2 == null) return (obj1 == obj2);
if (obj1.equals(obj2)) return true;
// For comparison purposes, get the array of bytes representing
// the HexBinary object.
if (obj1 instanceof HexBinary) {
obj1 = ((HexBinary) obj1).getBytes();
}
if (obj2 instanceof HexBinary) {
obj2 = ((HexBinary) obj2).getBytes();
}
... other types compared below that...