You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by vickatvuuch <vl...@gmail.com> on 2009/12/11 03:30:28 UTC

CXF REST nested bean initialization in the POST x-www-form-urlencoded

I've ran into some small gotcha with my java bean parameter.
It has simple bean nested inside as a member,which works fine if 
I execute GET request with params on the url, for examle:
/login?principal.username=dude
Here is my GET entry point:
On the top of the impl I have:
  @Consumes({"text/xml", "application/xml", "application/json",
"application/x-www-form-urlencoded"})

  @GET
  @Path("/login")
  public WSSessionInfo login(@QueryParam("") WSAuthRequest auth) throws
WSAuthFault

On the POST side, things are not as great as found out, for example my
attempt to get 
it to work over a POST form didn't work, anything I annotated wrong or it
simple not supporting
nested beans arriving in POST forms:

  @POST
  @Path("/login")
  @Produces({"text/xml", "application/xml", "application/json"})
  @Consumes({"application/x-www-form-urlencoded"}) 
  public WSSessionInfo login2(WSAuthRequest auth)  throws WSAuthFault

The request I sent in:

POST /services/v1/rest/Auth/login HTTP/1.1
Accept-Encoding: gzip,deflate
Accept: application/xml
Content-Type: application/x-www-form-urlencoded
User-Agent: Jakarta Commons-HttpClient/3.1
Host: localhost:8085
Content-Length: 39

principal.username=dude
password=1234

I was hoping for this to work in the same way as when I do GET, shouldn't
it?

Thanks,
-Vitaly
-- 
View this message in context: http://old.nabble.com/CXF-REST-nested-bean-initialization-in-the-POST-x-www-form-urlencoded-tp26737818p26737818.html
Sent from the cxf-user mailing list archive at Nabble.com.


RE: CXF REST nested bean initialization in the POST x-www-form-urlencoded

Posted by Sergey Beryozkin <sb...@progress.com>.
Please see comments with S.B inlined

Cheers, Sergey
-----Original Message-----
From: vickatvuuch [mailto:vlisovsky@gmail.com] 
Sent: 11 December 2009 15:09
To: users@cxf.apache.org
Subject: Re: CXF REST nested bean initialization in the POST
x-www-form-urlencoded


Thanks Sergey, for this great level of details. 

What I really miss is a mechanism where the engine could decide, 
based on the mime type supplied in the HTTP request, which method 
to call on the REST port and inject in all cases whether annotated or
not.

> S.B. I'm not sure if there is any ambiguity. In JAXRS message body
providers are responsible for handling payloads only. When we look at
any particular method, a parameter not annotated with JAXRS parameter or
context annotations is assumed to be representing a request body, same
as a return type. All other method in  parameters are not dealt with by
message body providers, in most cases they may to various request URI
parts and the way they're populated is prescribed by the JAXRS spec. CXF
adds few extensions such as QueryParam("") or ParameterHandler. 

It should be able to inject it, whether there is @FormParam or
@QueryParam
annotation. 

> S.B yes, provided you do have either @FormParam("") or @QueryParam("")
attached to a given method parameter.

Regarding the MultiValueMap, if I put a MultiValueMap props,
inside my WSAuthRequest, could it fill it in with form params then? 

> S.B No, injecting into bean map properties is not supported yet

Just a suggestion: if there is a MVM property in the bean fill it in
with
form params, then
other properties by name as before. Not having this in place forced
me to define a separate method with MultiValueMap as the only parameter,
later I have to initialize the WSAuthRequest myself by pulling data out
of
the map.. 

> S.B this sounds over complicated. As I suggested earlier on, filling
in such a map either in the custom form provider or in a filter would do
the trick


The bean injection use case for me, goes like this: The
WSAuthRequest.principal 
injection works nicely in SOAP and a corresponding REST login method
annotated 
with @QueryParam("") allows me to do HTTP GET no problem there. 

Now if I want to enable POST, with form params, that makes me to
define anoter mehod login2, that is only visible to REST and even that 
doesn't help as like you mentioned injection doesn't work in this case
:( 

> S.B It is not possible in JAXRS to have a single resource method
handling multiple HTTP methods. We thought about extending CXF a bit in
this regard...

Conceptually I do not see why can't it be done whether I send
principal.username=dude on the Url or on the POST form?

> S.B. It can be done if you attach either @FormParam("") or
QueryParam(""). If you do POST then you can also have a custom form
provider which can rely on internal CXF utility to populate a bean, as I
suggested earlier on.

PS
I did attached custom query and form providers, 
which for now fixed the dot decoding issue. 

S.B. no code is attached

Thanks,
-Vitaly


Sergey Beryozkin-2 wrote:
> 
> Hi,
> 
>>
>> I've ran into some small gotcha with my java bean parameter.
>> It has simple bean nested inside as a member,which works fine if
> <snip/>
>> On the POST side, things are not as great as found out, for example
my
>> attempt to get
>> it to work over a POST form didn't work, anything I annotated wrong
or it
>> simple not supporting
>> nested beans arriving in POST forms:
>>
>>  @POST
>>  @Path("/login")
>>  @Produces({"text/xml", "application/xml", "application/json"})
>>  @Consumes({"application/x-www-form-urlencoded"})
>>  public WSSessionInfo login2(WSAuthRequest auth)  throws WSAuthFault
>>
>> The request I sent in:
>>
>> POST /services/v1/rest/Auth/login HTTP/1.1
>> Accept-Encoding: gzip,deflate
>> Accept: application/xml
>> Content-Type: application/x-www-form-urlencoded
>> User-Agent: Jakarta Commons-HttpClient/3.1
>> Host: localhost:8085
>> Content-Length: 39
>>
>> principal.username=dude
>> password=1234
>>
>> I was hoping for this to work in the same way as when I do GET,
shouldn't
>> it?
> 
> JAXRS providers handling "application/x-www-form-urlencoded" only
support
> MultivaluedMap :
> 
> public WSSessionInfo login2(MultivaluedMap form)  {}
> 
> For the arbitrary bean injection to work you need to add
@FormParam("") :
> 
> public WSSessionInfo login2(@FormParam("") WSAuthRequest auth)
> 
> that is the bean injection works only for method parameters annotatted
> with @FormParam("") or @QueryParam("") or PathParam("") or 
> @MatrixParam("").
> 
> If you decide to go with FormParam(""), then, unless you're ready to
work
> with the 2.2.6-SNAPSHOT, you'd need to move your current 
> form name decoding fix into a filter, as suggested earlier on, this is
due
> to the fact that a code handling @FormParams does not 
> rely on the form provider, rather both this code and the provider rely
on
> a shared utility code so your custom provider won't be 
> used in this case. Though it looks like the dot is not url-encoded in
your
> case so you should be ok with the existing code handling 
> @FormParam.
> 
> Finally,
> 
> public WSSessionInfo login2(WSAuthRequest auth)  throws WSAuthFault
> 
> shoud work if your custom form provider overrides isReadable (return
true
> if it is WSAuthRequest or super.isReadbale() is true) and 
> readFrom, where you delegate io InjectionUtils if it is WSAuthRequest
that
> has to be initialized, after populating a map of form 
> name.value pairs :
> 
> InjectionUtils.handleBean(WSAuthRequest.class,
theMapOfFormNameValuePairs,
> ParameterType.FORM, new MessageImpl(), true);
> 
> hope it helps, Sergey
> 
> 
>>
>> Thanks,
>> -Vitaly
>> -- 
>> View this message in context: 
>>
http://old.nabble.com/CXF-REST-nested-bean-initialization-in-the-POST-x-
www-form-urlencoded-tp26737818p26737818.html
>> Sent from the cxf-user mailing list archive at Nabble.com.
>> 
> 
> 
> 

-- 
View this message in context:
http://old.nabble.com/CXF-REST-nested-bean-initialization-in-the-POST-x-
www-form-urlencoded-tp26737818p26745834.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: CXF REST nested bean initialization in the POST x-www-form-urlencoded

Posted by vickatvuuch <vl...@gmail.com>.
Thanks Sergey, for this great level of details. 

What I really miss is a mechanism where the engine could decide, 
based on the mime type supplied in the HTTP request, which method 
to call on the REST port and inject in all cases whether annotated or not.

It should be able to inject it, whether there is @FormParam or @QueryParam
annotation. 

Regarding the MultiValueMap, if I put a MultiValueMap props,
inside my WSAuthRequest, could it fill it in with form params then? 

Just a suggestion: if there is a MVM property in the bean fill it in with
form params, then
other properties by name as before. Not having this in place forced
me to define a separate method with MultiValueMap as the only parameter,
later I have to initialize the WSAuthRequest myself by pulling data out of
the map.. 

The bean injection use case for me, goes like this: The
WSAuthRequest.principal 
injection works nicely in SOAP and a corresponding REST login method
annotated 
with @QueryParam("") allows me to do HTTP GET no problem there. 

Now if I want to enable POST, with form params, that makes me to
define anoter mehod login2, that is only visible to REST and even that 
doesn't help as like you mentioned injection doesn't work in this case :( 

Conceptually I do not see why can't it be done whether I send
principal.username=dude on the Url or on the POST form?

PS
I did attached custom query and form providers, 
which for now fixed the dot decoding issue. 

Thanks,
-Vitaly


Sergey Beryozkin-2 wrote:
> 
> Hi,
> 
>>
>> I've ran into some small gotcha with my java bean parameter.
>> It has simple bean nested inside as a member,which works fine if
> <snip/>
>> On the POST side, things are not as great as found out, for example my
>> attempt to get
>> it to work over a POST form didn't work, anything I annotated wrong or it
>> simple not supporting
>> nested beans arriving in POST forms:
>>
>>  @POST
>>  @Path("/login")
>>  @Produces({"text/xml", "application/xml", "application/json"})
>>  @Consumes({"application/x-www-form-urlencoded"})
>>  public WSSessionInfo login2(WSAuthRequest auth)  throws WSAuthFault
>>
>> The request I sent in:
>>
>> POST /services/v1/rest/Auth/login HTTP/1.1
>> Accept-Encoding: gzip,deflate
>> Accept: application/xml
>> Content-Type: application/x-www-form-urlencoded
>> User-Agent: Jakarta Commons-HttpClient/3.1
>> Host: localhost:8085
>> Content-Length: 39
>>
>> principal.username=dude
>> password=1234
>>
>> I was hoping for this to work in the same way as when I do GET, shouldn't
>> it?
> 
> JAXRS providers handling "application/x-www-form-urlencoded" only support
> MultivaluedMap :
> 
> public WSSessionInfo login2(MultivaluedMap form)  {}
> 
> For the arbitrary bean injection to work you need to add @FormParam("") :
> 
> public WSSessionInfo login2(@FormParam("") WSAuthRequest auth)
> 
> that is the bean injection works only for method parameters annotatted
> with @FormParam("") or @QueryParam("") or PathParam("") or 
> @MatrixParam("").
> 
> If you decide to go with FormParam(""), then, unless you're ready to work
> with the 2.2.6-SNAPSHOT, you'd need to move your current 
> form name decoding fix into a filter, as suggested earlier on, this is due
> to the fact that a code handling @FormParams does not 
> rely on the form provider, rather both this code and the provider rely on
> a shared utility code so your custom provider won't be 
> used in this case. Though it looks like the dot is not url-encoded in your
> case so you should be ok with the existing code handling 
> @FormParam.
> 
> Finally,
> 
> public WSSessionInfo login2(WSAuthRequest auth)  throws WSAuthFault
> 
> shoud work if your custom form provider overrides isReadable (return true
> if it is WSAuthRequest or super.isReadbale() is true) and 
> readFrom, where you delegate io InjectionUtils if it is WSAuthRequest that
> has to be initialized, after populating a map of form 
> name.value pairs :
> 
> InjectionUtils.handleBean(WSAuthRequest.class, theMapOfFormNameValuePairs,
> ParameterType.FORM, new MessageImpl(), true);
> 
> hope it helps, Sergey
> 
> 
>>
>> Thanks,
>> -Vitaly
>> -- 
>> View this message in context: 
>> http://old.nabble.com/CXF-REST-nested-bean-initialization-in-the-POST-x-www-form-urlencoded-tp26737818p26737818.html
>> Sent from the cxf-user mailing list archive at Nabble.com.
>> 
> 
> 
> 

-- 
View this message in context: http://old.nabble.com/CXF-REST-nested-bean-initialization-in-the-POST-x-www-form-urlencoded-tp26737818p26745834.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: CXF REST nested bean initialization in the POST x-www-form-urlencoded

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

>
> I've ran into some small gotcha with my java bean parameter.
> It has simple bean nested inside as a member,which works fine if
<snip/>
> On the POST side, things are not as great as found out, for example my
> attempt to get
> it to work over a POST form didn't work, anything I annotated wrong or it
> simple not supporting
> nested beans arriving in POST forms:
>
>  @POST
>  @Path("/login")
>  @Produces({"text/xml", "application/xml", "application/json"})
>  @Consumes({"application/x-www-form-urlencoded"})
>  public WSSessionInfo login2(WSAuthRequest auth)  throws WSAuthFault
>
> The request I sent in:
>
> POST /services/v1/rest/Auth/login HTTP/1.1
> Accept-Encoding: gzip,deflate
> Accept: application/xml
> Content-Type: application/x-www-form-urlencoded
> User-Agent: Jakarta Commons-HttpClient/3.1
> Host: localhost:8085
> Content-Length: 39
>
> principal.username=dude
> password=1234
>
> I was hoping for this to work in the same way as when I do GET, shouldn't
> it?

JAXRS providers handling "application/x-www-form-urlencoded" only support MultivaluedMap :

public WSSessionInfo login2(MultivaluedMap form)  {}

For the arbitrary bean injection to work you need to add @FormParam("") :

public WSSessionInfo login2(@FormParam("") WSAuthRequest auth)

that is the bean injection works only for method parameters annotatted with @FormParam("") or @QueryParam("") or PathParam("") or 
@MatrixParam("").

If you decide to go with FormParam(""), then, unless you're ready to work with the 2.2.6-SNAPSHOT, you'd need to move your current 
form name decoding fix into a filter, as suggested earlier on, this is due to the fact that a code handling @FormParams does not 
rely on the form provider, rather both this code and the provider rely on a shared utility code so your custom provider won't be 
used in this case. Though it looks like the dot is not url-encoded in your case so you should be ok with the existing code handling 
@FormParam.

Finally,

public WSSessionInfo login2(WSAuthRequest auth)  throws WSAuthFault

shoud work if your custom form provider overrides isReadable (return true if it is WSAuthRequest or super.isReadbale() is true) and 
readFrom, where you delegate io InjectionUtils if it is WSAuthRequest that has to be initialized, after populating a map of form 
name.value pairs :

InjectionUtils.handleBean(WSAuthRequest.class, theMapOfFormNameValuePairs, ParameterType.FORM, new MessageImpl(), true);

hope it helps, Sergey


>
> Thanks,
> -Vitaly
> -- 
> View this message in context: 
> http://old.nabble.com/CXF-REST-nested-bean-initialization-in-the-POST-x-www-form-urlencoded-tp26737818p26737818.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>