users@jersey.java.net

Re: Collection serialization in RESTful service

From: Florian Rosenberg <florian_at_vitalab.tuwien.ac.at>
Date: Tue, 23 Oct 2007 08:51:04 -0400 (EDT)

Hi Paul,


On Tue, October 23, 2007 05:31, Paul Sandoz wrote:
> Hi Florian, James,
>
> This is a tricky problem [*].

indeed, I stumbled upon this problem with the type erasure a couple of
times, it is very annoying. anyway, we have to deal with that now ;)

> Some possible solutions:
>
> 1) We could provide a Collection type entity provider that checks if all
> of the objects are JAXB element objects, if so a root element is
> written out and then each JAXB element is marshalled.
>
> 2) A generic collection type class with an entity provider:
>
> class CollectionType<T> {
> Collection<T> c;
>
> CollectionType(Collection<T> c) { ... }
> }
>
> The entity provider can then create a JAXBElement instance:
>
> QName q = // work out root element name from c
> new JAXBElement(q, CollectionType.class, c)

I would go with (1) just for simplicity and it allows the user to stick to
his preferred API without used the typed collection. when going for (1)
you need to find a name for the root element, eg., customers if the
objects in the collection are of type Customer.

> 2) is really a specialization of 1) that is more efficient (and we
> anyway will have to implement something like this for 1), but we have to
> do do this:
>
> public TypeCollection<Customer> findAllCustomers() {
> Collection<Customer> c = ...
> return new TypeCollection(c);
> }
>
> instead of:
>
> public Collection<Customer> findAllCustomers() {
> Collection<Customer> c = ...
> return c;
> }
>
> Utilizing 2) we could also support the returning of a JAXB element so
> the root element could be specified by the application:
>
> class ElementCollection<T> extends JAXBElement<TypeCollection<T>> {
> ElementCollection(Collection<T> c) { ... }
>
> ElementCollection(QName root, Collection<T> c) { ... }
> }
>
> public JAXBElement<CollectionType<Customer>> findAllCustomers() {
> Collection<Customer> c = ...
>
> return new ElementCollection(new QName("root"), c);
> }
>

-Florian

> Florian Rosenberg wrote:
>> Hi James,
>>
>> On Mon, October 22, 2007 11:09, James Weir wrote:
>>> Hi Florian,
>>>
>>> The way I solved this problem is to create another class called
>>> Customers
>>>
>>> for example:
>>>
>>> @XmlRootElement(name="Customers")
>>> public class Customers{
>>> private List<Customer> collection;
>>> }
>>>
>>> and so...
>>>
>>> @HttpMethod("GET")
>>> @ProduceMime("text/xml")
>>> @UriTemplate("customers")
>>> public Customers findAllCustomers() { }
>>
>>
>> that's my current solution too, but I guess there should a "nicer" way
>> to
>> tell JAXB to serialize the collection of JAXB annotated classes, without
>> writing an "extra" class for that.
>>
>> If anybody has an idea let me know. I tried to search in the JAXB docs,
>> probably we need to add another JAXB provider for doing that. I'm not a
>> JAXB expert, so maybe somebody can clarify on this issues.
>>
>> Thanks,
>> -Florian
>>
>>> Florian Rosenberg wrote:
>>>> hi folks,
>>>>
>>>> just found out about Jersey and I tried to hack my first example, it
>>>> works
>>>> great except some detail which I do not get to work.
>>>>
>>>> I want to create a RESTful service that implements a simple customer
>>>> management where with the following operations in my CustomerResource
>>>> class (I left out the impl for readability):
>>>>
>>>> @UriTemplate("/")
>>>> public class CustomerService {
>>>>
>>>> @UriTemplate("customers/{id}")
>>>> @HttpMethod("POST")
>>>> public void addCustomer(@UriParam("id") String id, Customer data) {
>>>> }
>>>>
>>>> @UriTemplate("customers/{id}")
>>>> @HttpMethod("DELETE")
>>>> public Customer deleteCustomer(@UriParam("id") String id) { }
>>>>
>>>> @UriTemplate("customers/{id}")
>>>> @HttpMethod("GET")
>>>> @ProduceMime("text/xml")
>>>> public Customer findCustomer(@UriParam("id") String id) { }
>>>>
>>>> @HttpMethod("GET")
>>>> @ProduceMime("text/xml")
>>>> @UriTemplate("customers")
>>>> public Collection<Customer> findAllCustomers() { }
>>>>
>>>> @UriTemplate("customers/{id}")
>>>> @HttpMethod("PUT")
>>>> public void updateCustomer(@UriParam("id") String id, Customer data)
>>>> {
>>>> }
>>>>
>>>> }
>>>>
>>>> The Customer class is annotated with JAXB annotations. The above works
>>>> great except the "findAllCustomers" as HTTP GET method. The problem is
>>>> that Jersey does not know how to serialize a collection of customer
>>>> objects. Is there a way to tell Jersey to do that. I tried for hours,
>>>> the
>>>> only workaround is the create your own Collection class that has the
>>>> XmlRootElement annotation. But this cannot be the way to go, I guess.
>>>>
>>>> The result of the "findAllCustomer" should be something like:
>>>>
>>>> <customers>
>>>> <customer id="1">
>>>> <!-- ... -->
>>>> </customer>
>>>> <customer id="2">
>>>> <!-- ... -->
>>>> </customer>
>>>> </customers>
>>>>
>>>> Any help is appreciated.
>>>>
>>>> Thanks,
>>>> -Florian
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>
>>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
> --
> | ? + ? = To question
> ----------------\
> Paul Sandoz
> x38109
> +33-4-76188109
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>