package compositions; import com.fasterxml.jackson.databind.JsonNode; import exceptions.ErrorResponse; import exceptions.PoseidonException; import play.libs.F; import play.libs.Json; import play.mvc.Action; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; import javax.persistence.EntityExistsException; import javax.persistence.PersistenceException; import static play.mvc.Http.Status.*; import static play.libs.Jsonp.jsonp; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class ErrorHandlingComposition { private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ErrorHandlingComposition.class); @With(ErrorHandlingAction.class) @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ErrorHandling { String value() default "*"; } public static class ErrorHandlingAction extends Action<ErrorHandling> { private static final String STANDARD_DB_ERROR_MESSAGE = "En feil oppstod under kommunikasjon med databasen. Feilen har blitt logget"; private static final String DB_ERROR_UNIQUE_CONSTRAINT = "En av de oppgitte verdiene er ikke unik"; public F.Promise<Result> call(Http.Context context) throws Throwable { F.Promise<Result> res; try { res = delegate.call(context); } catch (PoseidonException e) { logError(e); ErrorResponse errorResponse = new ErrorResponse(e.getErrorCode(), e.getMessage()); String callback = resolveCallback(context); Result result; if ( e.getErrorCode() == BAD_REQUEST){ result = badRequesJsonp(callback, Json.toJson(errorResponse)); } else if ( e.getErrorCode() == NOT_FOUND){ result = notFoundJsonp(callback, Json.toJson(errorResponse)); } else if ( e.getErrorCode() == UNAUTHORIZED){ result = unauthorizedJsonp(callback, Json.toJson(errorResponse)); } else if ( e.getErrorCode() == FORBIDDEN){ result = forbiddenJsonp(callback, Json.toJson(errorResponse)); } else result = internalServerErrorJsonp(callback,Json.toJson(errorResponse)); return F.Promise.pure(result); } catch (EntityExistsException e){ logError(e); String callback = resolveCallback(context); String msg = DB_ERROR_UNIQUE_CONSTRAINT; ErrorResponse response = new ErrorResponse(INTERNAL_SERVER_ERROR,msg); return F.Promise.pure(badRequesJsonp(callback,Json.toJson(response))); } catch (PersistenceException e){ logError(e); String callback = resolveCallback(context); String msg = STANDARD_DB_ERROR_MESSAGE; if ( e.getMessage().toLowerCase().contains("unique")){ msg = DB_ERROR_UNIQUE_CONSTRAINT; } ErrorResponse response = new ErrorResponse(INTERNAL_SERVER_ERROR,msg); return F.Promise.pure(internalServerErrorJsonp(callback,Json.toJson(response))); } catch (Exception e){ logError(e); String callback = resolveCallback(context); ErrorResponse response = new ErrorResponse(INTERNAL_SERVER_ERROR,e.getMessage()); return F.Promise.pure(internalServerErrorJsonp(callback,Json.toJson(response))); } return res; } private void logError(Exception e) { logger.error("REST call failed exception message " + e.getMessage(),e); if ( e.getCause() != null) { logger.error("REST call failed with cause " + e.getCause().getMessage()); } } private String resolveCallback(Http.Context context) { String[] callbackmap = context.request().queryString().get("callback"); String callback = null; if (callbackmap != null && callbackmap.length > 0) { callback = callbackmap[0]; } return callback; } private static Result badRequesJsonp(String callback, JsonNode jsonOutput){ return callback == null ? badRequest(jsonOutput) : badRequest(jsonp(callback, jsonOutput)); } private static Result notFoundJsonp(String callback, JsonNode jsonOutput){ return callback == null ? notFound(jsonOutput) : notFound(jsonp(callback, jsonOutput)); } private static Result internalServerErrorJsonp(String callback, JsonNode jsonOutput){ return callback == null ? internalServerError(jsonOutput) : internalServerError(jsonp(callback, jsonOutput)); } private static Result unauthorizedJsonp(String callback, JsonNode jsonOutput){ return callback == null ? unauthorized(jsonOutput) : unauthorized(jsonp(callback, jsonOutput)); } private static Result forbiddenJsonp(String callback, JsonNode jsonOutput){ return callback == null ? forbidden(jsonOutput) : forbidden(jsonp(callback, jsonOutput)); } } }