users@jersey.java.net

[Jersey] Re: Sample for URI<--->JAXB replacement on the fly

From: Markus Karg <karg_at_quipsy.de>
Date: Thu, 24 Mar 2011 08:14:41 +0100

Jakub,

 

as I posted it under LGPL you can just put it into your WIKI as long as you don't remove the copyright and my name.

 

I also would appreciate supporting this by the hyperlinking extensions, but the question is whether this is compatible with custom message body providers.

 

Regards

Markus

 

From: Jakub Podlesak [mailto:jakub.podlesak_at_oracle.com]
Sent: Donnerstag, 24. März 2011 02:14
To: users_at_jersey.java.net
Subject: [Jersey] Re: Sample for URI<--->JAXB replacement on the fly

 

Hello Markus,

Thanks for the example. I think the use case is something we should consider
to support in the server hyper-linking module.

Anyway, i need to check how to proceed further with adding this to the Wiki,
as i am not sure about the licensing.

Thanks,

~Jakub

On 03/18/2011 08:38 PM, Markus Karg wrote:

Hello Jersey Community,

 

this week I had been asked to publish a sample on "replacing URI by a JAXB element (and vice versa) on the fly". So here it is. If anybody likes to put this on the Jersey WIKI, please feel free to do so, but would be nice to keep my name and a link to my web site http://www.headcrashing.eu). The below code shall be treated as published under the terms of LGPL v2. :-)

 

Problem Scenario: You're using JAXB (typically using JAX-RS) to transport data. You don't want to contain all referenced information inside of the XML body, but instead want to have referencing URIs in the body instead. So you want to replace Java references by URIs at marshalling, and URIs by Java references at unmarshalling.

 

Solution Stereotype: Provide a custom adapter for marshalling / unmarshalling and mark the respective references to use these adapters instead of default marshalling / unmarshalling.

 

Example:

 

The following code snippets are published under the terms of the LGPL v2.

 

/*

* Copyright © 2011 Markus KARG http://www.headcrashing.eu

*/

 

/**

* Demonstrates optional usage of adapter.<br>

* {_at_code referencedBanana} is replaced by {_at_code URI} using the below adapter.

* {_at_code containedBanana} is contained as usual.

* <FruitBox referencedBanana="http://host:port/root/bananas/The%20Second%20Banana">

* <ContainedBanana id="The First Banana"/>

* </FruitBox>

*/

@XmlRootElement @XmlAccessorType(FIELD) @Entity public class FruitBox {

    Banana containedBanana;

    @XmlJavaTypeAdapter(BananaReplacer) @XmlAttribute Banana referencedBanana;

}

 

/**

* Sample entity, *optionally* replaced by {_at_code URI} and vice versa.

*/

@XmlRootElement @XmlAccessorType(FIELD) @Entity public class Banana {

    @XmlAttribute @Id int id;

}

 

/**

* Replaces references by URIs and vice versa.

*

 * @author Markus KARG (markus_at_headcrashing.eu)

*/

public class BananaReplacer extends XmlAdapter<URI, Banana> {

    /**

     * Replace {_at_code URI} by {_at_code Banana}.

     */

    @Override public BoundType unmarshal(URI uri) throws Exception {

        return uri == null ? null : JAXB.unmarshal(uri, Banana.class);

    }

 

    /**

     * Replace {_at_code Banana} by {_at_code URI}.

     */

    @Override public URI marshal(Banana banana) throws Exception {

        return banana == null ? null : UriBuilder.from(BananaResource.class).path(BananaResource.class, "get").build(banana.id);

    }

}

 

/**

* Allows {_at_code BananaAdapter} to resolve {_at_code URI} by downloading a {_at_code Banana}.

*/

@Path("bananas") public class BananaResource {

    @GET @Path("{id}") public Banana get(@PathParam("id") String id) {

        return em.find(Banana.class, id);

    }

}

 

Hope that it might be useful for anybody. Would be nice if JAX-RS would support this out-of-the-box some day (without the need to write an adapter). Note, if you want to use the adapter on the client side, you will need to know the service's absolute root URI as typically you don't have the JAX-RS to look it up from that using UriBuilder.from(...).

 

Regards

Markus