package com.bitmonlab.osiris.core.errorhandler; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.ws.rs.WebApplicationException; 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; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.JsonParseException; import com.google.common.collect.ImmutableList; import com.yammer.dropwizard.validation.InvalidEntityException; /** * * Every exception in rest layer is caught by this class to be handled and * 'restability' (I mean build rest) the error response, with a description * * The flow of this goes as I next describe: * * First it load the property file to a map in memory Later find all messages in * database and overload the properties values in case there are anyone already * in database. After that, The memory map is stored in database. And at the end * of the flow, a scheduler load from database the changes every 30 minutes. * */ @Provider public class RestErrorsHandler implements ExceptionMapper<Exception> { private static final Logger LOG = LoggerFactory.getLogger(RestErrorsHandler.class); private Map<String, DataException> httpCodes = null; public RestErrorsHandler() { initializeFromProperties(); } public Response toResponse(Exception exception) { try { Class<? extends Exception> exceptionClass = exception.getClass(); if (exception instanceof WebApplicationException) { WebApplicationException wae = (WebApplicationException) exception; return Response.status(wae.getResponse().getStatus()).entity(wae.getResponse().getEntity()).build(); } else if (exception instanceof JsonParseException) { DataException httpDataException = httpDataException(exception, httpCodes); return returnErrorResponse(exception.getMessage(), exceptionClass.getSimpleName(), httpDataException, Status.BAD_REQUEST); } else if (exception instanceof InvalidEntityException) { InvalidEntityException invalidEntityException = (InvalidEntityException) exception; ImmutableList<String> iList = invalidEntityException.getErrors(); String exMsg = ""; for (String errorMsg : iList) { exMsg += errorMsg + ", "; } exMsg = exMsg.substring(0, exMsg.length() - 2); DataException httpDataException = httpDataException(exception, httpCodes); return returnErrorResponse(exMsg, exceptionClass.getSimpleName(), httpDataException, Status.BAD_REQUEST); } else { DataException httpDataException = httpDataException(exception, httpCodes); return returnErrorResponse(exception.getMessage(), exceptionClass.getSimpleName(), httpDataException, null); } } catch (Throwable e) { e.printStackTrace(); return null; } } private Response returnErrorResponse(String exceptionMessage, String exceptionClassSimpleName, DataException httpDataException, Status status) { if (null == status) status = httpDataException.getStatus(); ErrorResponse error = buildErrorBean(status, httpDataException.getCode(), exceptionClassSimpleName, httpDataException.getDescription(), exceptionMessage); return Response.status(status.getStatusCode()).entity(error).build(); } public ErrorResponse buildErrorBean(Status status, Integer code, String className, String description, String msg) { ErrorResponse error = new ErrorResponse(); error.setStatus(status.getStatusCode()); error.setStatusReason(status.getReasonPhrase()); error.setCode(code); error.setException(className); error.setDescription(description); error.setMessage(msg); return error; } public DataException httpDataException(Exception exception, Map<String, DataException> httpCodes) { String className = exception.getClass().getName(); DataException dataException = httpCodes.get(className); if (dataException == null) { httpCodes.put(className, new DataException(httpCodes.keySet().size() + 1, Status.INTERNAL_SERVER_ERROR, "")); dataException = httpCodes.get(className); LOG.error("Application Error", exception); } else { LOG.warn("User Error: {}, {}", dataException.getDescription(), exception.getMessage()); } return dataException; } private void initializeFromProperties() { httpCodes = new HashMap<String, DataException>(); Enumeration<String> allErrorsKeys = RestErrors.getKeys(); while (allErrorsKeys.hasMoreElements()) { try { String exceptionName = allErrorsKeys.nextElement(); String string = RestErrors.getString(exceptionName); String restErrorLineValue[] = string.split(","); int code = Integer.parseInt(restErrorLineValue[0]); String status = restErrorLineValue[1]; String description = restErrorLineValue[2]; System.out.println(exceptionName + ";" + string + ";" + status + ";" + description); httpCodes.put(exceptionName, new DataException(code, Status.valueOf(status), description)); } catch (Throwable e) { e.printStackTrace(); } } } public Map<String, DataException> getHttpCodes() { return httpCodes; } }