You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by John Baker <jb...@dryfish.org.uk> on 2013/07/29 12:52:05 UTC
JAX-RS method matching
Hello
I'm having trouble with CXF's JAX-RS implementation. The service is
struggling to match the correct method defined on an interface. Please
consider:
@Path("/update")
public interface MyService {
@PUT
@Path("/{id}")
public void updateFruit(@QueryParam("id") String id, Banana banana);
@PUT
@Path("/{id}")
public void updateAnimal(@QueryParam("id") String id, Dog dog);
}
where both Banana and Dog extend a common object. When making a call to
updateFruit from a jax-rs client, it calls updateAnimal. I've traced the
problem into JAXRSUtils and I'm wondering if there's any solution, or do
these methods need unique paths?
Thanks
John
--
John Baker
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 29/07/13 12:48, John Baker wrote:
> I can only determine the parameter type / method by the message body, so
> I guess I need a generic "put" method with an object, and use the
> provider to create the correct object, before using an if instanceof in
> the method.
>
May be you can use a custom provider which will have "@Context Providers
providers;" injected - your provider will read IS, do the checks to
determine the type, restore IS and then ask 'providers' to find the
right provider, or if you know that it is always JAXB for ex, then
simply delegate to JAXBElementProvider after the actual type has been
determined, it will be simpler
Cheers, Sergey
Re: JAX-RS method matching
Posted by John Baker <jb...@dryfish.org.uk>.
I can only determine the parameter type / method by the message body, so
I guess I need a generic "put" method with an object, and use the
provider to create the correct object, before using an if instanceof in
the method.
--
John Baker
On Mon, Jul 29, 2013, at 12:46 PM, Sergey Beryozkin wrote:
> On 29/07/13 12:41, John Baker wrote:
> > Sergey,
> >
> >
> >> You can have "@Context MessageContext" or any of standard JAX-RS
> >> contexts injected into your custom provider
> >
> > Just to clarify, should I inject this as a class variable on the
> > provider, ie are the providers thread safe and is the message updated on
> > each call to readFrom?
> >
> Yes, the injected contexts ate thread-safe
>
> Sergey
> >
> > John
> >
>
>
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 29/07/13 12:41, John Baker wrote:
> Sergey,
>
>
>> You can have "@Context MessageContext" or any of standard JAX-RS
>> contexts injected into your custom provider
>
> Just to clarify, should I inject this as a class variable on the
> provider, ie are the providers thread safe and is the message updated on
> each call to readFrom?
>
Yes, the injected contexts ate thread-safe
Sergey
>
> John
>
Re: JAX-RS method matching
Posted by John Baker <jb...@dryfish.org.uk>.
Sergey,
> You can have "@Context MessageContext" or any of standard JAX-RS
> contexts injected into your custom provider
Just to clarify, should I inject this as a class variable on the
provider, ie are the providers thread safe and is the message updated on
each call to readFrom?
John
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 29/07/13 12:27, John Baker wrote:
> Hello
>
> Thanks for responding so quickly.
>
>> JAX-RS selection algorithm sees these 2 methods as equal candidates.
>> IMHO having unique paths for different type of resources (from the
>> client's POV, not from the Java hierarchy perspective) is reasonable
>> IMHO, but if you prefer or *have to* use the same method signatures, then
>
> Yes, it is very bad, I agree. But the client disagrees. :)
>
> I'll look into your solution but could you also tell me how to get the
> Message object, or more importantly, the URI from an extension of an
> AbstractConfigurableProvider? I've got something to translate the
> message body into objects (ie deserialise it) and there may be a
> solution in there..
>
You can have "@Context MessageContext" or any of standard JAX-RS
contexts injected into your custom provider
Sergey
>
> John
>
Re: JAX-RS method matching
Posted by John Baker <jb...@dryfish.org.uk>.
Hello
Thanks for responding so quickly.
> JAX-RS selection algorithm sees these 2 methods as equal candidates.
> IMHO having unique paths for different type of resources (from the
> client's POV, not from the Java hierarchy perspective) is reasonable
> IMHO, but if you prefer or *have to* use the same method signatures, then
Yes, it is very bad, I agree. But the client disagrees. :)
I'll look into your solution but could you also tell me how to get the
Message object, or more importantly, the URI from an extension of an
AbstractConfigurableProvider? I've got something to translate the
message body into objects (ie deserialise it) and there may be a
solution in there..
John
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 29/07/13 12:52, John Baker wrote:
>
>> use CXF ResourceComparator,
>> http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Customselectionbetweenmultipleresources
>
> How is the ResourceComparator implementation registered with the
> service? Can it be done via an annotation on the interface?
>
Have you read the section :-) ?
It says:
"Starting from CXF 2.2.5 it is possible to register a custom
ResourceComparator implementation using a
jaxrs:server/resourceComparator element."
Actually, it has to be "jaxrs:server/jaxrs:resourceComparator", will fix it
Sergey
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
It looks quite perfect, though you can probably simplify and avoid
checking a super-class, unless you can also have for example multiple
PUT operations with intersecting path values or some complex Consumes
expressions...
re returning 0: means you don't mind which method will be selected which
is not your case, but yes, you can default to 0
Cheers, Sergey
On 29/07/13 14:01, John Baker wrote:
> This appears to be the answer:
>
>
>
> // Check if CXF can make a decision
>
> int cxfResult= super.compare(oper1, oper2);
>
> if (cxfResult != 0)
>
> return cxfResult;
>
>
>
> Int result = 0;
>
> String s = … message body.
>
> String target= null;
>
> if (s.startsWith(“banana”))
>
> target= "updateFruit";
>
> else if (s.startsWith(“dog”))
>
> target= "updateAnimal";
>
> if (target!=null) {
>
> if (m1.equals(m2) && m1.equals(target))
>
> result = 0;
>
> else if (m1.equals(target))
>
> result= -1;
>
> else if (m2.equals(target))
>
> result= 1;
>
> else
>
> result= m1.compareTo(m2);
>
> }
>
> return result;
>
Re: JAX-RS method matching
Posted by John Baker <jb...@dryfish.org.uk>.
This appears to be the answer:
// Check if CXF can make a decision
int cxfResult= super.compare(oper1, oper2);
if (cxfResult != 0)
return cxfResult;
Int result = 0;
String s = … message body.
String target= null;
if (s.startsWith(“banana”))
target= "updateFruit";
else if (s.startsWith(“dog”))
target= "updateAnimal";
if (target!=null) {
if (m1.equals(m2) && m1.equals(target))
result = 0;
else if (m1.equals(target))
result= -1;
else if (m2.equals(target))
result= 1;
else
result= m1.compareTo(m2);
}
return result;
--
John Baker
On Mon, Jul 29, 2013, at 01:51 PM, John Baker wrote:
>
> > The relevant RC method needs to help with ordering the method
> > candidates, so return either -1 or 1 to help the runtime choose the
> > right candidate
>
> But what is "equal"? Is it the two resource infos pointing to
> updateFruit when i know the target is that method? So return 0 in that
> case?
>
> And what's the algorithm when two different resource infos are passed,
> that may or may not be updateFruit?
>
> (I think there may be an easier way to write this interface - simply
> list through the methods calling a method on an interface that returns
> true or false - but that's a discussion for another day.)
Re: JAX-RS method matching
Posted by John Baker <jb...@dryfish.org.uk>.
> The relevant RC method needs to help with ordering the method
> candidates, so return either -1 or 1 to help the runtime choose the
> right candidate
But what is "equal"? Is it the two resource infos pointing to
updateFruit when i know the target is that method? So return 0 in that
case?
And what's the algorithm when two different resource infos are passed,
that may or may not be updateFruit?
(I think there may be an easier way to write this interface - simply
list through the methods calling a method on an interface that returns
true or false - but that's a discussion for another day.)
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 29/07/13 13:39, John Baker wrote:
> Ok I'm stumped. Given my example:
>
> @PUT
> @Path("/{id}")
> public void updateFruit(@QueryParam("id") String id, Banana banana);
>
> @PUT
> @Path("/{id}")
> public void updateAnimal(@QueryParam("id") String id, Dog dog);
>
> what should I be testing in the compare(OperationalResourceInfo r1,
> OperationalResourceInfo r2) method? I see the OperationalResourceInfo
> methods have a getAnnotatedMethod property, and let's assume I know it
> should be calling updateAnimal (because of the Message body), what
> should I return for the various potential values?
>
The relevant RC method needs to help with ordering the method
candidates, so return either -1 or 1 to help the runtime choose the
right candidate
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 29/07/13 13:05, John Baker wrote:
> Defining in the XML Is fine. I'm just working out how the compare method
> for a method is supposed to work with my example...
>
What you can do is to do a check in your custom RC on the input stream
available on the current message
(message.getContent(InputStream.class)), determine the type, restore IS
(via message.putContent) and also save the determined type as a message
property, ex, message.put("custom.type", Banana.class);
Next your custom MessageBodyReader will get this actual type from the
injected MessageContext.get(...) and use it when calling on
JAXBElementProvider
May be there is a cleaner way
Sergey
Re: JAX-RS method matching
Posted by John Baker <jb...@dryfish.org.uk>.
Defining in the XML Is fine. I'm just working out how the compare method
for a method is supposed to work with my example...
--
John Baker
On Mon, Jul 29, 2013, at 01:02 PM, Sergey Beryozkin wrote:
> On 29/07/13 12:59, John Baker wrote:
> >
> >> Have you read the section :-) ?
> >
> > Yes but not well enough.
> >
> >> It says:
> >> "Starting from CXF 2.2.5 it is possible to register a custom
> >> ResourceComparator implementation using a
> >> jaxrs:server/resourceComparator element."
> >>
> >> Actually, it has to be "jaxrs:server/jaxrs:resourceComparator", will fix
> >> it
> >
> > Ah, you're referring to the Spring element. I think a short example that
> > looks like XML would be superb at that position :)
> >
> OK. I can do that.
>
> re the possible annotation: probably not possible, RC can select both
> classes & operations, the former function is mostly redundant with
> JAX-RS 2.0, but it would be tricky to manage RCs declared at multiple
> class or method levels
>
> Sergey
>
> > Thanks!
> >
>
>
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 29/07/13 12:59, John Baker wrote:
>
>> Have you read the section :-) ?
>
> Yes but not well enough.
>
>> It says:
>> "Starting from CXF 2.2.5 it is possible to register a custom
>> ResourceComparator implementation using a
>> jaxrs:server/resourceComparator element."
>>
>> Actually, it has to be "jaxrs:server/jaxrs:resourceComparator", will fix
>> it
>
> Ah, you're referring to the Spring element. I think a short example that
> looks like XML would be superb at that position :)
>
OK. I can do that.
re the possible annotation: probably not possible, RC can select both
classes & operations, the former function is mostly redundant with
JAX-RS 2.0, but it would be tricky to manage RCs declared at multiple
class or method levels
Sergey
> Thanks!
>
Re: JAX-RS method matching
Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 29/07/13 11:52, John Baker wrote:
> Hello
>
> I'm having trouble with CXF's JAX-RS implementation. The service is
> struggling to match the correct method defined on an interface. Please
> consider:
>
> @Path("/update")
> public interface MyService {
>
> @PUT
> @Path("/{id}")
> public void updateFruit(@QueryParam("id") String id, Banana banana);
>
> @PUT
> @Path("/{id}")
> public void updateAnimal(@QueryParam("id") String id, Dog dog);
> }
>
> where both Banana and Dog extend a common object. When making a call to
> updateFruit from a jax-rs client, it calls updateAnimal. I've traced the
> problem into JAXRSUtils and I'm wondering if there's any solution, or do
> these methods need unique paths?
>
JAX-RS selection algorithm sees these 2 methods as equal candidates.
IMHO having unique paths for different type of resources (from the
client's POV, not from the Java hierarchy perspective) is reasonable
IMHO, but if you prefer or *have to* use the same method signatures, then
use CXF ResourceComparator,
http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Customselectionbetweenmultipleresources
Another approach is to do Subresource locators:
@Path("/update")
public interface MyService {
@Path("/{id}")
public void update(@PathParam("id") String id, @QueryParam("type")
String type) {
if ("banana".equals(type)) {
return new Bananaresource(id);
}
...
}
public class BananaResource {
private String id;
@PUT
public void update(Banana b) {
}
etc
Sergey
> Thanks
>
>
> John
>