Debugging REST POSTs with Tomcat and Jersey

Øyvind Wergeland
Shark Bytes
Published in
2 min readJul 3, 2018
“A macro shot of a Macbook Pro screen with a few dozen lines of code” by Luca Bravo on Unsplash

We use Jersey in Apache Tomcat as a REST framework. Most of the time, we have full control of the client, as it usually is implemented by our front-end team. However, we have a few services that are consumed by our customers. When extending one of these services, occasionally we found that we were unable to parse the incoming data, and also unable to debug the inbound messages.

The first element that made debugging hard, was that we use DTOs to map inbound JSON messages. If any one of the fields failed to map it was silently set to null in the DTO with no traceable error message. The second element was that we were running in Tomcat, which has a custom log configuration. Note that Tomcat is implemented with Apache Commons Logging (ACL), but a special version hard coded to use java.util.logging framework (JUL). This is the same logging framework that Jersey uses.

We had configured Tomcat to use log4j for its own logging, using the extras module. However, this leads to two further issues: log4j is available for the webapp, and any library that uses ACL will most likely log with log4j. Any library outside Tomcat (seemingly, org.apache.catalina) using JUL, will not be directed to log4j. This may be possible by using the Log4J JUL Adpater and setting LOGGING_MANAGER=org.apache.logging.log4j.jul.LogManager. If you do this, make sure that log4j-jul.jar is on the CLASSPATH used by catalina.sh / catalina.bat. If you are running under a SecurityManager, you also need to update catalina.policy. Note that the Log4j JUL Adapter is not aware of the different webapp contexts.

I was not successful in the approach above, and as I only needed to set up one logger to debug, I ended up with just configuring JUL and the Jersey logging feature instead.

Configuring JUL and the Jersey logging feature

Enable and configure LoggingFeature. If configuring Jersey in web.xml:

<servlet>
<servlet-name>rest-ws</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
...
org.glassfish.jersey.logging.LoggingFeature
</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.trace</param-name>
<param-value>ALL</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.logging.verbosity</param-name>
<param-value>PAYLOAD_TEXT</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Add to $CATALINA_BASE/conf/logging.properties:

handlers = java.util.logging.FileHandler
java.util.logging.FileHandler.pattern=/absolulute/path/to/logs/jersey.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s
org.glassfish.jersey.logging.LoggingFeature.handlers = java.util.logging.FileHandler
org.glassfish.jersey.logging.LoggingFeature.level = FINE

Note that it is crucial to define all handlers in the handlersproperty as well as to reference it from the logger (<classname>.handler). You will now get all headers and payloads of requests and responses in jersey.log.

If anybody has a better approach on how to redirect JUL to log4j in Tomcat, I am very keen to get your comment on this article!

--

--

Øyvind Wergeland
Shark Bytes

Director of Engineering at Exabel AS, former CTO of OMS. Still getting code dirt under my fingernails.