users@jersey.java.net

[Jersey] Re: Implementing a Query by Example

From: Ivar <ivarconr_at_gmail.com>
Date: Tue, 22 Oct 2013 15:36:06 +0200

Hi,

What you could do is have a a registered implementation of
javax.ws.rs.ext.ParamConverterProvider JAX-RS extension SPI that returns a
javax.ws.rs.ext.ParamConverter instance capable of a "from string"
conversion for the Book type.

Ivar Østhus



Med vennlig hilsen,

Ivar Conradi Østhus
920 43 382
ivarconr_at_gmail.com


On 22 October 2013 15:28, Antonio Goncalves <antonio.mailing_at_gmail.com>wrote:

> Hi all,
>
> I'm using a very manual approach to solve this problem and I would like to
> share it with you in case you have a better idea. Basically my resource
> doesn't do much, it just uses a @QueryParam to get the XML and JPA to do a
> QBE :
>
> @GET
> @Path("*/query*")
> @Produces("application/xml")
> public Response findByQBE(*_at_QueryParam("example")* *Book* example) {
>
> CriteriaBuilder builder = em.getCriteriaBuilder();
> CriteriaQuery<Book> criteria = builder.createQuery(Book.class);
> // ...
> // query by example
> return Response.ok(books).build();
> }
>
>
> The manual work that I do is in the Book entity. Basically I give it a
> constructor with a String (needed by JAX-RS) to be able to unmarshall the
> XML into the bean itself, and I create a toXML() method that marshalls the
> bean into XML :
>
> @Entity
> *_at_XmlRootElement*
> public class Book implements Serializable {
>
> @Id @GeneratedValue
> private String isbn;
> private String title;
> private String description;
> // ... other attributes
>
> public Book() {
> }
>
> public *Book(String xml)* throws JAXBException {
> // Uses JAXB to unmarshall the XML string into the bean itself
> JAXBContext ctx = JAXBContext.newInstance(Book.class);
> Unmarshaller m = ctx.createUnmarshaller();
> Book book = (Book) m.*unmarshal*(new StringReader(xml));
> this.isbn = book.getIsbn();
> this.title = book.getTitle();
> this.description = book.getDescription();
> this.nbOfPages = book.getNbOfPages();
> this.publisher = book.getPublisher();
> }
>
> public String *toXML()* throws JAXBException {
> // Uses JAXB to marshall the bean into an XML string
> StringWriter writer = new StringWriter();
> JAXBContext ctx = JAXBContext.newInstance(Book.class);
> Marshaller m = ctx.createMarshaller();
> m.*marshal*(this, writer);
> return writer.toString();
> }
>
> // ... getters & setters
> }
>
> Then, to invoke my resource with the Client API, I just call the toXML()
> method as follow :
>
> Book example = new Book();
> example.setTitle("Java");
> Response response = client.target(URL + "/books").path("/query")
> .queryParam("example", *example.toXML()*)
> .request(MediaType.APPLICATION_XML)
> .get();
>
> This way I invoke the resource with a request that looks like what I want
> :
>
> /rest/books/*query/example=<book><title>Java</title></book>*
>
>
> So it does work except there is many manual code that, in my mind, could
> be automatised. Am I wrong ? Do you have a better idea ? In this case I
> suppose a provider would make sense but I already use JAXB and XML so it
> feels weird to do the job a second time.
>
> Thanks for you thoughts
>
> Antonio
>
>
> 2013/10/22 Antonio Goncalves <antonio.mailing_at_gmail.com>
>
>> Hi all,
>>
>> I need to implement a query by example service and be able to consume it
>> with the new client API.
>>
>> The idea is that I have a Book entity with a JAXB annotation :
>>
>> @Entity
>> @XmlRootElement
>> public class Book implements Serializable {
>>
>> @Id @GeneratedValue
>> private Long id = null;
>>
>> private String isbn;
>> private String title;
>> private String description;
>> }
>>
>>
>> I now need a service that would be able to receive an 'example' of the
>> Book in XML format. So if the service receives :
>>
>> <book><isbn>1234</isbn></book>
>>
>> It will return all the books with an ISBN like '1234. If the service
>> receives :
>>
>> <book><isbn>1234</isbn><title>Java</title><description>Best
>> book</description></book>
>>
>> Il will return all the books with an ISBN like '1234' AND a title like
>> 'Java' AND a description like 'Best Book'. As you can see, the query string
>> depends on which attributes of the entity are set. So I was thinking of
>> having a URI that would look like :
>>
>> /rest/books/*query*=<book><isbn>1234</isbn></book>
>> /rest/books/*query*=<book><isbn>1234</isbn><title>Java</title><description>Best
>> book</description></book>
>>
>> So I assume that the resource would then look like :
>>
>> @GET
>> public Response findByQBE(@QueryParam("*query*") Book example) {
>> ...
>> }
>>
>> And the client API
>>
>> Book *example* = new Book();
>> example.setTitle("Java");
>> client.target(URL + "/books").path("/qbe").queryParam("*query*", *example
>> *).request(MediaType.APPLICATION_XML).get();
>>
>> But that doesn't work (I get a 404).
>>
>> I feel I don't need to write a provider to marshall the POJO into an XML
>> String. So I think I'm doing something wrong here.
>>
>> Any idea
>>
>> Thanks
>>
>> --
>> Antonio Goncalves
>> Software architect and Java Champion
>>
>> Web site <http://www.antoniogoncalves.org/> | Twitter<http://twitter.com/agoncal>
>> | LinkedIn <http://www.linkedin.com/in/agoncal> | Paris JUG<http://www.parisjug.org/>
>> | Devoxx France <http://www.devoxx.fr/>
>>
>
>
>
> --
> Antonio Goncalves
> Software architect and Java Champion
>
> Web site <http://www.antoniogoncalves.org/> | Twitter<http://twitter.com/agoncal>
> | LinkedIn <http://www.linkedin.com/in/agoncal> | Paris JUG<http://www.parisjug.org/>
> | Devoxx France <http://www.devoxx.fr/>
>