users@jersey.java.net

[Jersey] Re: dinamyc content type

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Thu, 18 Aug 2011 12:11:42 +0200

On 08/18/2011 11:27 AM, Jose Antonio Illescas Del Olmo wrote:
> Rob, I don't see why this solution is specific to one problem. Please, Can you explain me why?
>
> For example, I have a REST service that get some resource not deleteable without any cache
>
> @Path("/some/resources")
> public class Resource
>
>
> JAS-RS code______________________
>
>
> @GET
> @Path("{id}")
> public Response get(@RequestParam() Long id) {
> Resource resource = getFromDatabase(id);
> CacheControl cache = new CacheControl();
> cache.setNocache(true);
> return Response.ok(resource).header("Allow", new String[]{"GET","POST","PUT"}).cacheControl(cache).build()
> }
>
> Annotated alternative___________________
>
> @GET
> @Path("{id}")
> @Output(cacheControl="no-cache", allow="GET,POST,PUT")
> public Response get(@RequestParam() Long id) { // This method return object from my model, It's simple to test with
> JUnit (I don't needed any JAS-RS framework to test)
> return getFromDatabase(id);
> }
>

Apart from the problem with tight coupling of several unrelated problem domains into a single annotation, I wonder what
is the advantage of your proposal? A very slight reduction in the amount of code is offset by the lost type-safety and
compile time checking (you can't fail on invalid Output.cacheControl value at compile-time). Would it make sense to
override these annotation values using some external deployment descriptor? I don't think so, those are not really
configuration values.

You may want to look more closely at Jersey concept of resource-specific filters:
http://jersey.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/spi/container/ResourceFilterFactory.html

Those let you generically solve the problem of making common request/response changes (such as attaching common response
headers) and the resource code can then look even simpler than the annotated alternative above:

    @GET
    @Path("{id}")
    public Response get(@RequestParam() Long id) {
       return getFromDatabase(id);
    }

The standard filters and handlers are comming in JAX-RS 2.0 - some preview is here:
http://java.net/projects/jax-rs-spec/pages/InterceptorsAndFilters



>
> Another example: Same Resource have one service that accept object to be created on database, but this insertion is not
> inmediate it's based on queued System or Batch processing (their response included a pointer, link, to status monitor
> and a estimated time to process at 13:30)
>
> JAS-RS code______________________
>
>
> @POST
> public Response queued(Resource resource) {
> queue(resource);
> return Response.status(202).entity(resource).header("Link", "</some/resources>").expires(todayAt(13,30,0)).build();
> }
>
> Annotated alternative___________________
>
> @POST
> @Output(status=202, link="/some/resources", expires="13:30:00")
> public Resource queued(Resource resource) { // again this method is easy to test
> return queue(resource);
> }

What use case does the code describe? What if I send a request to the method at 13:30:01? Do I receive an expired response?

>
>
>
> You really think that programatic is better alternative?

In this case, yes!

Marek


 Of course annotated alternative is restricted to static
> headers (dynamic header requires java code).
>
> I see this as a simple alternative that only require one annotation
>
>
> I really interested on your point-of-view, and why you see as specific solution
>
> Regards
>
> On 18/08/2011 03:34, Rob - wrote:
>> It seems quite specific to your problem... in my opinion, it does not add value to a framework that's supposed to be
>> generic enough for building REST infrastructure...
>>
>> IMHO
>>
>> ------------------------------------------------------------------------------------------------------------------------
>> Date: Wed, 17 Aug 2011 10:34:33 +0200
>> From: jantonio.illescas_at_rbcdexia-is.es
>> To: users_at_jersey.java.net
>> CC: skyscrapper666_at_hotmail.com
>> Subject: [Jersey] Re: dinamyc content type
>>
>> Yes, must be processed as any HTTP request.
>>
>> Exist Content-type-negotiation (CTN) based on "Accept" request header and "contentTypes" configured on service
>> (with @Produces or @Output).
>>
>> I really see 2 posibilities based on JAX-RS API:
>>
>> 1.- Servlet filter that captures any request and sets the response headers (and status) from selected @Option.
>>
>> · Guice based interceptor captures any method annotated with @Option and store options on ThreadLocal
>> · Servlet filter select the apropiated @Option based on HTTPServletResponse.status => use
>> HTTPServletResponseWrapper to retrieve the status code.
>>
>> 2.- Guice interceptor captures any method annotated with @Option and generate custom "javax.ws.rs.core.Reponse"
>> based on selected @Option
>>
>> note: this solution require program content-type-negotiation algorithm (not use Jersey CTN) to select the
>> apropiated content type.
>>
>> Please, note that:
>>
>> · first alternative use content-type-negotiation provided by JAX-RS implementation (Jersey) based on "Accept"
>> request header and @Provides annotation
>> · second one require custom content-type-negotiation (JAX-RS hide to developer) based on "Accept" request header and
>> @Provides/_at_Option annotation (use @Option when present and @Provides in other case)
>>
>>
>>
>> On 17/08/2011 04:25, Rob - wrote:
>>
>> Shouldn't that be driven by the HTTP Accept header and processed as any http request?
>>
>> ------------------------------------------------------------------------------------------------------------------------
>>
>> On 16/08/2011 18:31, Jose Antonio Illescas Del Olmo wrote:
>>
>> Paul, apologize for any inconvenience on my expressions (English is not my native language).
>>
>> Sorry...
>>
>>
>> Let me explain my idea: now, my rest framework works:
>>
>> 1. Request -> Java -> XML (with XStream) -> Transformation (XSL/STX) -> Response => Yes, internally only
>> works with XML and transform with XSL/STX to any format (at moment any object can output as: XHTML,
>> JSON, CSV or PDF)
>> 2. Any Request can controlled (MVC point of view) as:
>>
>> * Transformation: any GET request generates a Java response that "serialize" Objects to XML and
>> "transformed" with XSL/STX
>> * Redirect: any POST, PUT, DELETE request redirect to some (static or dynamic) url after process
>> o static: redirect to static configured URL
>> o dynamic: redirect to programatic generated URL
>> * Error: any error redirect to previous URL (form with submit button) with current parameters (filling any
>> input with submited values) and a new one "error" with a message error (showing the error at top)
>>
>> Well, on JAX-RS any custom Response requires programatic actions. But... Can exits any "static" (annotated
>> alternative)?
>>
>> My idea is annotate services with "static" headers (and response codes) per mediaType:
>>
>> @GET
>> @Output { contentType="text/html", link="html.xsl" } => custom provider serialize result object to XML and
>> transforms with "html.xsl" when contentType = text/html
>> public Object find(...)
>>
>>
>> @PUT
>> @Output { contentType="*", location="/some-resource-url" } => redirect to "/some-resource-url" after
>> processing to any Request
>> public Object post(...)
>>
>> @POST
>> @Output { contentType="*", status = 202 } => responds with 202 - Accepted but not processed to any Request
>> public Object acceptedButNotPrecessed(...)
>>
>> Of course, I say per media type, you can annotated multiples mediatypes:
>>
>> @GET
>> @Outputs {
>> @Output { contentType="text/html", link="html.xsl" } , => custom provider serialize result object to XML
>> and transforms with "html.xsl"
>> @Output { contentType="application/json", link="json.xsl" } , => custom provider serialize result object
>> to XML and transforms to html with "html.xsl"
>> @Output { contentType="text/csv", link="csv.xsl" } , => custom provider serialize result object to XML
>> and transforms to json with "json.xsl"
>> @Output { contentType="application/pdf", link="xsl-fo.xsl" } , => custom provider serialize result
>> object to XML and transforms to xsl-fo with "xsl-fo.xsl"
>> }
>> public Object find(...)
>>
>> @Output annotation allows "simple alternatives" without programming.
>>
>> Your opinion?
>>
>>
>>
>> On 16/08/2011 17:30, Pavel Bucek wrote:
>>
>> well, you have your "ugly" solution. Currently I don't see the way how you could obtain result of content
>> negotiation process (I think this was here some time back and result was basically the same).
>>
>> Btw, how many content types (approx) are you supporting per resource?
>>
>> On 8/16/11 5:12 PM, Jose Antonio Illescas Del Olmo wrote:
>>
>> Please any suggestion?
>>
>> I needed the "default contentType" after jersey content-type-negotiation? (I need on my REST
>> method, annotated with @POST, @PUT)
>>
>>
>> On 11/08/2011 16:04, Jose Antonio Illescas Del Olmo wrote:
>>
>> Can get the "default" contentType selected by Jersey on my method?
>>
>> Please note that Jersey (and any JAX-RS implementation) calculates the content type to invoke
>> the method with valid media type...
>>
>>
>>
>>
>>
>>
>>
>>
>