Hi The initial support for reading/writing collections is on the trunk now. Writing/reading collections/arrays is supported for plain JAXB, only writing is currently supported for JSON. I'll be looking at fixing a JSON reading issue and optimizing it all.
By default, pluralized XMLRootElement name attribute will be used as a wrapper, namespace-prefixed if needed, if no name attribute is there then a lower-case pluralized class name will be used. This can be customized by using setCollectionWrapperName on JAXB/JSON providers thanks, Sergey Sergey Beryozkin-2 wrote: > > 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 foos = new ArrayList(); >> 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((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 > > -- View this message in context: http://www.nabble.com/Handling-Collection%3CJAXBElement%3E-returns-via-JAX-RS-tp24262522p24517386.html Sent from the cxf-user mailing list archive at Nabble.com.
