0

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 ... 

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

5 Comments

They're both in the war, as stated. I'll check if rhey're both deployed, but I've never come across that kind of partially successful deployment before.
Can you check the server startup logs, Jersey usually prints mapping of path to resources on startup..
Right now, there is no log from Jersey in the startup log, only from Tomcat that the war is deployed. I'll check how to get Jersey to log resource mappings.
I updated the web.xml to use Servlet 3.0 spec, then all root resources are logged on deployment. DetailsResource is found, but still not matched at runtime. (OP is updated)
Your help was much appreciated! Though the problem turned out to be a Jersey bug (see own answer)...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.