Custom Reason Phrase in HTTP status error message response with JAX-RS (Jersey)

In some of my recent work I got the request to produce a custom Reason Phrase in the  HTTP status response delivered to one of our REST API consuming clients when an error occurs. In this post I will demonstrate how you can achieve that with Jersey.

1. Define checked exception and exception mapper

As you might have found out from my post Error handling in REST API with Jersey, I like handling the checked exceptions using Jersey’s ExceptionMapper capability.

For the purpose of this demonstration I defined a CustomReasonPhraseException:

package org.codingpedia.demo.rest.errorhandling;

public class CustomReasonPhraseException extends Exception {

	private static final long serialVersionUID = -271582074543512905L;

	private final int businessCode;

	public CustomReasonPhraseException(int businessCode, String message) {
		super(message);
		this.businessCode = businessCode;
	}

	public int getBusinessCode() {
		return businessCode;
	}

}

and a  CustomReasonPhraseExceptionMapper to handle the mapping to a response if a CustomReasonPhraseException occurs:

package org.codingpedia.demo.rest.errorhandling;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class CustomReasonPhraseExceptionMapper implements ExceptionMapper<CustomReasonPhraseException> {

	public Response toResponse(CustomReasonPhraseException bex) {
		return Response.status(new CustomReasonPhraseExceptionStatusType(Status.BAD_REQUEST))
				.entity("Custom Reason Phrase exception occured : " + bex.getMessage())
				.build();
	}

}

Reminder: When the application throws a CustomReasonPhraseException the toResponse method of the CustomReasonPhraseExceptionMapper instance will be invoked.

In the ExceptionMapper code note line 12:

return Response.status(new CustomReasonPhraseExceptionStatusType(Status.BAD_REQUEST))

In Jersey’s ResponseBuilder you have the possibility to define your own status types, by implementing the javax.ws.rs.core.Response.StatusType interface.

2. Implement custom StatusType

To make a little more extensible I’ve created an AbstractStatusType class:

package org.codingpedia.demo.rest.errorhandling;

import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.Response.StatusType;

/**
 * Class used to provide custom StatusTypes, especially for the the Reason Phrase that appears in the HTTP Status Response
 */
public abstract class AbstractStatusType implements StatusType {

	public AbstractStatusType(final Family family, final int statusCode,
                          final String reasonPhrase) {
	    super();

	    this.family = family;
	    this.statusCode = statusCode;
	    this.reasonPhrase = reasonPhrase;
	}

	protected AbstractStatusType(final Status status,
	                             final String reasonPhrase) {
	    this(status.getFamily(), status.getStatusCode(), reasonPhrase);
	}

	@Override
	public Family getFamily() { return family; }

	@Override
	public String getReasonPhrase() { return reasonPhrase; }

	@Override
	public int getStatusCode() { return statusCode; }

	private final Family family;
	private final int statusCode;
	private final String reasonPhrase;

}

, which I extend afterwards with the CustomReasonPhraseExceptionStatusType to provide the custom Reason Phrase I desire (e.g. “Custom error message”) in the response:

package org.codingpedia.demo.rest.errorhandling;

import javax.ws.rs.core.Response.Status;

/**
 * Implementation of StatusType for CustomReasonPhraseException.
 * The Reason Phrase is set in this case to "Custom error message"
 */
public class CustomReasonPhraseExceptionStatusType extends AbstractStatusType{

	private static final String CUSTOM_EXCEPTION_REASON_PHRASE = "Custom error message";

	public CustomReasonPhraseExceptionStatusType(Status httpStatus) {
		super(httpStatus, CUSTOM_EXCEPTION_REASON_PHRASE);
	}

}

 

 3. Test the custom Reason Phrase in the HTTP status response

3.1. Request

GET http://localhost:8888/demo-rest-jersey-spring/mocked-custom-reason-phrase-exception HTTP/1.1
Accept-Encoding: gzip,deflate
Host: localhost:8888
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

3.2. Response

Et voila:

HTTP/1.1 400 Custom error message
Content-Type: text/plain
Content-Length: 95
Server: Jetty(9.0.7.v20131107)

Custom Reason Phrase exception occured : message attached to the Custom Reason Phrase Exception

, the custom Reason Phrase appears in the response as expected.

Tip: If you want really learn how to design and implement REST API in Java read the following Tutorial – REST API design and implementation in Java with Jersey and Spring

Summary

You’ve seen in this post how to create a custom Reason Phrase in a HTTP status response when you want to flag a “special” error. Of course you can use this mechanism to define your own Reason Phrase-s for other HTTP statuses as well.  Actually you should not abuse this Reason Phrase feature as in the HTTP 1.1 rfc2616 is stated the following:

“The Status-Code element is a 3-digit integer result code of the attempt to understand and satisfy the request. These codes are fully defined in section 10. The Reason-Phrase is intended to give a short textual description of the Status-Code. The Status-Code is intended for use by automata and the Reason-Phrase is intended for the human user. The client is not required to examine or display the Reason- Phrase.”[1]

Well, that’s it. Keep on coding and keep on sharing coding knowledge.

Resources

  1. Hypertext Transfer Protocol — HTTP/1.1 – Response
  2. Jersey User Guide
Podcastpedia image

Adrian Matei

Creator of Podcastpedia.org and Codingpedia.org, computer science engineer, husband, father, curious and passionate about science, computers, software, education, economics, social equity, philosophy - but these are just outside labels and not that important, deep inside we are all just consciousness, right?

How to redirect domain to www url with nginx

Snippet from nginx config file that redirects all requests (http and https) to the www URL Continue reading