You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Brad <br...@javawork.co.uk> on 2008/05/06 15:35:26 UTC

@Path not mapping to required methods

Hi,

I'm getting an issue where my @Path annotations aren't mapping to the
required URLs. Here's a rough outline of my test class:

@Path(value="/{domain}/{network}/{user}/mail")
public class MailService {

	@GET
	@ConsumeMime({"application/xml", "application/json"})
	@ProduceMime({"application/xml", "application/json"})
	public MailFolderDocument listMail(@PathParam("domain")String domain,
@PathParam("network")String network, @PathParam("user")String user,
@HeaderParam("token")String token){
            ....
        }

	@Path(value="/{messageId}", limited=true)
	@GET
	@ConsumeMime({"application/xml", "application/json"})
	@ProduceMime({"application/xml", "application/json"})
	public MessageDocument readMessage(@PathParam("user")String user,
@PathParam("messageId")String messageId, @HeaderParam("token")String
token){
            ....
        }
}

The problem I'm seeing is that when i invoke the URL
http://localhost:8081/cxf/rest/test/domain/network/brad/mail, it
invokes the readMessage method instead of listMail. Am I using the
correct format for my annotations here?

Anyway, just in case I have got it right (*pig flies by*) I stepped
through JAXRSUtils.findTargetMethod and I was left wondering if this
line is correct:

private static final String URITEMPLATE_VARIABLE_REGEX = "(.*?)";

I'm no regex expert but I did find this in the Java 1.5 API docs:

X*?  	X, zero or more times
X+? 	X, one or more times

Would that value make more sense as "(.+?)" ?

Thanks,
Brad.

Re: @Path not mapping to required methods

Posted by Sergey Beryozkin <se...@iona.com>.
Hi Brad

Thanks for looking into this code. It would be great if several people could have a shared knowledge of what's happening in that 
code...The algorithm implementation in CXF may still need some fixes applied to it.

> (requested)uri:               "/"
> template:                      "/{messageId}"
> templateRegexPattern:  "/(.*?)(/.*)?"

This is all dictated by the spec. Every occurence of {} template parameter is substituted by /(.*?), and then (/.*)? is added if 
it's a limited template (default).
The rationale I believe is that it allows for some methods to point some other methods on subresource locators. For example, if 
http://localhost:8081/cxf/rest/test/domain/network/brad/mail/123 were to be processed by a sub locator, then the value of the final 
matching group would be '123' and it would be used to find the actual method on the sub locator class.



> Hi,
>
> just to follow up from yesterday, I just wanted to clarify the regular
> expression stuff.
>
> Having stepped through the code in URITemplate.match the main point of
> interest seems to be around line 122:
>
>        Matcher m = templateRegexPattern.matcher(uri);
>        if (!m.matches()) {
>            return false;
>        }
>
> As far as I can tell, this is what compares the requested URI to those
> declared for each method and therefore dictates what methods are
> matched. Given my test class the values I'm seeing the following
> variable values for the method readMessage:
>
> (requested)uri:               "/"
> template:                      "/{messageId}"
> templateRegexPattern:  "/(.*?)(/.*)?"
>
> Regex is not exactly my forte but from what I can tell this pattern
> would match the template because it is effectively the "/" with zero
> or more characters after it, potentially repeated one or more times.
> Is that correct?
>
> My expectation here is that it shouldn't match because the method
> template specifies that the "/" has a variable "messageId" after it.
> With this requirement in mind, shouldn't it be looking for one or more
> characters after the "/" which would require the pattern "/(.+?)".
> With the pattern set to "/(.*?)" it seems to me that there is no way
> to differentiate between the template for listMail ("/") and the
> template for readMail ("/{messageId}").

It makes sense. I've actually asked a question on the JAX-RS users list for some clarification on this issue...
It's most likely that there's a flaw in the CXF implementation of the algorithm and this needs to be tracked down...

Cheers, Sergey

>
> Apologies if I've got that fundamentally wrong. I don't think my
> understanding of capturing groups is what it could be. It does seem to
> be matching both of the method templates though.
>
> Brad.

----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland

Re: @Path not mapping to required methods

Posted by Brad <br...@javawork.co.uk>.
Hi Sergey,

yeah saw the discussion over on the jax-rs mailing list.

Not a bug then as its in line with the spec. Bit disappointed that the
spec doesn't support that but maybe that's just me.

Thanks for looking into it.

Brad.

On Wed, May 7, 2008 at 2:36 PM, Sergey Beryozkin
<se...@iona.com> wrote:
>
>
> Hi Brad
>
> Thanks for looking into this code. It would be great if several people could
> have a shared knowledge of what's happening in that code...The algorithm
> implementation in CXF may still need some fixes applied to it.
>
> > (requested)uri:               "/"
> > template:                      "/{messageId}"
> > templateRegexPattern:  "/(.*?)(/.*)?"
>
> This is all dictated by the spec. Every occurence of {} template parameter
> is substituted by /(.*?), and then (/.*)? is added if it's a limited
> template (default).
>
> The rationale I believe is that it allows for some methods to point some
> other methods on subresource locators. For example, if
> http://localhost:8081/cxf/rest/test/domain/network/brad/mail/123 were to be
> processed by a sub locator, then the value of the final matching group would
> be '123' and it would be used to find the actual method on the sub locator
> class.
>
>
>
>
> > Hi,
> >
> > just to follow up from yesterday, I just wanted to clarify the regular
> > expression stuff.
> >
> > Having stepped through the code in URITemplate.match the main point of
> > interest seems to be around line 122:
> >
> >        Matcher m = templateRegexPattern.matcher(uri);
> >        if (!m.matches()) {
> >            return false;
> >        }
> >
> > As far as I can tell, this is what compares the requested URI to those
> > declared for each method and therefore dictates what methods are
> > matched. Given my test class the values I'm seeing the following
> > variable values for the method readMessage:
> >
> > (requested)uri:               "/"
> > template:                      "/{messageId}"
> > templateRegexPattern:  "/(.*?)(/.*)?"
> >
> > Regex is not exactly my forte but from what I can tell this pattern
> > would match the template because it is effectively the "/" with zero
> > or more characters after it, potentially repeated one or more times.
> > Is that correct?
> >
> > My expectation here is that it shouldn't match because the method
> > template specifies that the "/" has a variable "messageId" after it.
> > With this requirement in mind, shouldn't it be looking for one or more
> > characters after the "/" which would require the pattern "/(.+?)".
> > With the pattern set to "/(.*?)" it seems to me that there is no way
> > to differentiate between the template for listMail ("/") and the
> > template for readMail ("/{messageId}").
>
> It makes sense. I've actually asked a question on the JAX-RS users list for
> some clarification on this issue...
> It's most likely that there's a flaw in the CXF implementation of the
> algorithm and this needs to be tracked down...
>
> Cheers, Sergey
>
> >
>
> > Apologies if I've got that fundamentally wrong. I don't think my
> > understanding of capturing groups is what it could be. It does seem to
> > be matching both of the method templates though.
> >
> > Brad.
> >
> > On Tue, May 6, 2008 at 5:36 PM, Brad <br...@javawork.co.uk> wrote:
> >> Hi Sergey,
> >>
> >>  yes listMail is added to the list of candidates.
> >>
> >>  https://issues.apache.org/jira/browse/CXF-1572
> >>
> >>  Brad.
> >>
> >>
> >>
> >>
> >>  On Tue, May 6, 2008 at 5:04 PM, Sergey Beryozkin
> >>  <se...@iona.com> wrote:
> >>  > Hi
> >>  >
> >>  >
> >>  >
> >>  > > Hi,
> >>  > >
> >>  > > I'm getting an issue where my @Path annotations aren't mapping to
> the
> >>  > > required URLs. Here's a rough outline of my test class:
> >>  > >
> >>  > > @Path(value="/{domain}/{network}/{user}/mail")
> >>  > > public class MailService {
> >>  > >
> >>  > > @GET
> >>  > > @ConsumeMime({"application/xml", "application/json"})
> >>  > > @ProduceMime({"application/xml", "application/json"})
> >>  > > public MailFolderDocument listMail(@PathParam("domain")String
> domain,
> >>  > > @PathParam("network")String network, @PathParam("user")String user,
> >>  > > @HeaderParam("token")String token){
> >>  > >           ....
> >>  > >       }
> >>  > >
> >>  > > @Path(value="/{messageId}", limited=true)
> >>  > > @GET
> >>  > > @ConsumeMime({"application/xml", "application/json"})
> >>  > > @ProduceMime({"application/xml", "application/json"})
> >>  > > public MessageDocument readMessage(@PathParam("user")String user,
> >>  > > @PathParam("messageId")String messageId, @HeaderParam("token")String
> >>  > > token){
> >>  > >           ....
> >>  > >       }
> >>  > > }
> >>  > >
> >>  > > The problem I'm seeing is that when i invoke the URL
> >>  > > http://localhost:8081/cxf/rest/test/domain/network/brad/mail, it
> >>  > > invokes the readMessage method instead of listMail. Am I using the
> >>  > > correct format for my annotations here?
> >>  > >
> >>  >
> >>  >  The annontations seem fine. Can you confirm please, as your're
> debugging,
> >>  > that listMail() is also added to the list of candidates ?
> >>  >  I'm actually not sure what exactly JAX_RS says in this regard, the
> only
> >>  > piece I can see is this one (section 3.6, 2.f) :
> >>  >
> >>  >  "Sort E using the number of literal characters in each member as the
> >>  > primary key (descending order), ..., number of capturing groups as the
> >>  > secondary key, and the source of each member ..."
> >>  >
> >>  >  In both cases it's a resource method, so the source is the same.
> Number of
> >>  > captuting groups for listMail is 3 as opposed to 2 for readEmail(),
> and the
> >>  > number of literal characters is different. It seems like only this bit
> of
> >>  > the specification which governs the dispatch in this case, but I''ll
> need to
> >>  > verify it...
> >>  >
> >>  >  One possible workaround is to
> >>  >
> >>  >  1. Have another root class created, but with slightly different Path.
> >>  >
> >>  >  In the end, I believe it's the CXF bug rather than the ambiguity of
> the
> >>  > JAX-RS spec...Can you please open a JIRA ?
> >>  >
> >>  >
> >>  >
> >>  >
> >>  >
> >>  > >
> >>  > > Anyway, just in case I have got it right (*pig flies by*) I stepped
> >>  > > through JAXRSUtils.findTargetMethod and I was left wondering if this
> >>  > > line is correct:
> >>  > >
> >>  > > private static final String URITEMPLATE_VARIABLE_REGEX = "(.*?)";
> >>  > >
> >>  > > I'm no regex expert but I did find this in the Java 1.5 API docs:
> >>  > >
> >>  > > X*?  X, zero or more times
> >>  > > X+? X, one or more times
> >>  > >
> >>  > > Would that value make more sense as "(.+?)" ?
> >>  > >
> >>  >
> >>  >  This is required by the spec, every template parameter is substituted
> by
> >>  > this reg expression. The rationale I believe is that it
> >>  >  makes it possible for a given method act as a subresource locator...
> >>  >
> >>  >  Cheers, Sergey
> >>  >
> >>  >
> >>  > >
> >>  > > Thanks,
> >>  > > Brad.
> >>  > >
> >>  >
> >>  >  ----------------------------
> >>  >  IONA Technologies PLC (registered in Ireland)
> >>  >  Registered Number: 171387
> >>  >  Registered Address: The IONA Building, Shelbourne Road, Dublin 4,
> Ireland
> >>  >
> >>
>
> ----------------------------
> IONA Technologies PLC (registered in Ireland)
> Registered Number: 171387
> Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland
>
>

Re: @Path not mapping to required methods

Posted by Brad <br...@javawork.co.uk>.
Hi,

just to follow up from yesterday, I just wanted to clarify the regular
expression stuff.

Having stepped through the code in URITemplate.match the main point of
interest seems to be around line 122:

        Matcher m = templateRegexPattern.matcher(uri);
        if (!m.matches()) {
            return false;
        }

As far as I can tell, this is what compares the requested URI to those
declared for each method and therefore dictates what methods are
matched. Given my test class the values I'm seeing the following
variable values for the method readMessage:

(requested)uri:               "/"
template:                      "/{messageId}"
templateRegexPattern:  "/(.*?)(/.*)?"

Regex is not exactly my forte but from what I can tell this pattern
would match the template because it is effectively the "/" with zero
or more characters after it, potentially repeated one or more times.
Is that correct?

My expectation here is that it shouldn't match because the method
template specifies that the "/" has a variable "messageId" after it.
With this requirement in mind, shouldn't it be looking for one or more
characters after the "/" which would require the pattern "/(.+?)".
With the pattern set to "/(.*?)" it seems to me that there is no way
to differentiate between the template for listMail ("/") and the
template for readMail ("/{messageId}").

Apologies if I've got that fundamentally wrong. I don't think my
understanding of capturing groups is what it could be. It does seem to
be matching both of the method templates though.

Brad.

On Tue, May 6, 2008 at 5:36 PM, Brad <br...@javawork.co.uk> wrote:
> Hi Sergey,
>
>  yes listMail is added to the list of candidates.
>
>  https://issues.apache.org/jira/browse/CXF-1572
>
>  Brad.
>
>
>
>
>  On Tue, May 6, 2008 at 5:04 PM, Sergey Beryozkin
>  <se...@iona.com> wrote:
>  > Hi
>  >
>  >
>  >
>  > > Hi,
>  > >
>  > > I'm getting an issue where my @Path annotations aren't mapping to the
>  > > required URLs. Here's a rough outline of my test class:
>  > >
>  > > @Path(value="/{domain}/{network}/{user}/mail")
>  > > public class MailService {
>  > >
>  > > @GET
>  > > @ConsumeMime({"application/xml", "application/json"})
>  > > @ProduceMime({"application/xml", "application/json"})
>  > > public MailFolderDocument listMail(@PathParam("domain")String domain,
>  > > @PathParam("network")String network, @PathParam("user")String user,
>  > > @HeaderParam("token")String token){
>  > >           ....
>  > >       }
>  > >
>  > > @Path(value="/{messageId}", limited=true)
>  > > @GET
>  > > @ConsumeMime({"application/xml", "application/json"})
>  > > @ProduceMime({"application/xml", "application/json"})
>  > > public MessageDocument readMessage(@PathParam("user")String user,
>  > > @PathParam("messageId")String messageId, @HeaderParam("token")String
>  > > token){
>  > >           ....
>  > >       }
>  > > }
>  > >
>  > > The problem I'm seeing is that when i invoke the URL
>  > > http://localhost:8081/cxf/rest/test/domain/network/brad/mail, it
>  > > invokes the readMessage method instead of listMail. Am I using the
>  > > correct format for my annotations here?
>  > >
>  >
>  >  The annontations seem fine. Can you confirm please, as your're debugging,
>  > that listMail() is also added to the list of candidates ?
>  >  I'm actually not sure what exactly JAX_RS says in this regard, the only
>  > piece I can see is this one (section 3.6, 2.f) :
>  >
>  >  "Sort E using the number of literal characters in each member as the
>  > primary key (descending order), ..., number of capturing groups as the
>  > secondary key, and the source of each member ..."
>  >
>  >  In both cases it's a resource method, so the source is the same. Number of
>  > captuting groups for listMail is 3 as opposed to 2 for readEmail(), and the
>  > number of literal characters is different. It seems like only this bit of
>  > the specification which governs the dispatch in this case, but I''ll need to
>  > verify it...
>  >
>  >  One possible workaround is to
>  >
>  >  1. Have another root class created, but with slightly different Path.
>  >
>  >  In the end, I believe it's the CXF bug rather than the ambiguity of the
>  > JAX-RS spec...Can you please open a JIRA ?
>  >
>  >
>  >
>  >
>  >
>  > >
>  > > Anyway, just in case I have got it right (*pig flies by*) I stepped
>  > > through JAXRSUtils.findTargetMethod and I was left wondering if this
>  > > line is correct:
>  > >
>  > > private static final String URITEMPLATE_VARIABLE_REGEX = "(.*?)";
>  > >
>  > > I'm no regex expert but I did find this in the Java 1.5 API docs:
>  > >
>  > > X*?  X, zero or more times
>  > > X+? X, one or more times
>  > >
>  > > Would that value make more sense as "(.+?)" ?
>  > >
>  >
>  >  This is required by the spec, every template parameter is substituted by
>  > this reg expression. The rationale I believe is that it
>  >  makes it possible for a given method act as a subresource locator...
>  >
>  >  Cheers, Sergey
>  >
>  >
>  > >
>  > > Thanks,
>  > > Brad.
>  > >
>  >
>  >  ----------------------------
>  >  IONA Technologies PLC (registered in Ireland)
>  >  Registered Number: 171387
>  >  Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland
>  >
>

Re: @Path not mapping to required methods

Posted by Brad <br...@javawork.co.uk>.
Hi Sergey,

yes listMail is added to the list of candidates.

https://issues.apache.org/jira/browse/CXF-1572

Brad.


On Tue, May 6, 2008 at 5:04 PM, Sergey Beryozkin
<se...@iona.com> wrote:
> Hi
>
>
>
> > Hi,
> >
> > I'm getting an issue where my @Path annotations aren't mapping to the
> > required URLs. Here's a rough outline of my test class:
> >
> > @Path(value="/{domain}/{network}/{user}/mail")
> > public class MailService {
> >
> > @GET
> > @ConsumeMime({"application/xml", "application/json"})
> > @ProduceMime({"application/xml", "application/json"})
> > public MailFolderDocument listMail(@PathParam("domain")String domain,
> > @PathParam("network")String network, @PathParam("user")String user,
> > @HeaderParam("token")String token){
> >           ....
> >       }
> >
> > @Path(value="/{messageId}", limited=true)
> > @GET
> > @ConsumeMime({"application/xml", "application/json"})
> > @ProduceMime({"application/xml", "application/json"})
> > public MessageDocument readMessage(@PathParam("user")String user,
> > @PathParam("messageId")String messageId, @HeaderParam("token")String
> > token){
> >           ....
> >       }
> > }
> >
> > The problem I'm seeing is that when i invoke the URL
> > http://localhost:8081/cxf/rest/test/domain/network/brad/mail, it
> > invokes the readMessage method instead of listMail. Am I using the
> > correct format for my annotations here?
> >
>
>  The annontations seem fine. Can you confirm please, as your're debugging,
> that listMail() is also added to the list of candidates ?
>  I'm actually not sure what exactly JAX_RS says in this regard, the only
> piece I can see is this one (section 3.6, 2.f) :
>
>  "Sort E using the number of literal characters in each member as the
> primary key (descending order), ..., number of capturing groups as the
> secondary key, and the source of each member ..."
>
>  In both cases it's a resource method, so the source is the same. Number of
> captuting groups for listMail is 3 as opposed to 2 for readEmail(), and the
> number of literal characters is different. It seems like only this bit of
> the specification which governs the dispatch in this case, but I''ll need to
> verify it...
>
>  One possible workaround is to
>
>  1. Have another root class created, but with slightly different Path.
>
>  In the end, I believe it's the CXF bug rather than the ambiguity of the
> JAX-RS spec...Can you please open a JIRA ?
>
>
>
>
>
> >
> > Anyway, just in case I have got it right (*pig flies by*) I stepped
> > through JAXRSUtils.findTargetMethod and I was left wondering if this
> > line is correct:
> >
> > private static final String URITEMPLATE_VARIABLE_REGEX = "(.*?)";
> >
> > I'm no regex expert but I did find this in the Java 1.5 API docs:
> >
> > X*?  X, zero or more times
> > X+? X, one or more times
> >
> > Would that value make more sense as "(.+?)" ?
> >
>
>  This is required by the spec, every template parameter is substituted by
> this reg expression. The rationale I believe is that it
>  makes it possible for a given method act as a subresource locator...
>
>  Cheers, Sergey
>
>
> >
> > Thanks,
> > Brad.
> >
>
>  ----------------------------
>  IONA Technologies PLC (registered in Ireland)
>  Registered Number: 171387
>  Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland
>

Re: @Path not mapping to required methods

Posted by Sergey Beryozkin <se...@iona.com>.
Hi

> Hi,
>
> I'm getting an issue where my @Path annotations aren't mapping to the
> required URLs. Here's a rough outline of my test class:
>
> @Path(value="/{domain}/{network}/{user}/mail")
> public class MailService {
>
> @GET
> @ConsumeMime({"application/xml", "application/json"})
> @ProduceMime({"application/xml", "application/json"})
> public MailFolderDocument listMail(@PathParam("domain")String domain,
> @PathParam("network")String network, @PathParam("user")String user,
> @HeaderParam("token")String token){
>            ....
>        }
>
> @Path(value="/{messageId}", limited=true)
> @GET
> @ConsumeMime({"application/xml", "application/json"})
> @ProduceMime({"application/xml", "application/json"})
> public MessageDocument readMessage(@PathParam("user")String user,
> @PathParam("messageId")String messageId, @HeaderParam("token")String
> token){
>            ....
>        }
> }
>
> The problem I'm seeing is that when i invoke the URL
> http://localhost:8081/cxf/rest/test/domain/network/brad/mail, it
> invokes the readMessage method instead of listMail. Am I using the
> correct format for my annotations here?

The annontations seem fine. Can you confirm please, as your're debugging, that listMail() is also added to the list of candidates ?
I'm actually not sure what exactly JAX_RS says in this regard, the only piece I can see is this one (section 3.6, 2.f) :

"Sort E using the number of literal characters in each member as the primary key (descending order), ..., number of capturing groups 
as the secondary key, and the source of each member ..."

In both cases it's a resource method, so the source is the same. Number of captuting groups for listMail is 3 as opposed to 2 for 
readEmail(), and the number of literal characters is different. It seems like only this bit of the specification which governs the 
dispatch in this case, but I''ll need to verify it...

One possible workaround is to

1. Have another root class created, but with slightly different Path.

In the end, I believe it's the CXF bug rather than the ambiguity of the JAX-RS spec...Can you please open a JIRA ?



>
> Anyway, just in case I have got it right (*pig flies by*) I stepped
> through JAXRSUtils.findTargetMethod and I was left wondering if this
> line is correct:
>
> private static final String URITEMPLATE_VARIABLE_REGEX = "(.*?)";
>
> I'm no regex expert but I did find this in the Java 1.5 API docs:
>
> X*?  X, zero or more times
> X+? X, one or more times
>
> Would that value make more sense as "(.+?)" ?

This is required by the spec, every template parameter is substituted by this reg expression. The rationale I believe is that it
makes it possible for a given method act as a subresource locator...

Cheers, Sergey

>
> Thanks,
> Brad.

----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland