Enterprise Java

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:

 
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:

CustomReasonPhraseExceptionMapper

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:

CustomReasonPhraseExceptionStatusType

 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:

AbstractStatusType

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:

CustomReasonPhraseExceptionStatusType extends AbstractStatusType

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

Request example

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:

Response example

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.

Adrian Matei

Adrian Matei (ama [AT] codingpedia DOT org) is the founder of Podcastpedia.org and Codingpedia.org, computer science engineer, husband, father, curious and passionate about science, computers, software, education, economics, social equity, philosophy.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Myself
Myself
7 years ago

Note that this will *not* work for status 400 getReasonPhrase” in jersey code.

I would have found it nice to send a ‘201 Created’ custom mesage with for instance an id of what is created… but apparently it doesn’t suite the web standards.

Back to top button