Java tutorial
/** * Copyright 2014 Unicon (R) Licensed under the * Educational Community License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. * */ package org.apereo.openlrs.controllers.xapi; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.RandomStringUtils; import org.apereo.openlrs.exceptions.NotFoundException; import org.apereo.openlrs.exceptions.xapi.InvalidXAPIRequestException; import org.apereo.openlrs.exceptions.xapi.StatementStateConflictException; import org.apereo.openlrs.model.xapi.XAPIErrorInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.NestedServletException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; /** * Class that handles exceptions generated from XAPI controllers, returning proper HTTP codes and useful messages. * @author Gary Roybal, groybal@unicon.net */ @ControllerAdvice(annotations = RestController.class) public class XAPIExceptionHandlerAdvice { private Logger logger = LoggerFactory.getLogger(XAPIExceptionHandlerAdvice.class); public XAPIExceptionHandlerAdvice() { } @ExceptionHandler(NotImplementedException.class) @ResponseStatus(value = HttpStatus.NOT_IMPLEMENTED) @ResponseBody public XAPIErrorInfo handleNotImplementedException(final HttpServletRequest request, final NotImplementedException e) { final XAPIErrorInfo result = new XAPIErrorInfo(HttpStatus.NOT_IMPLEMENTED, request, e.getLocalizedMessage()); this.logException(e); this.logError(result); return result; } @ExceptionHandler(NotFoundException.class) @ResponseStatus(value = HttpStatus.NOT_FOUND) @ResponseBody public XAPIErrorInfo handleNotImplementedException(final HttpServletRequest request, final NotFoundException e) { final XAPIErrorInfo result = new XAPIErrorInfo(HttpStatus.NOT_FOUND, request, e.getLocalizedMessage()); this.logException(e); this.logError(result); return result; } @ExceptionHandler(InvalidXAPIRequestException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public XAPIErrorInfo handleInvalidRestRequestException(final HttpServletRequest request, final InvalidXAPIRequestException e) { final XAPIErrorInfo result = new XAPIErrorInfo(HttpStatus.BAD_REQUEST, request, e.getLocalizedMessage()); this.logException(e); this.logError(result); return result; } @ExceptionHandler(StatementStateConflictException.class) @ResponseStatus(value = HttpStatus.CONFLICT) @ResponseBody public XAPIErrorInfo handleStatementStateConflictException(final HttpServletRequest request, final HttpServletResponse response, final StatementStateConflictException e) { final XAPIErrorInfo result = new XAPIErrorInfo(HttpStatus.CONFLICT, request, e.getLocalizedMessage()); this.logException(e); this.logError(result); return result; } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public XAPIErrorInfo handleMethodArgumentNotValidException(final HttpServletRequest request, MethodArgumentNotValidException e) { final List<String> errorMessages = new ArrayList<String>(); for (ObjectError oe : e.getBindingResult().getAllErrors()) { if (oe instanceof FieldError) { final FieldError fe = (FieldError) oe; final String msg = String.format("Field error in object '%s' on field '%s': rejected value [%s].", fe.getObjectName(), fe.getField(), fe.getRejectedValue()); errorMessages.add(msg); } else { errorMessages.add(oe.toString()); } } final XAPIErrorInfo result = new XAPIErrorInfo(HttpStatus.BAD_REQUEST, request, errorMessages); this.logException(e); this.logError(result); return result; } @ExceptionHandler(UnrecognizedPropertyException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public XAPIErrorInfo handleUnrecognizedPropertyException(final HttpServletRequest request, UnrecognizedPropertyException e) { final String errorMessage = String.format("Unrecognized property: [%s].", e.getPropertyName()); final XAPIErrorInfo result = new XAPIErrorInfo(HttpStatus.BAD_REQUEST, request, errorMessage); this.logException(e); this.logError(result); return result; } @ExceptionHandler(HttpMessageNotReadableException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public XAPIErrorInfo handleHttpMessageNotReadableException(final HttpServletRequest request, HttpMessageNotReadableException e) { if (e.getCause() instanceof UnrecognizedPropertyException) { return this.handleUnrecognizedPropertyException(request, (UnrecognizedPropertyException) e.getCause()); } else { XAPIErrorInfo result; if (e.getCause() instanceof JsonProcessingException) { final JsonProcessingException jpe = (JsonProcessingException) e.getCause(); result = new XAPIErrorInfo(HttpStatus.BAD_REQUEST, request, jpe.getOriginalMessage()); } else { result = new XAPIErrorInfo(HttpStatus.BAD_REQUEST, request, e); } this.logException(e); this.logError(result); return result; } } @ExceptionHandler(org.springframework.web.util.NestedServletException.class) public void test(NestedServletException e) { Throwable t = e.getCause(); logger.debug("*************************** " + t.getClass().getName()); } @ExceptionHandler(Exception.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public XAPIErrorInfo exception(final HttpServletRequest request, Exception e) throws Exception { final String logMessageReferenceId = RandomStringUtils.randomAlphanumeric(8); final XAPIErrorInfo result = new XAPIErrorInfo(HttpStatus.INTERNAL_SERVER_ERROR, request, "Unexpected error [reference ID: " + logMessageReferenceId + "]."); logger.debug("Unexpected XAPI exception [refId: {}]: {}", logMessageReferenceId, e); this.logError(result); return result; } private void logException(final Exception e) { logger.debug("Exception message: {}", e.getMessage()); } private void logError(final XAPIErrorInfo error) { logger.debug("Returning error: {}", error); } }