users@jersey.java.net

Re: [Jersey] Trailing slash redirect

From: Chris Carrier <ctcarrier_at_gmail.com>
Date: Thu, 11 Feb 2010 10:20:08 -0800

OK I turned those on and got a bit more logging. Not sure if it'll be
very helpful. So this is with FEATURE_REDIRECT set to true and a path
on my GET like:

@GET
@Path("/{id}/")

It's weird looking because it seems to forward correctly to add a
slash at the end but still returns a 404. I can send another trace
with redirect turned off and no slash at the end of my Path if you
want. It's funny if I have the start at the end of the Path the
output looks very similar except no exception. It just adds the slash
to the end and then finds my endpoint.


Feb 11, 2010 10:09:27 AM
com.sun.jersey.spi.spring.container.servlet.SpringServlet getContext
INFO: Using default applicationContext
Feb 11, 2010 10:09:27 AM
com.sun.jersey.spi.spring.container.SpringComponentProviderFactory
register
INFO: Registering Spring bean, jaxbContextResolver, of type
com.something.config.JaxbContextResolver as a provider class
Feb 11, 2010 10:09:27 AM
com.sun.jersey.spi.spring.container.SpringComponentProviderFactory
register
INFO: Registering Spring bean, somethingExceptionMapper, of type
com.something.config.SomethingExceptionMapper as a provider class
Feb 11, 2010 10:09:27 AM
com.sun.jersey.spi.spring.container.SpringComponentProviderFactory
register
INFO: Registering Spring bean, somethingLinkEndpoint, of type
com.something.something.SomethingLinkEndpoint as a root resource class
Feb 11, 2010 10:09:27 AM
com.sun.jersey.spi.spring.container.SpringComponentProviderFactory
register
INFO: Registering Spring bean, followSomethingEndpoint, of type
com.something.something.FollowSomethingEndpoint as a root resource
class
Feb 11, 2010 10:09:27 AM
com.sun.jersey.spi.spring.container.SpringComponentProviderFactory
register
INFO: Registering Spring bean, somethingSomethingEndpoint, of type
com.something.something.SomethingSomethingEndpoint as a root resource
class
Feb 11, 2010 10:09:27 AM
com.sun.jersey.spi.spring.container.SpringComponentProviderFactory
register
INFO: Registering Spring bean, followSomethingEndpoint, of type
com.something.something.FollowSomethingFastEndpoint as a root resource
class
Feb 11, 2010 10:09:27 AM
com.sun.jersey.server.impl.application.WebApplicationImpl initiate
INFO: Initiating Jersey application, version 'Jersey: 1.1.5 01/20/2010 04:04 PM'
2010-02-11 10:09:27,682 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:214 Returning
cached instance of singleton bean 'jaxbContextResolver'
2010-02-11 10:09:27,758 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:214 Returning
cached instance of singleton bean 'somethingExceptionMapper'
Feb 11, 2010 10:09:28 AM
com.sun.jersey.core.spi.component.ProviderServices getInstances
SEVERE: The class true could not be found. This class is ignored.
Feb 11, 2010 10:09:28 AM
com.sun.jersey.core.spi.component.ProviderServices getInstances
SEVERE: The class true could not be found. This class is ignored.
2010-02-11 10:09:28,391 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:214 Returning
cached instance of singleton bean 'somethingLinkEndpoint'
2010-02-11 10:09:28,395 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:214 Returning
cached instance of singleton bean 'followSomethingEndpoint'
2010-02-11 10:09:28,397 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:214 Returning
cached instance of singleton bean 'somethingSomethingEndpoint'
2010-02-11 10:09:28,399 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:214 Returning
cached instance of singleton bean 'followSomethingEndpoint'
3937 [main] INFO org.mortbay.log - Started SocketConnector_at_0.0.0.0:8050
2010-02-11 10:09:32,733 DEBUG org.springframework.web.context.request.RequestContextListener:69 Bound
request context to thread: GET
/something/something-link/1.0/json/rK3dgK0g5 HTTP/1.1
Host: admin.localhost:8050
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.0-beta2 (java 1.5)


2010-02-11 10:09:32,736 DEBUG org.springframework.web.context.request.RequestContextListener:89 Cleared
thread-bound request context: GET
/something/something-link/1.0/json/rK3dgK0g5 HTTP/1.1
Host: admin.localhost:8050
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.0-beta2 (java 1.5)


2010-02-11 10:09:32,743 DEBUG org.springframework.web.context.request.RequestContextListener:69 Bound
request context to thread: GET
/something/something-link/1.0/json/rK3dgK0g5/ HTTP/1.1
Host: admin.localhost:8050
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.0-beta2 (java 1.5)


Feb 11, 2010 10:09:32 AM
com.sun.jersey.spi.container.ContainerResponse traceException
INFO: Mapped exception to response: 404 (Not Found)
com.sun.jersey.api.NotFoundException
        at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:991)
        at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:941)
        at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:932)
        at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:384)
        at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:451)
        at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:632)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:380)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:324)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
        at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:865)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
        at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
        at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)
2010-02-11 10:09:32,905 DEBUG org.springframework.web.context.request.RequestContextListener:89 Cleared
thread-bound request context: GET
/something/something-link/1.0/json/rK3dgK0g5/ HTTP/1.1
Host: admin.localhost:8050
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.0-beta2 (java 1.5)


On Thu, Feb 11, 2010 at 9:52 AM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
> Hi Chris,
>
> Two things to help throw more light on this issue:
>
> 1) Set tracing to true:
>
> https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/core/ResourceConfig.html#FEATURE_TRACE
>
> 2) Set request and response logging on:
>
> https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/container/filter/LoggingFilter.html
>
> Feel free to send the output privately if public disclosure is an issue.
> And, if i still cannot work out what is wrong from the logging output then a
> reproducible test case will be most appreciated so i can better work out
> what is going wrong.
>
>
> On Feb 11, 2010, at 6:44 PM, Chris Carrier wrote:
>
>> My Jersey dependencies are:
>>
>> <!--Jersey-->
>>       <dependency>
>>           <groupId>com.sun.jersey</groupId>
>>           <artifactId>jersey-bundle</artifactId>
>>           <version>1.1.5</version>
>>       </dependency>
>>       <dependency>
>>           <groupId>com.sun.jersey.contribs</groupId>
>>           <artifactId>jersey-spring</artifactId>
>>           <version>1.1.5</version>
>>       </dependency>
>>
>> I'm using the bundle dependency because of issues I ran into with the
>> META-INF/services directory clashing across dependencies (I could also
>> fix this with the Maven shade plugin i think).
>
> Correct, and make sure you use the ServicesResourceTransformer to merge
> META-INF service files.
>
> Paul.
>
>>  When I remove the star
>> I am left with a class level Path that looks like:
>>
>> @Path("/some/path/{version}/json/")
>>
>> And my GET like:
>>
>> @GET
>> @Path("/{id}/")
>>
>> But my tests then fail.  And if i try without trailing slash redirect
>> with a path like:
>>
>> @GET
>> @Path("/{id}")
>>
>> They also fail.  The only way I can get GETs without trailing slashes
>> to work is with the path i mentioned before:
>>
>> @GET
>> @Path("/{id}/*")
>>
>> And trailing slash redirect turned on.
>>
>> Chris
>>
>> On Thu, Feb 11, 2010 at 9:31 AM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>>>
>>> On Feb 11, 2010, at 6:06 PM, Chris Carrier wrote:
>>>
>>>> I seemed to have found a solution by messing with my Path.  If I
>>>> annotate my GETs with a Path like:
>>>>
>>>> @Path("/{key}/*")
>>>>
>>>> Where before i just had:
>>>>
>>>> @Path("/{key}")
>>>>
>>>
>>> Not sure what is going on here as the '*' character should be considered
>>> a
>>> literal character that is part of the path and should not have the same
>>> syntax as that defined for regular expressions. Although that could be a
>>> bug
>>> in the template to regex convertor...
>>>
>>> It would help if i knew what version of Jersey you are using.
>>>
>>> In any case the @Path("/{key}/") should work as documented when
>>> FEATURE_REDIRECT is declared:
>>>
>>>
>>> https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/core/ResourceConfig.html#FEATURE_REDIRECT
>>>
>>> And if that value is false and you have @Path("/{key}") then it should
>>> match
>>> with or without a '/' present at the end of the request URL path.
>>>
>>>
>>>> It works.  I'm not sure why i need the star at the end but that seems
>>>> to fix it.  Is that expected behavior?
>>>
>>> No.
>>>
>>>
>>>
>>>> As for the POST issue it must
>>>> be my client.  I'm using Wiztools (Rest Client) from google tools.  It
>>>> must auto redirect even on POSTs.
>>>>
>>>
>>> OK.
>>>
>>>
>>>> It would be ideal if I didn't have this 'magic" path pattern but as
>>>> long as it works I don't have too much to complain about.  If you
>>>> still want to see a project that shows this behavior I could pretty
>>>> easily strip down our code to a simple endpoint and test and send it
>>>> over.
>>>>
>>>
>>> If it is something that does not take a lot of time for you to do then it
>>> would be most helpful as there might be a bug or two lurking here.
>>>
>>> Paul.
>>>
>>>
>>>> Chris
>>>>
>>>> On Thu, Feb 11, 2010 at 12:48 AM, Paul Sandoz <Paul.Sandoz_at_sun.com>
>>>> wrote:
>>>>>
>>>>> Hi Chris,
>>>>>
>>>>> What version of Jersey are you using?
>>>>>
>>>>> The latest version of Jersey will work with or without a trailing '/'
>>>>> but
>>>>> by
>>>>> default no redirection will be performed. And you can enabled
>>>>> redirection
>>>>> as
>>>>> you have done with the FEATURE_REDIRECT property.
>>>>>
>>>>> I think there may be something wrong with your configuration. It is
>>>>> hard
>>>>> to
>>>>> tell with Jetty, Spring and Jersey in the mix what exactly is going
>>>>> wrong.
>>>>> Plus i do not know what client you are using.
>>>>>
>>>>> Note that redirection on temporary redirect responses are only meant to
>>>>> happen for GET and HEAD, not POST:
>>>>>
>>>>> http://greenbytes.de/tech/webdav/rfc2616.html#status.307
>>>>>
>>>>>  If the 307 status code is received in response to a request other than
>>>>> GET
>>>>> or HEAD, the user agent MUST NOT
>>>>>  automatically redirect the request unless it can be confirmed by the
>>>>> user,
>>>>> since this might change the conditions
>>>>>  under which the request was issued.
>>>>>
>>>>> Would it be possible to send me (privately if public disclosure is an
>>>>> issue)
>>>>> a maven-based project that reproduces the issue?
>>>>>
>>>>> Paul.
>>>>>
>>>>> On Feb 10, 2010, at 8:55 PM, Chris Carrier wrote:
>>>>>
>>>>>> Hi folks,
>>>>>>
>>>>>> I've seen this topic mentioned in the archive but I am having trouble
>>>>>> getting it to work.  It's a pretty annoying problem.  I just want all
>>>>>> my calls to work whether they have a trailing slash or not.  In this
>>>>>> project we're using embedded Jetty that is being programatically
>>>>>> configured.  So in that code I added:
>>>>>>
>>>>>> Servlet servlet = new SpringServlet();
>>>>>> ServletHolder holder = new ServletHolder(servlet);
>>>>>>
>>>>>> Map initParams = new HashMap();
>>>>>> initParams.put(ResourceConfig.FEATURE_REDIRECT, "true");
>>>>>> holder.setInitParameters(initParams);
>>>>>>
>>>>>> But this seems to cause pretty unpredictable behavior.  For instance
>>>>>> after I added that I tried making a POST to my endpoint which has a
>>>>>> method annotated as @POST but I get a 400 response.  And the weird
>>>>>> thing is the debug log shows:
>>>>>>
>>>>>> 2010-02-10 11:40:03,382 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:69
>>>>>>  Bound
>>>>>> request context to thread: POST /some/path HTTP/1.1
>>>>>> ...
>>>>>>
>>>>>> 2010-02-10 11:40:03,383 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:89
>>>>>>  Cleared
>>>>>> thread-bound request context: POST /some/path HTTP/1.1
>>>>>> ...
>>>>>>
>>>>>> 2010-02-10 11:40:03,384 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:69
>>>>>>  Bound
>>>>>> request context to thread: GET /some/path/ HTTP/1.1
>>>>>> ...
>>>>>>
>>>>>> 2010-02-10 11:40:03,385 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:89
>>>>>>  Cleared
>>>>>> thread-bound request context: GET /some/path/ HTTP/1.1
>>>>>> ...
>>>>>>
>>>>>> There isn't a GET call being made.  It's like the POST is getting
>>>>>> turned into a GET for some reason.  This doesn't happen when i don't
>>>>>> have the redirect on.  Does the trailing slash thing only apply to
>>>>>> GETs?  If that's the case shouldn't it just ignore my POST?  If i have
>>>>>> a trailing slash in the original call it works fine.
>>>>>>
>>>>>> Aside from that the redirect doesn't even work for my GETs.  When i
>>>>>> try a GET without a trailing slash I get:
>>>>>>
>>>>>> 2010-02-10 11:47:15,344 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:69
>>>>>>  Bound
>>>>>> request context to thread: GET  /some/path/c4e713e HTTP/1.1
>>>>>>
>>>>>> 2010-02-10 11:47:15,346 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:89
>>>>>>  Cleared
>>>>>> thread-bound request context: GET  /some/path/c4e713e HTTP/1.1
>>>>>>
>>>>>> 2010-02-10 11:47:15,359 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:69
>>>>>>  Bound
>>>>>> request context to thread: GET  /some/path/c4e713e/ HTTP/1.1
>>>>>>
>>>>>> 2010-02-10 11:47:15,440 DEBUG
>>>>>> org.springframework.web.context.request.RequestContextListener:89
>>>>>>  Cleared
>>>>>> thread-bound request context: GET /some/path/c4e713e/ HTTP/1.1
>>>>>>
>>>>>> Which looks like it's redirecting properly but then it returns a 404.
>>>>>> In this case it doesn't matter whether i have a trailing slash on the
>>>>>> original call or not it always returns a 404.  Even though I have a
>>>>>> GET annotated class and I've tried various combinations for the path:
>>>>>>
>>>>>> @GET
>>>>>> @Path("/{id}/")
>>>>>>
>>>>>> @GET
>>>>>> @Path("/{id}")
>>>>>>
>>>>>> Is there something I'm missing here?  For my main Path i've tried:
>>>>>>
>>>>>> @Path("/some/path/")
>>>>>> @Path("/some/path")
>>>>>> @Path("/some/path*")
>>>>>>
>>>>>> And probably some others.
>>>>>>
>>>>>> Any ideas?
>>>>>>
>>>>>> Thanks!
>>>>>> Chris
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>