Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!

Jakub is a Java EE developer since 2005 and occasionally a project manager, working currently with Iterate AS. He's highly interested in developer productivity (and tools like Maven and AOP/AspectJ), web frameworks, Java portals, testing and performance and works a lot with IBM technologies. A native to Czech Republic, he lives now in Oslo, Norway. Jakub is a DZone MVB and is not an employee of DZone and has posted 90 posts at DZone. You can read more from them at their website. View Full User Profile

Troubleshooting Jersey REST Server and Client

02.07.2012
Email
Views: 2110
  • submit to reddit

The logging in Jersey, the reference JAX-RS implementation, is little sub-optimal. For example if it cannot find a method producing the expected MIME type then it will return “Unsupported mime type” to the client but won’t log anything (which mime type was requested, which mime types are actually available, …).  Debugging it isn’t exactly easy either, so what to do?

Well, I don’t know the ultimate solution but want to share few tips.

Enable Tracing of Request Matching

Jersey since version 1.1.5 supports request matching tracing, provided somehow detailed information about the matching process in the response headers.

To enable it for the Jersey Test framework you’d do something like this in your test class:

public class MyJerseyTest extends JerseyTest {

    public MyJerseyTest() {
        super(new WebAppDescriptor
                .Builder("my.package.with.jaxrs.resources")
                .contextPath("myCtxPath")
                .servletPath("/myServletPath")
                .initParam("com.sun.jersey.config.feature.Trace", "true")
                .build());
    }

    // Your test methods here ...; you can get the trace headers via ClientResponse#getHeaders()
}

To enable it for the server itself (though might be not such a good idea to enable this in production), you would set it in web.xml:

<web-app  ...>
    <servlet>
        <servlet-name>Jersey REST Service for value codes</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        ...
        <init-param>
            <param-name>com.sun.jersey.config.feature.Trace</param-name>
            <param-value>true</param-value>
        </init-param>

    </servlet>
...
</web-app>

The headers, which you can obtain via e.g. curl -i or via ClientResponse#getHeaders(), might look like this:

{X-Jersey-Trace-008=[mapped exception to response: javax.ws.rs.WebApplicationException@56f9659d -> 415 (Unsupported Media Type)],
X-Jersey-Trace-002=[accept right hand path java.util.regex.Matcher[pattern=/myResource/([-0-9a-zA-Z_]+)(/.*)? region=0,17 lastmatch=/myResource/23/mySubresources]: "/myResource/23/mySubresources" -> "/myResource/23" : "/mySubresources"],
X-Jersey-Trace-003=[accept resource: "myResource/23" -> @Path("/myResource/{item: [-0-9a-zA-Z_]+}") com.example.MyExampleResource@41babddb],
X-Jersey-Trace-000=[accept root resource classes: "/myResource/23/mySubresources"],
X-Jersey-Trace-001=[match path "/myResource/23/mySubresources" -> "/application\.wadl(/.*)?", "/myResource/([-0-9a-zA-Z_]+)(/.*)?", "/myResource(/.*)?", "/mySubresources/([-0-9a-zA-Z_]+)(/.*)?"],
X-Jersey-Trace-006=[accept sub-resource methods: "myResource/23" : "/mySubresources", GET -> com.example.MyExampleResource@41babddb],
X-Jersey-Trace-007=[accept termination (matching failure): "/mySubresources"],
X-Jersey-Trace-004=[match path "/mySubresources" -> "/mySubresources(/)?", ""],
X-Jersey-Trace-005=[accept right hand path java.util.regex.Matcher[pattern=/mySubresources(/)? region=0,6 lastmatch=/mySubresources]: "/mySubresources" -> "/mySubresources" : ""]
, Transfer-Encoding=[chunked], Date=[Tue, 31 Jan 2012 14:48:26 GMT], server=[grizzly/2.1.2], Content-Type=[text/html; charset=iso-8859-1]}

provided that you have the class com.example.MyExampleResource annotated with @Path("/myResource/{item: [-0-9a-zA-Z_]+}") and a method annotated with @GET @Path("mySubresources") (and the class field @PathParam("item") Long item).

As you can see, there is still no info regarding accepted/supported MIME types.

Get Detailed Logging Into a File

Jersey uses Java logging, which is know for being difficult to configure. Here is a dirty trick to get detailed Jersey logs into a file:

public class MyJerseyTest extends JerseyTest {

    @BeforeClass public static void setupJerseyLog() throws Exception {
        Handler fh = new FileHandler("/tmp/jersey_test.log");
        Logger.getLogger("").addHandler(fh);
        Logger.getLogger("com.sun.jersey").setLevel(Level.FINEST);
    }

    // Your test methods here ...
}

Notice that even thoug the log level is ALL, the logs still might be quite useless to troubleshoot some problems (such s the unsupported MIME type).

Configure Request/Response Logging Filters

Jersey provides a LoggingFilter that can be used to log request/response entities and it can be installed both into the server and the client. The com.sun.jersey.api.container.filter.LoggingFilter may be installed into the server via init-params, the com.sun.jersey.api.client.filter.LoggingFilter may be installed into the client via client.addFilter. JerseyTest automatically installs the LoggingFilter into the client it uses if the system property “enableLogging” is set (to whatever).

 

From http://theholyjava.wordpress.com/2012/01/31/troubleshooting-jersey-rest-server-and-client/

Tags:
Published at DZone with permission of Jakub Holý, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)