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

Comments

Subscribe
Notify of
guest
7 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode