

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") public @ResponseBody ResponseEntity addItem(@PathVariable final String itemID, @RequestBody final Item item, HttpServletRequest request ) { RESTItem inserted = null; try{ inserted = itemService.insertItem(itemID, item); }catch(ItemAlreadyExistsException iaee){ HttpHeaders responseHeaders = new HttpHeaders(); ResponseEntity re; try{ 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") public @ResponseBody 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{ ....

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 ItemController.java, addItem, 61 - e: info.lotharschulz.item.model.data.exception.ItemAlreadyExistsException: RESTItem already exists. 16963 [http-bio-8080-exec-21] DEBUG ItemController.java, addItem, 71 - re: ...... 16969 [http-bio-8080-exec-30] DEBUG ItemController.java, getItem, 36 - RESTItem{externalID=id123,description=description,label=label} 16985 [http-bio-8080-exec-30] DEBUG AbstractMessageConverterMethodProcessor.java, 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.

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: https://github.com/lotharschulz/customHTTPcodes/tree/v0.1.
update
- screenshots and urls updated due to new branches and tags in the underlying github project
- travis ci badge:
- codacy badge:
Leave a Reply