You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Vincenzo Vitale <vi...@gmail.com> on 2009/10/14 03:01:28 UTC

Setting the status code in the injected (via the jax-rs @context) HttpServletResponse

Hi,

in my service implementation I'm injecting the HttpServletResponse with the
@Context annotation:

    @POST
    @Path("/login")
    public Feed login(@PathParam("username") String username,
            @PathParam("password") String password,
            @Context HttpServletResponse httpServletResponse)

and than I set the 401 status code when the user is not authorized. The
problem is that the status code is than overwritten in the
AbstractHTTPDestination class during the headers flushing:

            Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE);
            if (i != null) {
                int status = i.intValue();
               ... ... ...
                response.setStatus(status);

is this the expected behaviour or is this a bug?



Thanks in advance,
Vincenzo.

Re: Setting the status code in the injected (via the jax-rs @context) HttpServletResponse

Posted by Sergey Beryozkin <sb...@progress.com>.
Hi



> Hi,
>
> in my service implementation I'm injecting the HttpServletResponse with the
> @Context annotation:
>
>    @POST
>    @Path("/login")
>    public Feed login(@PathParam("username") String username,
>            @PathParam("password") String password,
>            @Context HttpServletResponse httpServletResponse)
>
> and than I set the 401 status code when the user is not authorized. The
> problem is that the status code is than overwritten in the
> AbstractHTTPDestination class during the headers flushing:
>
>            Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE);
>            if (i != null) {
>                int status = i.intValue();
>               ... ... ...
>                response.setStatus(status);
>
> is this the expected behaviour or is this a bug?

It is a bug. The injected HttpServletResponse will detect if the data have been already written to the output stream, but the status 
is lost.
One option is to return a status from a custom ResponseFilter; starting from 2.2.4 you can have contexts like UriInfo injected into 
filters, so you can get the username/password values easily enough (assuming you'd like to keep them in the uri) so from the filter 
you can just do

return Response.status(403).build().

cheers, Sergey

>
>
>
> Thanks in advance,
> Vincenzo.
> 


Re: Setting the status code in the injected (via the jax-rs @context) HttpServletResponse

Posted by Vincenzo Vitale <vi...@gmail.com>.
Done:
https://issues.apache.org/jira/browse/CXF-2471


<https://issues.apache.org/jira/browse/CXF-2471>Cheers,
V.

On Wed, Oct 14, 2009 at 11:55 AM, Sergey Beryozkin <sb...@progress.com>wrote:

> Hi Vincenzo
>
>
>  Hi Sergey,
>> thanks very much for that. I was already thinking changing everything to
>> Response so it's also clearer from the service implementation what's going
>> on.
>>
>> Do you want me to fill a Jira issue or have you already created it?
>>
>
> Please create the one (to do with custom HttpServletResponse statuses being
> lost)
>
> thanks, Sergey
>
>
>
>>
>> Cheers,
>> V.
>>
>> On Wed, Oct 14, 2009 at 11:35 AM, Sergey Beryozkin <sberyozk@progress.com
>> >wrote:
>>
>>  ok... so if you move this code to a custom filter then it will work as
>>> expected (without having to throw the exception).
>>> But it's a form submission. If you decide to use a custom filter then you
>>> can have a JAXRS Providers injected and ask it to get you a provider
>>> capable
>>> of reading application/www-url-form-encoded, or simply instantiate a CXF
>>> FormProvider directly and ask it to read the possibly encoded string into
>>> a
>>> Map and proceed from there; if it is only a simple user=bar&password=foo
>>> kind of post then you might want just to read it directly from the
>>> message
>>> input stream...
>>>
>>> Actually, perhaps the simplest option is to simply return a Response
>>> directly from your method...it will have the right status and Feed set in
>>>
>>> cheers, Sergey
>>>
>>>
>>>
>>>  At the moment I solved throwing a WebApplicationException:
>>>
>>>>
>>>> feed.addCategory(ERROR_SCHEME,
>>>> String.valueOf(Status.UNAUTHORIZED.getStatusCode()), "Username or
>>>> password
>>>> not valid.");
>>>> throw new
>>>>
>>>>
>>>> WebApplicationException(Response.status(Status.UNAUTHORIZED).entity(feed).build());
>>>>
>>>> were the feed is an Abdera feed. For me it's important to always return
>>>> a
>>>> proper feed (serialized by the correct provider) independently from the
>>>> status code. Throwing the exception seems to work fine.
>>>>
>>>> Pro: at least in this service I can avoid including the servlet class in
>>>> the
>>>> interface and implementation.
>>>> Contra: it doesn't sound correct to me throwing exceptions for setting
>>>> the
>>>> status code.
>>>>
>>>>
>>>> Cheers,
>>>> V.
>>>>
>>>> P.s.: in the previous email @PathParam --> @FormParam (not yet Atom
>>>> style
>>>> for posting)
>>>>
>>>> On Wed, Oct 14, 2009 at 3:01 AM, Vincenzo Vitale
>>>> <vi...@gmail.com>wrote:
>>>>
>>>>  Hi,
>>>>
>>>>>
>>>>> in my service implementation I'm injecting the HttpServletResponse with
>>>>> the
>>>>> @Context annotation:
>>>>>
>>>>>   @POST
>>>>>   @Path("/login")
>>>>>   public Feed login(@PathParam("username") String username,
>>>>>           @PathParam("password") String password,
>>>>>           @Context HttpServletResponse httpServletResponse)
>>>>>
>>>>> and than I set the 401 status code when the user is not authorized. The
>>>>> problem is that the status code is than overwritten in the
>>>>> AbstractHTTPDestination class during the headers flushing:
>>>>>
>>>>>           Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE);
>>>>>           if (i != null) {
>>>>>               int status = i.intValue();
>>>>>              ... ... ...
>>>>>               response.setStatus(status);
>>>>>
>>>>> is this the expected behaviour or is this a bug?
>>>>>
>>>>>
>>>>>
>>>>> Thanks in advance,
>>>>> Vincenzo.
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>

Re: Setting the status code in the injected (via the jax-rs @context) HttpServletResponse

Posted by Sergey Beryozkin <sb...@progress.com>.
Hi Vincenzo


> Hi Sergey,
> thanks very much for that. I was already thinking changing everything to
> Response so it's also clearer from the service implementation what's going
> on.
> 
> Do you want me to fill a Jira issue or have you already created it?

Please create the one (to do with custom HttpServletResponse statuses being lost)

thanks, Sergey

> 
> 
> Cheers,
> V.
> 
> On Wed, Oct 14, 2009 at 11:35 AM, Sergey Beryozkin <sb...@progress.com>wrote:
> 
>> ok... so if you move this code to a custom filter then it will work as
>> expected (without having to throw the exception).
>> But it's a form submission. If you decide to use a custom filter then you
>> can have a JAXRS Providers injected and ask it to get you a provider capable
>> of reading application/www-url-form-encoded, or simply instantiate a CXF
>> FormProvider directly and ask it to read the possibly encoded string into a
>> Map and proceed from there; if it is only a simple user=bar&password=foo
>> kind of post then you might want just to read it directly from the message
>> input stream...
>>
>> Actually, perhaps the simplest option is to simply return a Response
>> directly from your method...it will have the right status and Feed set in
>>
>> cheers, Sergey
>>
>>
>>
>>  At the moment I solved throwing a WebApplicationException:
>>>
>>> feed.addCategory(ERROR_SCHEME,
>>> String.valueOf(Status.UNAUTHORIZED.getStatusCode()), "Username or password
>>> not valid.");
>>> throw new
>>>
>>> WebApplicationException(Response.status(Status.UNAUTHORIZED).entity(feed).build());
>>>
>>> were the feed is an Abdera feed. For me it's important to always return a
>>> proper feed (serialized by the correct provider) independently from the
>>> status code. Throwing the exception seems to work fine.
>>>
>>> Pro: at least in this service I can avoid including the servlet class in
>>> the
>>> interface and implementation.
>>> Contra: it doesn't sound correct to me throwing exceptions for setting the
>>> status code.
>>>
>>>
>>> Cheers,
>>> V.
>>>
>>> P.s.: in the previous email @PathParam --> @FormParam (not yet Atom style
>>> for posting)
>>>
>>> On Wed, Oct 14, 2009 at 3:01 AM, Vincenzo Vitale
>>> <vi...@gmail.com>wrote:
>>>
>>>  Hi,
>>>>
>>>> in my service implementation I'm injecting the HttpServletResponse with
>>>> the
>>>> @Context annotation:
>>>>
>>>>    @POST
>>>>    @Path("/login")
>>>>    public Feed login(@PathParam("username") String username,
>>>>            @PathParam("password") String password,
>>>>            @Context HttpServletResponse httpServletResponse)
>>>>
>>>> and than I set the 401 status code when the user is not authorized. The
>>>> problem is that the status code is than overwritten in the
>>>> AbstractHTTPDestination class during the headers flushing:
>>>>
>>>>            Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE);
>>>>            if (i != null) {
>>>>                int status = i.intValue();
>>>>               ... ... ...
>>>>                response.setStatus(status);
>>>>
>>>> is this the expected behaviour or is this a bug?
>>>>
>>>>
>>>>
>>>> Thanks in advance,
>>>> Vincenzo.
>>>>
>>>>
>>>
>>
>

Re: Setting the status code in the injected (via the jax-rs @context) HttpServletResponse

Posted by Vincenzo Vitale <vi...@gmail.com>.
Hi Sergey,
thanks very much for that. I was already thinking changing everything to
Response so it's also clearer from the service implementation what's going
on.

Do you want me to fill a Jira issue or have you already created it?


Cheers,
V.

On Wed, Oct 14, 2009 at 11:35 AM, Sergey Beryozkin <sb...@progress.com>wrote:

> ok... so if you move this code to a custom filter then it will work as
> expected (without having to throw the exception).
> But it's a form submission. If you decide to use a custom filter then you
> can have a JAXRS Providers injected and ask it to get you a provider capable
> of reading application/www-url-form-encoded, or simply instantiate a CXF
> FormProvider directly and ask it to read the possibly encoded string into a
> Map and proceed from there; if it is only a simple user=bar&password=foo
> kind of post then you might want just to read it directly from the message
> input stream...
>
> Actually, perhaps the simplest option is to simply return a Response
> directly from your method...it will have the right status and Feed set in
>
> cheers, Sergey
>
>
>
>  At the moment I solved throwing a WebApplicationException:
>>
>> feed.addCategory(ERROR_SCHEME,
>> String.valueOf(Status.UNAUTHORIZED.getStatusCode()), "Username or password
>> not valid.");
>> throw new
>>
>> WebApplicationException(Response.status(Status.UNAUTHORIZED).entity(feed).build());
>>
>> were the feed is an Abdera feed. For me it's important to always return a
>> proper feed (serialized by the correct provider) independently from the
>> status code. Throwing the exception seems to work fine.
>>
>> Pro: at least in this service I can avoid including the servlet class in
>> the
>> interface and implementation.
>> Contra: it doesn't sound correct to me throwing exceptions for setting the
>> status code.
>>
>>
>> Cheers,
>> V.
>>
>> P.s.: in the previous email @PathParam --> @FormParam (not yet Atom style
>> for posting)
>>
>> On Wed, Oct 14, 2009 at 3:01 AM, Vincenzo Vitale
>> <vi...@gmail.com>wrote:
>>
>>  Hi,
>>>
>>> in my service implementation I'm injecting the HttpServletResponse with
>>> the
>>> @Context annotation:
>>>
>>>    @POST
>>>    @Path("/login")
>>>    public Feed login(@PathParam("username") String username,
>>>            @PathParam("password") String password,
>>>            @Context HttpServletResponse httpServletResponse)
>>>
>>> and than I set the 401 status code when the user is not authorized. The
>>> problem is that the status code is than overwritten in the
>>> AbstractHTTPDestination class during the headers flushing:
>>>
>>>            Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE);
>>>            if (i != null) {
>>>                int status = i.intValue();
>>>               ... ... ...
>>>                response.setStatus(status);
>>>
>>> is this the expected behaviour or is this a bug?
>>>
>>>
>>>
>>> Thanks in advance,
>>> Vincenzo.
>>>
>>>
>>
>

Re: Setting the status code in the injected (via the jax-rs @context) HttpServletResponse

Posted by Sergey Beryozkin <sb...@progress.com>.
ok... so if you move this code to a custom filter then it will work as expected (without having to throw the exception).
But it's a form submission. If you decide to use a custom filter then you can have a JAXRS Providers injected and ask it to get you 
a provider capable of reading application/www-url-form-encoded, or simply instantiate a CXF FormProvider directly and ask it to read 
the possibly encoded string into a Map and proceed from there; if it is only a simple user=bar&password=foo kind of post then you 
might want just to read it directly from the message input stream...

Actually, perhaps the simplest option is to simply return a Response directly from your method...it will have the right status and 
Feed set in

cheers, Sergey


> At the moment I solved throwing a WebApplicationException:
>
> feed.addCategory(ERROR_SCHEME,
> String.valueOf(Status.UNAUTHORIZED.getStatusCode()), "Username or password
> not valid.");
> throw new
> WebApplicationException(Response.status(Status.UNAUTHORIZED).entity(feed).build());
>
> were the feed is an Abdera feed. For me it's important to always return a
> proper feed (serialized by the correct provider) independently from the
> status code. Throwing the exception seems to work fine.
>
> Pro: at least in this service I can avoid including the servlet class in the
> interface and implementation.
> Contra: it doesn't sound correct to me throwing exceptions for setting the
> status code.
>
>
> Cheers,
> V.
>
> P.s.: in the previous email @PathParam --> @FormParam (not yet Atom style
> for posting)
>
> On Wed, Oct 14, 2009 at 3:01 AM, Vincenzo Vitale
> <vi...@gmail.com>wrote:
>
>> Hi,
>>
>> in my service implementation I'm injecting the HttpServletResponse with the
>> @Context annotation:
>>
>>     @POST
>>     @Path("/login")
>>     public Feed login(@PathParam("username") String username,
>>             @PathParam("password") String password,
>>             @Context HttpServletResponse httpServletResponse)
>>
>> and than I set the 401 status code when the user is not authorized. The
>> problem is that the status code is than overwritten in the
>> AbstractHTTPDestination class during the headers flushing:
>>
>>             Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE);
>>             if (i != null) {
>>                 int status = i.intValue();
>>                ... ... ...
>>                 response.setStatus(status);
>>
>> is this the expected behaviour or is this a bug?
>>
>>
>>
>> Thanks in advance,
>> Vincenzo.
>>
> 


Re: Setting the status code in the injected (via the jax-rs @context) HttpServletResponse

Posted by Vincenzo Vitale <vi...@gmail.com>.
At the moment I solved throwing a WebApplicationException:

feed.addCategory(ERROR_SCHEME,
String.valueOf(Status.UNAUTHORIZED.getStatusCode()), "Username or password
not valid.");
throw new
WebApplicationException(Response.status(Status.UNAUTHORIZED).entity(feed).build());

were the feed is an Abdera feed. For me it's important to always return a
proper feed (serialized by the correct provider) independently from the
status code. Throwing the exception seems to work fine.

Pro: at least in this service I can avoid including the servlet class in the
interface and implementation.
Contra: it doesn't sound correct to me throwing exceptions for setting the
status code.


Cheers,
V.

P.s.: in the previous email @PathParam --> @FormParam (not yet Atom style
for posting)

On Wed, Oct 14, 2009 at 3:01 AM, Vincenzo Vitale
<vi...@gmail.com>wrote:

> Hi,
>
> in my service implementation I'm injecting the HttpServletResponse with the
> @Context annotation:
>
>     @POST
>     @Path("/login")
>     public Feed login(@PathParam("username") String username,
>             @PathParam("password") String password,
>             @Context HttpServletResponse httpServletResponse)
>
> and than I set the 401 status code when the user is not authorized. The
> problem is that the status code is than overwritten in the
> AbstractHTTPDestination class during the headers flushing:
>
>             Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE);
>             if (i != null) {
>                 int status = i.intValue();
>                ... ... ...
>                 response.setStatus(status);
>
> is this the expected behaviour or is this a bug?
>
>
>
> Thanks in advance,
> Vincenzo.
>