users@jax-rpc.java.net

Re: Use of derived classes in JAX-RPC methods

From: Kim Topley <kt_at_topley.demon.co.uk>
Date: Tue, 29 Oct 2002 20:30:12 +0000

Thank you for confirming that. Maybe you could help me with
another issue in the same area.

Suppose I defined a method that returns a HashMap in which the
values are of type String[]. In order for serialization to work,
I need to add java.lang.String[] to the additionalTypes list and
use the usual model trick to get wsdeploy to recognize them.
Having done this, both the client and server ends have a serializer
for ArrayOfstring. This looks good. Further, the type mapping
registry at both ends gets set up with a mapping to this serializer
for Java type String[] and XML type ArrayofString.

However, when I call this method, I get an error on the client side
during deserialization -- the client deserialization happens upon
an <item> element, but it expects to see an <element> element. This
<item> element is inside the multi-ref serialization of the String[]
object, which looks a bit like this:

<ns0:ArrayOfstring xsi:type="enc:Array" ......>
   <item xsi:type="xsd:string">First in array</item>

</ns0:ArrayOfstring>

etc (from memory, so this may not be 100% correct).

What seems to happen is this:

1. On the server side, a serializer for Java type String[] is required
during serialization of the HashMap. This finds the one for
ArrayOfstring,
so the array is serialized as shown above, which looks correct to me.

2. On the client side, while deserializing the value in the HashMap,
the code looks not at the element name (ArrayOfstring), but at the
type -- enc:Array. This results in it using the polymorphic array
deserializer (is I think the correct name) instead of the registered
deserializer ArrayOfstring. Unfortunately, this deserializer expects
to see nested <element> elements, not nested <item> elements.

As a result of this, I can't see how to handle cases where I need to
transfer a String[] (and it probably applies to other array types as
well) unless the type is explicitly called out in the method signature.
Is this a known issue, or am I doing something wrong?

Regards
Kim Topley
Keyboard Edge Limited



Doug Kohlert wrote:
>
> Kim, your observations are correct and this is the intended behavior.
> We took this stance for strictly a performance point of view as it takes
> extra time at runtime to determine what is being serialized/deserialized
> etc. So you are correct that you should create an AbstractValueType to
> achieve the desired results.
>
> Thank you for your interest in JAXRPC.
>
> Kim Topley wrote:
> > Suppose I define an endpoint that uses two value types:
> >
> > BaseValueType - a value type acting as a base class, which is not abstract.
> > DerivedValueType - a value type derived from BaseValueType.
> >
> > Suppose also that the endpoint includes the following methods:
> >
> > public BaseValueType transform(BaseValueType type)
> > throws RemoteException;
> > public HashMap geValueTypes() throws RemoteException;
> >
> > The first method accepts a BaseValueType object and returns it after
> > making some changes. The second returns a HashMap in which all instances
> > of BaseValueType appear as values. Any and all instances of BaseValueType
> > could, of course, be instances of DerivedValueType.
> >
> > In order to deploy and run this service, the necessary additionalTypes
> > element for DerivedValueType is added to config.xml and the endpoint
> > element in the jaxrpc-ri.xml file refers to a model file, so that a
> > serializer/deserializer for ExtendedValueType is created and registered
> > at both the client and server ends.
> >
> > Here's the problem. If the client calls the transform() method and sends
> > a DerivedValueType, it actually gets serialized as a BaseValueType. The
> > same would happen at the server end. However, if the server includes
> > DerivedValueTypes in the HashMap it returns from getValueType(), then this
> > is serialized properly and the client will get the right type.
> >
> > It seems that the following is true:
> >
> > 1. If the argument or return value is Object, an abstract class or an
> > interface (that also look like valid value types), or if the object
> > is in a collection, then the serialization choice is made at run-time,
> > as it would have to be.
> > 2. If, however, the method signature involves concrete types, then the
> > choice of serialization is made at compile time.
> >
> > In other words, to get the expected result, I would have to change the
> > signature of the transform() class to
> >
> > public Object transform(Object o)
> >
> > or introduce an abstract base class:
> >
> > public AbstractValueType transform(AbstractValueType o)
> >
> > and then derive BaseValueType from it.
> >
> > Is this correct? And is it intended, or just a feature of the JAX-RPC
> > reference implementation.
> >
> > Thanks in advance
> > Kim Topley
> > Keyboard Edge Limited
>
> --
> Doug Kohlert
> Java Software Division
> Sun Microsystems, Inc.
> phone: 503 345-9806