All of my domain objects have a client interface that they implement
("separation of interface and implementation" and all that), so on the rare
occasion that I have an array property, it is inevitably an array of
interfaces.

Doing the straightforward approach that works elsewhere (just map the
implementation class and the property) failed.  I did some searching on the
mailing list and found the suggestion to map the interface as well.  When I
tried to use the TypedArrayMapper on the interface type with an abstract
mapping on the interface and an extends element on the implementation, I still
get this exception during marshalling:

org.jibx.runtime.JiBXException: Invalid object type for marshaller
    at org.jibx.extras.TypedArrayMapper.marshall(TypedArrayMapper.java:166)
    ...

When I looked at TypedArrayMapper.marshall, two problems in the code became
apparent.

            // verify object as a handled array type
            Class clas = obj.getClass();
            if (!clas.isArray() ||
!IMarshallable.class.isAssignableFrom(clas.getComponentType())) {

First and most importantly, this code is checking that the property is a mapped
type based on reflection from the referring class, instead of checking the
actual instances.  I ought to be able to have an Object[] array and have the
checking occur the same way it does for collection types: on the actual
instances of the array/collection.  This is pretty easy to fix:

Class clas = obj.getClass();
////////////  CHANGES BEGIN HERE ////////////////////////
if (!clas.isArray()) {
////////////  CHANGES END HERE ////////////////////////
    throw new JiBXException("Invalid object type for array marshaller: " +
clas.getName());
} else {

    [...]

    // loop through all entries in array
    for (int i = 0; i < array.length; i++) {
         Object item = array[i];
         if (item == null) {
             throw new JiBXException("Null value at offset " + i +
                 " not supported");
////////////  CHANGES BEGIN HERE ////////////////////////
         } else if (!(item instanceof IMarshallable)) {
             throw new JiBXException("Invalid object type for marshaller" +
item.getClass().getName());
////////////  CHANGES END HERE ////////////////////////
         } else {
             ((IMarshallable)item).marshal(ctx);
         }
    }
}

Once the TypedArrayMapper is fixed with the changes above, it turns out that
there is no need to bind the interface (and thank goodness: one-deep
inheritance is already forcing enough issues into my object model without
spending it on my interfaces).

The second error that the early IMarshallable check reveals that my interface
type, though mapped as an abstract type, has not been modified to extend
IMarshallable.  I haven't investigated this in any depth, so I don't know if
IMarshallable is only for concrete types, or perhaps only appropriate for
classes, but this would seem to interfere with a number of use cases where the
object model heavily uses interfaces.

Regards,
Ross


-------------------------------------------------------
This SF.Net email is sponsored by Yahoo.
Introducing Yahoo! Search Developer Network - Create apps using Yahoo!
Search APIs Find out how you can build Yahoo! directly into your own
Applications - visit http://developer.yahoo.net/?fr=offad-ysdn-ostg-q22005
_______________________________________________
jibx-users mailing list
jibx-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jibx-users

Reply via email to