custom http status codes with spring mvc 3.2

custom status codes
POST response - Poster
POST response – Poster

I never thought creating customized http status codes would forces me to start an own sample project.

Some time ago I wanted to return customized http codes for rest resources in one of my sample projects. I started searching the web and found amongst many results some interesting such as this and that this and that . Although those websites contain detailed information, I wanted to dive deep into the subject and decided to code my own piece of code. I decided to use spring 3.2 as base of the resulting project.

Two ways of returning http status codes are implemented in the code:

  • returning a ResponseEntity
  • throwing an Exception

(both in the controller class of the sample project) .
Returning a ResponseEntity instance is quite easy. There is a list of several constructors you can choose from.
This code snippet shows two different constructor calls:

@RequestMapping(value = "/{itemID}", method = RequestMethod.PUT, produces="application/json")
ResponseEntity addItem(@PathVariable final String itemID, @RequestBody final Item item, HttpServletRequest request  ) {
RESTItem inserted = null;
inserted = itemService.insertItem(itemID, item);
}catch(ItemAlreadyExistsException iaee){
HttpHeaders responseHeaders = new HttpHeaders();
ResponseEntity re;
responseHeaders.setLocation(new URI(request.getRequestURL().toString()));
re = new ResponseEntity(responseHeaders, HttpStatus.SEE_OTHER);
}catch (URISyntaxException urise){
log.error("URISyntaxException: " + urise + " n");
re = new ResponseEntity(HttpStatus.SEE_OTHER);
return re;
return new ResponseEntity(HttpStatus.CREATED);

The other approach is throwing an Exception.

@RequestMapping(value = "/{itemID}", method = RequestMethod.POST, produces="application/json")
RESTItem udpateItem(@PathVariable final String itemID, @RequestBody final Item item) {
RESTItem updated = itemService.updateItemByExternalID(itemID, item.getDescription(), item.getLabel());
if (null == updated) {
throw new BadRequestException();
return updated;

The exception class should extend RuntimeException and utilize spring’s @ResponseStatus annotation.
This annotation allows you to define the http code that is produced once the exception is thrown.

@ResponseStatus( value = HttpStatus.BAD_REQUEST )
public class BadRequestException extends RuntimeException{
PUT response - Poster
PUT response – Poster

The other classes in this sample project follow spring’s proposed mvc structure. My deployment uses maven’s tomcat7 plugin ( mvn tomcat7:(re)/(un)deploy ). This way the application is available via localhost on a local machine.

Often I used Poster for smoke test – so I did for this sample. One interesting detail about Poster is that it follows redirects. The addItem method showed above returns a SEE_OTHER http code including a location header if the item already exists. If the location header is followed with a get request that produces a 200/OK answer (see screenshot “PUT response – Poster” for details). Also the catalina.out log points to a 303 followed by a get request:

16962 [http-bio-8080-exec-21] DEBUG, addItem, 61   - e: RESTItem already exists.
16963 [http-bio-8080-exec-21] DEBUG, addItem, 71   - re:
16969 [http-bio-8080-exec-30] DEBUG, getItem, 36   - RESTItem{externalID=id123,description=description,label=label}
16985 [http-bio-8080-exec-30] DEBUG, writeWithMessageConverters, 150   - Written [RESTItem{externalID=id123,description=description,label=label}] as "application/json" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@7326cbb1]

Postman, another tool to test (RESTful) APIs shows the same follow redirection behaviour.

PUT response - POSTMAN
PUT response – POSTMAN

Automated test are not included in the project ( yet ), however one tasks would be to check the SEE_OTHER status code rather then the redirected url status code.

You can find the sample code on github:


Be the first to comment

Leave a Reply

Your email address will not be published.


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