Wednesday, August 14, 2013

Spring 3 MVC + Hibernate 4 + JdbcTemplate + Partial REST controller (Part 2)

Second part of the article will focus on the controllers which will process clients' requests as well as other helper classes.

We start off with a custom exception. We add on a HttpStatus code into the exception to return to clients:

package com.techtots.services.api.common.exceptions;

import org.springframework.http.HttpStatus;

public class RestException extends Exception {

 private static final long serialVersionUID = -6373811042517187537L;

 public static final HttpStatus DEFAULT_ERROR_STATUS = HttpStatus.BAD_REQUEST;
 
 private HttpStatus status;
  
 public HttpStatus getStatus() {
  return status;
 }

 public void setStatus(HttpStatus status) {
  this.status = status;
 }

 public RestException() {
  super();
  
  this.status = DEFAULT_ERROR_STATUS;
 }

 public RestException(String message) {
  super(message);
 
  this.status = DEFAULT_ERROR_STATUS;
 }
 
 public RestException(HttpStatus status, String message) {
  super(message);
  
  this.status = status;
 }
}

With Spring 3.2, we can use the @ControllerAdvice annotation to centralize validation and exception handling.

package com.techtots.services.api.common;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import com.techtots.services.api.common.exceptions.RestException;

@ControllerAdvice
public class RestResponseExceptionHandler extends ResponseEntityExceptionHandler {

 Logger log = LoggerFactory.getLogger(RestResponseExceptionHandler.class);
 
 @ExceptionHandler(RestException.class)
 protected ResponseEntity handleBadRequest(RestException ex) {

  log.error(ExceptionUtils.getStackTrace(ex));
  
  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.TEXT_HTML);
  
  ResponseEntity entity = new ResponseEntity(ex.getMessage(), headers, ex.getStatus()); 
  
  return entity;
 }
}


Finally, a test controller to hook everything up:

package com.techtots.services.api.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.techtots.services.api.common.exceptions.RestException;

@Controller
@RequestMapping("/auth")
public class AuthController extends BaseController {
 @RequestMapping(value = "/test", method = RequestMethod.GET, produces = "application/json")
 @ResponseBody
 public String test() throws Exception {

  return "ok";
 }

 @RequestMapping(value = "/test2", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
 @ResponseBody
 public void test2() throws Exception {

  throw new RestException("something's missing...");
 }

}

Calling the test method will return a JSON encoded message. While calling the test2 method will throw a HTTP exception with the message "something's missing" with HTTP error code 400 (the default HTTP error code returned in RestResponseExceptionHandler).

No comments: