(bear with me, this is a bit of a long question)

I'm working on a project, Kuali Rice (http://www.kuali.org/rice), that
basically acts as a service bus for a series of other systems.  We are
using CXF behind the scenes to publish JAX-WS annotated services that
are written code-first.  These services can either be looked up and
accessed by a client through a JAX-WS service proxy or, if Rice is
running embedded in an app, an actual reference to the implementation
can be given the to client.

This works great in the general case.  However we've recently started
trying to enforce immutability on lots of our model objects and
Collections/Maps of those model objects for various reasons.  Our
services are using these immutable model objects as both parameters
and return types.  Where this breaks down with JAX-WS and SOAP is in
the case where a service method returns a Collection of these model
objects back and we want the Collection itself to be immutable (e.g.
the type you would get back from one of the
Collections.unmodifiable*() methods).  If a client makes a service
call through the JAX-WS proxy and the return type is
List<SomeModelObject> then what it gets back is a modifiable List.
This basically means that the two possible implementations that a
client can reference will have different behaviors that break the
documented expectation of what gets returned from method calls that
return a List type (that expectation being an immutable list).

Despite the fact that these services are code first, we are striving
to to make sure that the generated WSDL/XSD from our JAXB and JAX-WS
annotated types and services produce somewhat of a sane contract for
possibly non-java clients to use in the future.  As such, doing
something like introducing an actual type for an ImmutableList (or
using something like ImmutableList from guava) would create needless
and java specific types in the generated WSDL/XSD.  We didn't go that
route for that very reason.

The first thing I tried was to write a simple XmlAdapter to that would
return an immutable List reference during unmarshalling.  It ended up
looking like this:


public class ImmutableListAdapter extends XmlAdapter<Object[], List<?>> {

    @Override
    public List<?> unmarshal(Object[] objects) throws Exception {
        return Collections.unmodifiableList(Arrays.asList(objects));
    }

    @Override
    public Object[] marshal(List<?> objects) throws Exception {
        return objects.toArray();
    }

}


This works, but now the generated XSD/WSDL has those sequences that
represent Lists as a sequence of <xs:any> types, which again we'd
prefer not to have in order to keep the XSD/WSDL sane in the future
for non java clients to use.   We could write an adapter for every
single List<SomeModelObject> there such that the unbounded wildcard
type isn't used and we are marshing to/from a
SomeJaxbAnnotatedModelObject[] instead of Object[] each time (thus
preventing the sequences of xs:any), but this seems like massive
overkill to do for every single model object that we have.   Is there
another possible way to do this with a XmlAdapter that wouldn't
require such duplication?

If a JAXB Adapter is not the way to go with this, would it possible
(and straightforward) to do this in a CXF interceptor that might do
the same thing as this XmlAdapter but in such a way that it does not
alter the generated XSD?  If so, what phase should that interceptor be
bound to?

Reply via email to