Jersey Logging Request and Response Entities using Filter

By default, Jersey uses JUL for logging – and does not print request/response entity bodies in logs. To print entity content, you must create your own LoggingFiler, and register it in place of default org.glassfish.jersey.filter.LoggingFilter. In this example, I am creating one such basic CustomLoggingFilter which extends org.glassfish.jersey.filter.LoggingFilter and implements ContainerRequestFilter and ContainerResponseFilter interfaces so that it can intercept the ongoing requests and responses.

Table of Contents

Create CustomLoggingFilter
Register CustomLoggingFilter
Log statements with default LoggingFilter 
Log statements with CustomLoggingFilter

Create CustomLoggingFilter

Let’s go straight to custom logging filter class for this jersey demo.

package com.howtodoinjava.jersey.provider;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;

import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.message.internal.ReaderWriter;

public class CustomLoggingFilter extends LoggingFilter implements ContainerRequestFilter, ContainerResponseFilter 
{
	@Override
	public void filter(ContainerRequestContext requestContext)	throws IOException 
	{
		StringBuilder sb = new StringBuilder();
		sb.append("User: ").append(requestContext.getSecurityContext().getUserPrincipal() == null ? "unknown"
						: requestContext.getSecurityContext().getUserPrincipal());
		sb.append(" - Path: ").append(requestContext.getUriInfo().getPath());
		sb.append(" - Header: ").append(requestContext.getHeaders());
		sb.append(" - Entity: ").append(getEntityBody(requestContext));
		System.out.println("HTTP REQUEST : " + sb.toString());
	}

	private String getEntityBody(ContainerRequestContext requestContext) 
	{
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		InputStream in = requestContext.getEntityStream();
		
		final StringBuilder b = new StringBuilder();
		try 
		{
			ReaderWriter.writeTo(in, out);

			byte[] requestEntity = out.toByteArray();
			if (requestEntity.length == 0)
			{
				b.append("").append("\n");
			}
			else
			{
				b.append(new String(requestEntity)).append("\n");
			}
			requestContext.setEntityStream( new ByteArrayInputStream(requestEntity) );

		} catch (IOException ex) {
			//Handle logging error
		}
		return b.toString();
	}

	@Override
	public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException 
	{
		StringBuilder sb = new StringBuilder();
		sb.append("Header: ").append(responseContext.getHeaders());
		sb.append(" - Entity: ").append(responseContext.getEntity());
		System.out.println("HTTP RESPONSE : " + sb.toString());
	}
}

Register CustomLoggingFilter

To register this CustomLoggingFilter, register in this way.

package com.howtodoinjava.jersey;

import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;

import com.howtodoinjava.jersey.provider.CustomLoggingFilter;

public class CustomApplication extends ResourceConfig 
{
	public CustomApplication() 
	{
		packages("com.howtodoinjava.jersey");
		register(JacksonFeature.class);

		register(CustomLoggingFilter.class);
	}
}

Log statements with default LoggingFilter

Now if you try to use any existing REST API without CustomLoggingFilter, logs will appear in this way.

Request

Jersey-custom-logging

Logs

Sep 30, 2015 6:18:41 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Server has received a request on thread http-bio-8080-exec-4
1 > POST http://localhost:8080/JerseyDemos/rest/employees
1 > accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
1 > accept-encoding: gzip, deflate
1 > accept-language: null
1 > cache-control: no-cache
1 > connection: keep-alive
1 > content-length: 35
1 > content-type: application/json; charset=UTF-8
1 > host: localhost:8080
1 > pragma: no-cache
1 > user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0

Sep 30, 2015 6:18:41 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Server responded with a response on thread http-bio-8080-exec-4
1 < 200
1 < Content-Type: application/json

Log statements with CustomLoggingFilter

After adding CustomLoggingFilter, you will get much better logs like below.

HTTP REQUEST : User: unknown - Path: employees - Header: {host=[localhost:8080], user-agent=[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0], accept=, accept-language=[null], accept-encoding=[gzip, deflate], content-type=[application/json; charset=UTF-8], content-length=[35], connection=[keep-alive], pragma=[no-cache], cache-control=[no-cache]} - Entity: {"id":2,"name":"Alex Kolenchiskey"}

HTTP RESPONSE : Header: {Content-Type=[application/json]} - Entity: Employee [id=2, name=Alex Kolenchiskey]
Please feel free to add/remove information from log statements as per your need. There is plenty of other useful information you may add in these logs.

Happy Learning !!

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

7 thoughts on “Jersey Logging Request and Response Entities using Filter”

    •  InputStream inputStream = response.readEntity(InputStream.class); // use raw InputStream to ignore Content-Type when parsing
      
      String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
      
      Reply
    • When I wrote the example, 2.19 was latest available Jersey version.

      &lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
      	xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd;
      	&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
      	&lt;groupId&gt;com.howtodoinjava.jersey&lt;/groupId&gt;
      	&lt;artifactId&gt;JerseyDemos&lt;/artifactId&gt;
      	&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
      	&lt;packaging&gt;war&lt;/packaging&gt;
      	&lt;repositories&gt;
      		&lt;repository&gt;
      			&lt;id&gt;maven2-repository.java.net&lt;/id&gt;
      			&lt;name&gt;Java.net Repository for Maven&lt;/name&gt;
      			&lt;url&gt;http://download.java.net/maven/2/&lt;/url&gt;
      			&lt;layout&gt;default&lt;/layout&gt;
      		&lt;/repository&gt;
      	&lt;/repositories&gt;
      	&lt;properties&gt;
      		&lt;jersey2.version&gt;2.19&lt;/jersey2.version&gt;
      		&lt;jaxrs.version&gt;2.0.1&lt;/jaxrs.version&gt;
      	&lt;/properties&gt;
      	&lt;dependencies&gt;
      		&lt;!-- JAX-RS --&gt;
      		&lt;dependency&gt;
      			&lt;groupId&gt;javax.ws.rs&lt;/groupId&gt;
      			&lt;artifactId&gt;javax.ws.rs-api&lt;/artifactId&gt;
      			&lt;version&gt;${jaxrs.version}&lt;/version&gt;
      		&lt;/dependency&gt;
      		&lt;!-- Jersey 2.19 --&gt;
      		&lt;dependency&gt;
      			&lt;groupId&gt;org.glassfish.jersey.containers&lt;/groupId&gt;
      			&lt;artifactId&gt;jersey-container-servlet&lt;/artifactId&gt;
      			&lt;version&gt;${jersey2.version}&lt;/version&gt;
      		&lt;/dependency&gt;
      		&lt;dependency&gt;
      			&lt;groupId&gt;org.glassfish.jersey.core&lt;/groupId&gt;
      			&lt;artifactId&gt;jersey-server&lt;/artifactId&gt;
      			&lt;version&gt;${jersey2.version}&lt;/version&gt;
      		&lt;/dependency&gt;
      		&lt;dependency&gt;
      			&lt;groupId&gt;org.glassfish.jersey.core&lt;/groupId&gt;
      			&lt;artifactId&gt;jersey-client&lt;/artifactId&gt;
      			&lt;version&gt;${jersey2.version}&lt;/version&gt;
      		&lt;/dependency&gt;
      		&lt;dependency&gt;
      			&lt;groupId&gt;org.glassfish.jersey.media&lt;/groupId&gt;
      			&lt;artifactId&gt;jersey-media-json-jackson&lt;/artifactId&gt;
      			&lt;version&gt;${jersey2.version}&lt;/version&gt;
      		&lt;/dependency&gt;
      	&lt;/dependencies&gt;
      	&lt;build&gt;
      		&lt;finalName&gt;JerseyDemos&lt;/finalName&gt;
      		&lt;plugins&gt;
      			&lt;plugin&gt;
      				&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
      				&lt;configuration&gt;
      					&lt;source&gt;1.7&lt;/source&gt;
      					&lt;target&gt;1.7&lt;/target&gt;
      				&lt;/configuration&gt;
      			&lt;/plugin&gt;
      		&lt;/plugins&gt;
      	&lt;/build&gt;
      &lt;/project&gt;
      
      Reply
  1. what version of jersey are you using for this example?.
    LoggerFilter is a final class, So we can not extend this filter for custom logging.. I am using the jersey version 2.21.

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.