You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Voß, Marko <Ma...@fiz-Karlsruhe.de> on 2012/03/26 17:04:41 UTC

Manipulating response header without returning javax.ws.rs.core.Response

Hello,

we have an issue, where we cannot return the javax.ws.rs.core.Response 
type in our method signatures of our JAX-RS interfaces. Example:

@Path("/foo")
public interface Foo {

   @Path("/{id}")
   ...
   JaxbFooObj retrieveFoo(@PathParam("id") String id) {
     return logic.retrieve(id);
   }
}

JaxbFooObj is a class generated by the JAXB maven-plugin, generated from 
a schema file. The data of JaxbFooObj may be stored into a database. The 
timestamp when this data has been stored or changed should become the 
'Last-Modified' HTTP header value according to RFC 2822 or RFC 5322.
Returning javax.ws.rs.core.Response is no option because we need the 
WADL-generator to use the return type to add the element type to the 
representation element. Example:

<representation mediaType="text/xml" element="prefix1:foo"/>

I tried to solve this by writing a CXF interceptor:

public class CustomOutInterceptor extends 
AbstractOutDatabindingInterceptor {

     public CustomOutInterceptor() {
         super(Phase.POST_LOGICAL);
     }

     public void handleMessage(Message message) {
         Map<String, List<String>> headers = (Map<String, 
List<String>>)message.get(Message.PROTOCOL_HEADERS);
         if (headers == null) {
             headers = new TreeMap<String, 
List<String>>(String.CASE_INSENSITIVE_ORDER);
             message.put(Message.PROTOCOL_HEADERS, headers);
         }
         List contents = message.getContent(List.class);
         if (contents != null) {
             for (int i=0; i<contents.size(); i++) {
                 if (contents.get(i) instanceof MetaObject) {
                     MetaObject meta = (MetaObject)contents.get(i);
                     contents.set(i, meta.getObj());

                     List<String> foo = new ArrayList<String>();
                     foo.add(meta.getLMD().toString());
                     headers.put("Last-Modified", foo);
                     return;
                 }
             }
         }
     }
}

The MetaObject contains the JaxbFooObj and the last modification date. 
This works but again, the element type is missing the in the generated 
WADL. So the result is the same as by simply returning 
javax.ws.rs.core.Response.


Can anyone help on this issue please?


Thank you in advance and kind regards,

Marko


-------------------------------------------------------

Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH. 
Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892. 
Geschäftsführerin: Sabine Brünger-Weilandt. 
Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.



Re: Manipulating response header without returning javax.ws.rs.core.Response

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Marko

On 26/03/12 17:21, Voß, Marko wrote:
> Hello Sergey,
>
> Thank you for pointing out the ElementClass annotation. This should do the job.
>
> I solved this issue right after my post to the mailing list by using "@Context HttpServletResponse response" in the method signature but I think, this is an "ugly" approach, because of the same JAX-RS interfaces are reused on client-side and the HttpServletResponse should not be available there. Your solution however looks great!
>
>> Is JaxbFooObj instance of MetaObject and with the method returning JaxbFooObj ? If yes then having the above interceptor should not affect the WADL generation.
>
> JaxbFooObj was the generic type of MetaObject and the method was returning MetaObject<JaxbFooObj>. I guess the WADL generator will only look at the interface/class annotations. I forgot to mention this.

WADLGenerator may be ignoring the generic type, though I think it should 
add those provided in List<JaxbFooObject>, I'll have a look

>
>> By the way, do you expect the timestamp property returned to the client?
>
> I expect the timestamp to appear in the HTTP response header for the client. I tested it using Firefox Live-HTTP headers and it works.
>
>
> Since we have to use the javax.ws.rs.core.Response return type, the clients, which are reusing these JAX-RS interfaces, will now get the javax.ws.rs.core.Response type instead of the real type. I kinda dislike this but I guess, there is no other way. It would be nice, if the javax.ws.rs.core.Response type would be generic.
>
It will be easier to work with Response in JAX-RS 2.0, I'm not sure 
Response will be made generic though as there's still some 'tension' on 
the api level as to whether get it shared between client & server 
runtimes or not. CXF ResponseReader provider can be registered on the 
client side and used to cast from response.getEntity() to the specific 
type. I'll have to resolve your JIRA though as won't fix :-) as it's not 
a CXF level issue

Cheers, Sergey
>
> Kind regards,
>
> Marko
>
> -----Original Message-----
> From: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
> Sent: Monday, March 26, 2012 5:59 PM
> To: users@cxf.apache.org
> Subject: Re: Manipulating response header without returning javax.ws.rs.core.Response
>
> Hi Marko
> On 26/03/12 16:04, Voß, Marko wrote:
>> Hello,
>>
>> we have an issue, where we cannot return the javax.ws.rs.core.Response
>> type in our method signatures of our JAX-RS interfaces. Example:
>>
>> @Path("/foo")
>> public interface Foo {
>>
>>      @Path("/{id}")
>>      ...
>>      JaxbFooObj retrieveFoo(@PathParam("id") String id) {
>>        return logic.retrieve(id);
>>      }
>> }
>>
>> JaxbFooObj is a class generated by the JAXB maven-plugin, generated
>> from a schema file. The data of JaxbFooObj may be stored into a
>> database. The timestamp when this data has been stored or changed
>> should become the 'Last-Modified' HTTP header value according to RFC 2822 or RFC 5322.
>> Returning javax.ws.rs.core.Response is no option because we need the
>> WADL-generator to use the return type to add the element type to the
>> representation element. Example:
>>
>> <representation mediaType="text/xml" element="prefix1:foo"/>
>>
> Adding a method-level ElementClass annotation
> (http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementClass.java)
> to the method returning Response should do it...
>
>
>> I tried to solve this by writing a CXF interceptor:
>>
>> public class CustomOutInterceptor extends
>> AbstractOutDatabindingInterceptor {
>>
>>        public CustomOutInterceptor() {
>>            super(Phase.POST_LOGICAL);
>>        }
>>
>>        public void handleMessage(Message message) {
>>            Map<String, List<String>>   headers = (Map<String,
>> List<String>>)message.get(Message.PROTOCOL_HEADERS);
>>            if (headers == null) {
>>                headers = new TreeMap<String,
>> List<String>>(String.CASE_INSENSITIVE_ORDER);
>>                message.put(Message.PROTOCOL_HEADERS, headers);
>>            }
>>            List contents = message.getContent(List.class);
>>            if (contents != null) {
>>                for (int i=0; i<contents.size(); i++) {
>>                    if (contents.get(i) instanceof MetaObject) {
>>                        MetaObject meta = (MetaObject)contents.get(i);
>>                        contents.set(i, meta.getObj());
>>
>>                        List<String>   foo = new ArrayList<String>();
>>                        foo.add(meta.getLMD().toString());
>>                        headers.put("Last-Modified", foo);
>>                        return;
>>                    }
>>                }
>>            }
>>        }
>> }
>>
>> The MetaObject contains the JaxbFooObj and the last modification date.
>> This works but again, the element type is missing the in the generated
>> WADL. So the result is the same as by simply returning
>> javax.ws.rs.core.Response.
>>
>
> Is JaxbFooObj instance of MetaObject and with the method returning JaxbFooObj ? If yes then having the above interceptor should not affect the WADL generation.
> You should also be able to se ResponseHandler filter and override the Response there by copying the original Response and adding the required header. By the way, do you expect the timestamp property returned to the client ? If no then it can be stripped off with the transform feature
>
> Cheers, Sergey
>
>>
>> Can anyone help on this issue please?
>>
>>
>> Thank you in advance and kind regards,
>>
>> Marko
>>
>>
>> -------------------------------------------------------
>>
>> Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH.
>> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892.
>> Geschäftsführerin: Sabine Brünger-Weilandt.
>> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.
>>
>>
>
>
> --
> Sergey Beryozkin
>
> Talend Community Coders
> http://coders.talend.com/
>
> Blog: http://sberyozkin.blogspot.com
>
>
> -------------------------------------------------------
>
> Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH.
> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892.
> Geschäftsführerin: Sabine Brünger-Weilandt.
> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.
>
>

RE: Manipulating response header without returning javax.ws.rs.core.Response

Posted by Voß, Marko <Ma...@fiz-Karlsruhe.de>.
Hello Sergey,

Thank you for pointing out the ElementClass annotation. This should do the job.

I solved this issue right after my post to the mailing list by using "@Context HttpServletResponse response" in the method signature but I think, this is an "ugly" approach, because of the same JAX-RS interfaces are reused on client-side and the HttpServletResponse should not be available there. Your solution however looks great!

> Is JaxbFooObj instance of MetaObject and with the method returning JaxbFooObj ? If yes then having the above interceptor should not affect the WADL generation.

JaxbFooObj was the generic type of MetaObject and the method was returning MetaObject<JaxbFooObj>. I guess the WADL generator will only look at the interface/class annotations. I forgot to mention this.

> By the way, do you expect the timestamp property returned to the client?

I expect the timestamp to appear in the HTTP response header for the client. I tested it using Firefox Live-HTTP headers and it works.


Since we have to use the javax.ws.rs.core.Response return type, the clients, which are reusing these JAX-RS interfaces, will now get the javax.ws.rs.core.Response type instead of the real type. I kinda dislike this but I guess, there is no other way. It would be nice, if the javax.ws.rs.core.Response type would be generic.


Kind regards,

Marko

-----Original Message-----
From: Sergey Beryozkin [mailto:sberyozkin@gmail.com] 
Sent: Monday, March 26, 2012 5:59 PM
To: users@cxf.apache.org
Subject: Re: Manipulating response header without returning javax.ws.rs.core.Response

Hi Marko
On 26/03/12 16:04, Voß, Marko wrote:
> Hello,
>
> we have an issue, where we cannot return the javax.ws.rs.core.Response 
> type in our method signatures of our JAX-RS interfaces. Example:
>
> @Path("/foo")
> public interface Foo {
>
>     @Path("/{id}")
>     ...
>     JaxbFooObj retrieveFoo(@PathParam("id") String id) {
>       return logic.retrieve(id);
>     }
> }
>
> JaxbFooObj is a class generated by the JAXB maven-plugin, generated 
> from a schema file. The data of JaxbFooObj may be stored into a 
> database. The timestamp when this data has been stored or changed 
> should become the 'Last-Modified' HTTP header value according to RFC 2822 or RFC 5322.
> Returning javax.ws.rs.core.Response is no option because we need the 
> WADL-generator to use the return type to add the element type to the 
> representation element. Example:
>
> <representation mediaType="text/xml" element="prefix1:foo"/>
>
Adding a method-level ElementClass annotation
(http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementClass.java)
to the method returning Response should do it...


> I tried to solve this by writing a CXF interceptor:
>
> public class CustomOutInterceptor extends 
> AbstractOutDatabindingInterceptor {
>
>       public CustomOutInterceptor() {
>           super(Phase.POST_LOGICAL);
>       }
>
>       public void handleMessage(Message message) {
>           Map<String, List<String>>  headers = (Map<String, 
> List<String>>)message.get(Message.PROTOCOL_HEADERS);
>           if (headers == null) {
>               headers = new TreeMap<String, 
> List<String>>(String.CASE_INSENSITIVE_ORDER);
>               message.put(Message.PROTOCOL_HEADERS, headers);
>           }
>           List contents = message.getContent(List.class);
>           if (contents != null) {
>               for (int i=0; i<contents.size(); i++) {
>                   if (contents.get(i) instanceof MetaObject) {
>                       MetaObject meta = (MetaObject)contents.get(i);
>                       contents.set(i, meta.getObj());
>
>                       List<String>  foo = new ArrayList<String>();
>                       foo.add(meta.getLMD().toString());
>                       headers.put("Last-Modified", foo);
>                       return;
>                   }
>               }
>           }
>       }
> }
>
> The MetaObject contains the JaxbFooObj and the last modification date.
> This works but again, the element type is missing the in the generated 
> WADL. So the result is the same as by simply returning 
> javax.ws.rs.core.Response.
>

Is JaxbFooObj instance of MetaObject and with the method returning JaxbFooObj ? If yes then having the above interceptor should not affect the WADL generation.
You should also be able to se ResponseHandler filter and override the Response there by copying the original Response and adding the required header. By the way, do you expect the timestamp property returned to the client ? If no then it can be stripped off with the transform feature

Cheers, Sergey

>
> Can anyone help on this issue please?
>
>
> Thank you in advance and kind regards,
>
> Marko
>
>
> -------------------------------------------------------
>
> Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH.
> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892.
> Geschäftsführerin: Sabine Brünger-Weilandt.
> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.
>
>


--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com


-------------------------------------------------------

Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH. 
Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892. 
Geschäftsführerin: Sabine Brünger-Weilandt. 
Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.



Re: Manipulating response header without returning javax.ws.rs.core.Response

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Marko
On 26/03/12 16:04, Voß, Marko wrote:
> Hello,
>
> we have an issue, where we cannot return the javax.ws.rs.core.Response
> type in our method signatures of our JAX-RS interfaces. Example:
>
> @Path("/foo")
> public interface Foo {
>
>     @Path("/{id}")
>     ...
>     JaxbFooObj retrieveFoo(@PathParam("id") String id) {
>       return logic.retrieve(id);
>     }
> }
>
> JaxbFooObj is a class generated by the JAXB maven-plugin, generated from
> a schema file. The data of JaxbFooObj may be stored into a database. The
> timestamp when this data has been stored or changed should become the
> 'Last-Modified' HTTP header value according to RFC 2822 or RFC 5322.
> Returning javax.ws.rs.core.Response is no option because we need the
> WADL-generator to use the return type to add the element type to the
> representation element. Example:
>
> <representation mediaType="text/xml" element="prefix1:foo"/>
>
Adding a method-level ElementClass annotation 
(http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementClass.java) 
to the method returning Response should do it...


> I tried to solve this by writing a CXF interceptor:
>
> public class CustomOutInterceptor extends
> AbstractOutDatabindingInterceptor {
>
>       public CustomOutInterceptor() {
>           super(Phase.POST_LOGICAL);
>       }
>
>       public void handleMessage(Message message) {
>           Map<String, List<String>>  headers = (Map<String,
> List<String>>)message.get(Message.PROTOCOL_HEADERS);
>           if (headers == null) {
>               headers = new TreeMap<String,
> List<String>>(String.CASE_INSENSITIVE_ORDER);
>               message.put(Message.PROTOCOL_HEADERS, headers);
>           }
>           List contents = message.getContent(List.class);
>           if (contents != null) {
>               for (int i=0; i<contents.size(); i++) {
>                   if (contents.get(i) instanceof MetaObject) {
>                       MetaObject meta = (MetaObject)contents.get(i);
>                       contents.set(i, meta.getObj());
>
>                       List<String>  foo = new ArrayList<String>();
>                       foo.add(meta.getLMD().toString());
>                       headers.put("Last-Modified", foo);
>                       return;
>                   }
>               }
>           }
>       }
> }
>
> The MetaObject contains the JaxbFooObj and the last modification date.
> This works but again, the element type is missing the in the generated
> WADL. So the result is the same as by simply returning
> javax.ws.rs.core.Response.
>

Is JaxbFooObj instance of MetaObject and with the method returning 
JaxbFooObj ? If yes then having the above interceptor should not affect 
the WADL generation.
You should also be able to se ResponseHandler filter and override the 
Response there by copying the original Response and adding the required 
header. By the way, do you expect the timestamp property returned to the 
client ? If no then it can be stripped off with the transform feature

Cheers, Sergey

>
> Can anyone help on this issue please?
>
>
> Thank you in advance and kind regards,
>
> Marko
>
>
> -------------------------------------------------------
>
> Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH.
> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892.
> Geschäftsführerin: Sabine Brünger-Weilandt.
> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.
>
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com