MrBackend
MrBackend

Reputation: 667

Jersey resource not found

Trying Jersey for the first time, I've quickly run into a problem that I can't figure out. I have two resources in the same package, following the same blueprint, but at runtime, Jersey only finds one of them. I have checked that both classes exist in the same folder in the jar included in the war.

Update: If I remove the @Path annotation on DashboardResource (effectively removing the resource), then DetailsResource suddenly comes to life. It seems like details is hidden by dashboard in some way.

In desperate need of some ideas of how to resolve this!

Facts and code

Versions: Jersey 2.4.1, Apache Tomcat 7.0.47

This one works fine:

package jerseytest;

import javax.ws.rs.*;

@Path("/dashboard")
public class DashboardResource {
  @GET
  @Produces("text/plain")
  public String getDashboard() { return "Dashboard"; }
}

This one gives me an HTTP 404:

package jerseytest;

import javax.ws.rs.*;

@Path("/details")
public class DetailsResource {
  @GET
  @Produces("text/plain")
  public String getDetails() { return "Details"; }
}

HTTP headers with Jersey tracing

http://localhost:8080/myservlet/dashboard:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Jersey-Tracing-000: START       [ ---- /  ---- ms |  ---- %] baseUri=[http://localhost:8080/myservlet/] requestUri=[http://localhost:8080/myservlet/dashboard] method=[GET] authScheme=[n/a] accept=[text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8] accept-encoding=[gzip,deflate,sdch] accept-charset=n/a accept-language=[en-US,en;q=0.8,da;q=0.6,nb;q=0.4,sv;q=0.2] content-type=n/a content-length=n/a
X-Jersey-Tracing-001: PRE-MATCH   [ 0,01 /  2,45 ms |  0,10 %] PreMatchRequest summary: 0 filters
X-Jersey-Tracing-002: MATCH       [ ---- /  2,90 ms |  ---- %] Matching path [/dashboard]
X-Jersey-Tracing-003: MATCH       [ ---- /  3,02 ms |  ---- %] Pattern [/dashboard(/)?] IS selected
X-Jersey-Tracing-004: MATCH       [ ---- /  3,38 ms |  ---- %] Matched resource: template=[/dashboard] regexp=[/dashboard(/.*)?] matches=[/dashboard] from=[/dashboard]
X-Jersey-Tracing-005: MATCH       [ ---- /  4,40 ms |  ---- %] Matched method  : public java.lang.String jerseytest.DashboardResource.getDashboard()
X-Jersey-Tracing-006: MATCH       [ ---- /  4,95 ms |  ---- %] Resource instance: [jerseytest.DashboardResource @5814b2a3]
X-Jersey-Tracing-007: MATCH       [ 2,63 /  5,17 ms | 30,68 %] RequestMatching summary
X-Jersey-Tracing-008: REQ-FILTER  [ 0,01 /  5,32 ms |  0,09 %] Request summary: 0 filters
X-Jersey-Tracing-009: INVOKE      [ 0,02 /  6,13 ms |  0,23 %] Resource [jerseytest.DashboardResource @5814b2a3] method=[public java.lang.String jerseytest.DashboardResource.getDashboard()]
X-Jersey-Tracing-010: INVOKE      [ ---- /  6,31 ms |  ---- %] Response: [org.glassfish.jersey.message.internal.OutboundJaxrsResponse @36dc1882 <200/SUCCESSFUL|OK|java.lang.String @66702fb1>]
X-Jersey-Tracing-011: RESP-FILTER [ 0,01 /  6,81 ms |  0,09 %] Response summary: 0 filters
X-Jersey-Tracing-012: WI          [ 0,01 /  7,12 ms |  0,08 %] [org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor @5e62c4bb #10] BEFORE context.proceed()
X-Jersey-Tracing-013: WI          [ 0,01 /  7,23 ms |  0,17 %] [org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor @26620166 #3000] BEFORE context.proceed()
X-Jersey-Tracing-014: MBW         [ ---- /  7,36 ms |  ---- %] Find MBW for type=[java.lang.String] genericType=[java.lang.String] mediaType=[[javax.ws.rs.core.MediaType @6c49e339]] annotations=[@javax.ws.rs.GET(), @javax.ws.rs.Produces(value=[text/plain])]
X-Jersey-Tracing-015: MBW         [ ---- /  7,60 ms |  ---- %] [org.glassfish.jersey.message.internal.StringMessageProvider @74e48049] IS writeable
X-Jersey-Tracing-016: MBW         [ 0,14 /  7,84 ms |  1,61 %] WriteTo by [org.glassfish.jersey.message.internal.StringMessageProvider @74e48049]
X-Jersey-Tracing-017: WI          [ 0,00 /  7,94 ms |  0,04 %] [org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor @26620166 #3000] AFTER context.proceed()
X-Jersey-Tracing-018: WI          [ 0,01 /  8,39 ms |  0,08 %] [org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor @5e62c4bb #10] AFTER context.proceed()
X-Jersey-Tracing-019: WI          [ 1,38 /  8,48 ms | 16,11 %] WriteTo summary: 2 interceptors
X-Jersey-Tracing-020: FINISHED    [ ---- /  8,56 ms |  ---- %] Response status: 200/SUCCESSFUL|OK
Content-Type: text/plain
Content-Length: 10
Date: Thu, 19 Dec 2013 16:18:03 GMT

http://localhost:8080/myservlet/details:

HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
X-Jersey-Tracing-000: START       [ ---- /  ---- ms |  ---- %] baseUri=[http://localhost:8080/myservlet/] requestUri=[http://localhost:8080/myservlet/details] method=[GET] authScheme=[n/a] accept=[text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8] accept-encoding=[gzip,deflate,sdch] accept-charset=n/a accept-language=[en-US,en;q=0.8,da;q=0.6,nb;q=0.4,sv;q=0.2] content-type=n/a content-length=n/a
X-Jersey-Tracing-001: PRE-MATCH   [ 0,01 /  3,74 ms |  0,20 %] PreMatchRequest summary: 0 filters
X-Jersey-Tracing-002: MATCH       [ ---- /  4,25 ms |  ---- %] Matching path [/details]
X-Jersey-Tracing-003: MATCH       [ 0,54 /  4,39 ms | 10,19 %] RequestMatching summary
X-Jersey-Tracing-004: RESP-FILTER [ 0,01 /  5,18 ms |  0,13 %] Response summary: 0 filters
X-Jersey-Tracing-005: FINISHED    [ ---- /  5,28 ms |  ---- %] Response status: 404/CLIENT_ERROR|Not Found
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 967
Date: Thu, 19 Dec 2013 16:18:47 GMT

web.xml:

<web-app version="3.0"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">

    <display-name>My Web App</display-name>

    <servlet>
        <display-name>My Servlet</display-name>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>jerseytest</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.tracing</param-name>
            <param-value>ALL</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

Jersey deployment log:

...
[2013-12-20 10:38:03,986] Artifact jerseytest-war:war: Artifact is being deployed, please wait...
Connected to server
des 20, 2013 10:38:06 AM org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer addServletWithDefaultConfiguration
INFO: Registering the Jersey servlet application, named javax.ws.rs.core.Application, with the following root resource and provider classes: [class jerseytest.DashboardResource, class org.glassfish.jersey.server.wadl.internal.WadlResource, class jerseytest.DetailsResource, class org.glassfish.jersey.client.filter.HttpDigestAuthFilter]
des 20, 2013 10:38:06 AM org.glassfish.jersey.server.ApplicationHandler initialize
INFO: Initiating Jersey application, version Jersey: 2.4.1 2013-11-08 12:08:47...
[2013-12-20 10:38:07,184] Artifact jerseytest-war:war: Artifact is deployed successfully
...

Upvotes: 0

Views: 9458

Answers (2)

MrBackend
MrBackend

Reputation: 667

After a considerable amount of digging, I found that the problem is that I have my resource classes in a jar inside a war. This hits a bug in Jersey 2.4.1, which is fixed in 2.5.

Upvotes: 2

harsh
harsh

Reputation: 7692

In all probability seems like DetailsResource is not found by Jersey container, open the war and check under classes or lib\jars if DetailsResource is actually deployed.

Update:

In your Jersey configuration, what's happening is that only one resource is getting registered (which I assume as root-resource). That also explain why details worked after removing dashboard.

I think you can try adding first root-resource which can have @Path("/") or @Path("v1") (where v1 corresponds to version number, just for example). Now this root-resource will link all available resources:

@Component
@Path("/")
public class BaseResource
{
    @Autowired //if using spring and interfaces for resource, else set it via setter/constructor
    private DashboardResource dashboardResource;

    @Autowired //if using spring and interfaces for resource, else set it via setter/constructor
    private DetailsResource detailsResource;

    @Path("dashboard")
    public DashboardResource getDashboardResource()
    {
        return dashboardResource;
    }

    @Path("details")
    public DetailsResource getDetailsResource()
    {
        return detailsResource;
    }
}

Remember to remove @Path annotation from details and dashboad resource classes.

Upvotes: 1

Related Questions