Hi Dan,

I'm doing 2) now, though it does now work quite well for JSON, but it's
a good start. Will definitely look into using ASM as well...

Cheers, Sergey

-----Original Message-----
From: Daniel Kulp [mailto:[email protected]] 
Sent: 15 July 2009 19:23
To: [email protected]
Cc: Sergey Beryozkin
Subject: Re: Handling Collection<JAXBElement> returns via JAX-RS


Well, on the JAX-WS side of things, if a method returns something like 
List<Foo> getFoos(), one of two things happens depending on if ASM is
found on 
the classpath:

If ASM is found:
At startup time, we use ASM to generate a wrapper bean in memory that
would 
basically be:
@XmlRootElement(....)
@XmlType(....)
public class  GetFoos {
   @XmlElement(...)
    List<Foo> foo;
   ...
}
that is then put into the JAXBContext along with Foo.   Since this can
be 
determined up front that we need to do it, that works fine.


2) If ASM is NOT found, we cannot do that above.   Thus, it becomes a
runtime 
thing.   In THAT case, we manually write a wrapper element out to the 
XMLStreamWriter and then literally do the equiv of:

for(Foo f : foos) {
   marshaller.marshal(f, writer);
}

and then close off the wrapper element.    I think you should be able to
do 
something similar to the latter within the JAXB provider.


Dan




On Tue July 14 2009 8:18:14 am Sergey Beryozkin wrote:
> Hi Dan
>
> I've started doing some work in this area and at the moment some
manual 
> top-level element start/end serialization is being done. I'd like to
> experiment a bit with using a generated Collection wrapper, for the
> deserailzation to work too, but I'm kind of stuck a bit as JAXB
complains,
> while serializing this generated Collection instance that no context
is
> available for say Foo.class, for ex :
>
> List<Object> foos = new ArrayList<Object>();
> foos.add(new Foo());
> Collection c = new Collection();
> c.getAny().addAll(foos);
> // marshal this collection instance
>
> perhaps the solution is to create a shared JAXBContext for both Foo &
> Collection, but is it the right approach ? My concern is that given
that in
> JAX-RS we don't know in advance all the types we may have to deal with
due
> to the dynamic subresource resolution, we may end up with contexts for
Foo
> & Collection, Bar & Collection, etc - though may be it's unlikely to
happen
> in practice... Dan K, Benson - is there any trick I may need to be
aware to
> make it work in the most efficient way ? thanks, Sergey
>
> > Hi,
> >
> > I'm writing a JAX-RS app and using CXF as the implementation.  I was
> > having trouble wiring up some of my methods -- specifically, one
that was
> > to return a list of people:
> >
> > @GET
> > @Path("/list")
> > List<Person> getPersons();
> >
> > Trying to run that, I got NPEs, as List can't be written out as a
root
> > element by default.
> >
> > A lot of the advice that I saw involved adding extra collections,
and
> > changing the method signature to return the JAXBtized collection
wrapper.
> > Since this isn't strictly a REST call, this either means that
everybody
> > using the service call will have to unwrap the collection, or that I
will
> > have to code two methods every time I want to return a collection.
> >
> > Instead, I'd like to actually fix this in the providers at the core
of
> > CXF. I created a collection object of my own:
> >
> >    <complexType name="Collection">
> >        <sequence>
> >            <any minOccurs="0" maxOccurs="unbounded"></any>
> >        </sequence>
> >    </complexType>
> >
> > ... And then overrode the JAXBElementProvider.writeTo method:
> >
> > package us.XXXXXXXXX.iotool.jaxrs;
> >
> > import java.io.IOException;
> > import java.io.OutputStream;
> > import java.lang.annotation.Annotation;
> > import java.lang.reflect.Type;
> >
> > import javax.ws.rs.WebApplicationException;
> > import javax.ws.rs.core.MediaType;
> > import javax.ws.rs.core.MultivaluedMap;
> >
> > import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
> >
> > import us.XXXXXXXXX.iotool.model.Collection;
> >
> > public class CollectionJAXBElementProvider extends
JAXBElementProvider {
> >
> > @Override
> > public void writeTo(Object obj, Class<?> cls, Type genericType,
> >     Annotation[] anns, MediaType m,
> >      MultivaluedMap<String, Object> headers, OutputStream os)
> >        throws IOException {
> > try {
> >  Object actualObject = checkAdapter(obj, anns, true);
> >  // if it's a java.util.Collection, wrap it in our collection object
> >  if (actualObject instanceof java.util.Collection) {
> >    us.XXXXXXXXX.iotool.model.Collection collection = new
Collection();
> >    java.util.List list  =
> >      new
java.util.ArrayList<Object>((java.util.Collection)actualObject);
> >    collection.setAnies(list);
> >    actualObject = collection;
> >  }
> >
> >  // now pass to the superclass
> >  super.writeTo(actualObject, cls, genericType, anns, m, headers,
os);
> >  }  catch (WebApplicationException e) {
> >   throw e;
> >  } catch (Exception e) {
> >   throw new WebApplicationException(e);
> >  }
> > }
> >
> > }
> >
> >
> > This works fine -- any java.util.Collection will get wrapped in a
> > <Collection> tag.
> >
> > There are a couple of downsides here:
> >
> > (1) Doing it in this provider means that it doesn't apply to my JSON
> > provider.
> > (2) I don't think that I have a great way to consume this on the
client
> > side as anything other than a wrapped collection (if that even
works).
> >
> > Two sets of questions:
> > (1) Can I get to my desired end -- transparently handling
> > java.util.Collection objects -- without all this mucking about?  Can
I do
> > this with a XmlJavaTypeAdapter?
> >
> > (2) Is there a different spot in the chain where I can put this that
> > would change the objects prior to their being consumed by any
providers? 
> > The documentation on the JAX-RS filters wasn't totally clear to me
on
> > this point.
> >
> > Thanks in advance,
> > Dan
> >
> >
> > -----
> > CONFIDENTIALITY NOTICE: The information contained in this message
> > may be privileged and confidential and protected from disclosure.
> > If the reader of this message is not the intended recipient, or
> > responsible for delivering it to the intended recipient, please
> > be advised that any distribution, dissemination, copying or other
> > transmission or use of the information contained in this message
> > or its enclosed attachments is strictly prohibited.  Please
> > notify us immediately if you have received this message in error
> > by replying to the sender of the message and deleting it from
> > your computer.  Thank you.

-- 
Daniel Kulp
[email protected]
http://www.dankulp.com/blog

Reply via email to