-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add injection point for handling exceptions
-- Before we hard-coded how we handled exceptions in the Servlets. For example, by default we return a 400 - Bad Request if we get an Exception. However, this is very inflexible. For example, suppose customers have some customizations (like their own SearchProviders) that may generate errors the DataServlet doesn't know to look for, but aren't the fault of the user. Then, Fili currently returns a 400, even though it should probably be some sort of 5xx. So we add an injection point to all servlets that allows customers to provide their own logic for handling DataServlet errors.
- Loading branch information
Andrew Cholewa
committed
Jul 13, 2018
1 parent
39678fd
commit 279a162
Showing
22 changed files
with
758 additions
and
241 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
fili-core/src/main/java/com/yahoo/bard/webservice/exception/DataExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2018 Oath Inc. | ||
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms. | ||
package com.yahoo.bard.webservice.exception; | ||
|
||
import com.yahoo.bard.webservice.web.apirequest.DataApiRequest; | ||
|
||
import com.fasterxml.jackson.databind.ObjectWriter; | ||
|
||
import java.util.Optional; | ||
|
||
import javax.ws.rs.container.AsyncResponse; | ||
import javax.ws.rs.container.ContainerRequestContext; | ||
import javax.ws.rs.core.UriInfo; | ||
|
||
/** | ||
* Allows a customer to inject custom code for handling Exceptions in Fili's DataServlet. | ||
* | ||
* For example, customers may want to return 500's for some custom exceptions, or return | ||
* an empty set when dimension rows are not found. | ||
*/ | ||
public interface DataExceptionHandler { | ||
|
||
/** | ||
* Handles any exception generated during response processing. | ||
* | ||
* @param e The generated throwable (i.e. exception or error) | ||
* @param asyncResponse A response that can be used to respond asynchronously | ||
* (probably with some sort of appropriate error code) | ||
* @param apiRequest A bean containing parsed information about the request, note that | ||
* this won't exist if an exception was thrown while constructing the request | ||
* @param containerRequestContext HTTP request context | ||
* @param uriInfo URiInfo of the request | ||
* @param writer A tool for serializing JSON | ||
*/ | ||
void handleException( | ||
Throwable e, | ||
AsyncResponse asyncResponse, | ||
Optional<DataApiRequest> apiRequest, | ||
ContainerRequestContext containerRequestContext, | ||
UriInfo uriInfo, | ||
ObjectWriter writer | ||
); | ||
} |
43 changes: 43 additions & 0 deletions
43
fili-core/src/main/java/com/yahoo/bard/webservice/exception/ExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2018 Oath Inc. | ||
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms. | ||
package com.yahoo.bard.webservice.exception; | ||
|
||
import com.yahoo.bard.webservice.web.apirequest.DataApiRequest; | ||
|
||
import com.fasterxml.jackson.databind.ObjectWriter; | ||
|
||
import java.util.Optional; | ||
|
||
import javax.ws.rs.container.AsyncResponse; | ||
import javax.ws.rs.container.ContainerRequestContext; | ||
import javax.ws.rs.core.UriInfo; | ||
|
||
/** | ||
* Allows a customer to inject custom code for handling Exceptions in Fili. | ||
* | ||
* For example, customers may want to return 500's for some custom exceptions, or return | ||
* an empty set when dimension rows are not found. | ||
*/ | ||
public interface ExceptionHandler { | ||
|
||
/** | ||
* Handles any exception generated during response processing. | ||
* | ||
* @param e The generated throwable (i.e. exception or error) | ||
* @param asyncResponse A response that can be used to respond asynchronously | ||
* (probably with some sort of appropriate error code) | ||
* @param apiRequest A bean containing parsed information about the request, note that | ||
* this won't exist if an exception was thrown while constructing the request | ||
* @param containerRequestContext HTTP request context | ||
* @param uriInfo URiInfo of the request | ||
* @param writer A tool for serializing JSON | ||
*/ | ||
void handleException( | ||
Throwable e, | ||
AsyncResponse asyncResponse, | ||
Optional<DataApiRequest> apiRequest, | ||
ContainerRequestContext containerRequestContext, | ||
UriInfo uriInfo, | ||
ObjectWriter writer | ||
); | ||
} |
66 changes: 66 additions & 0 deletions
66
fili-core/src/main/java/com/yahoo/bard/webservice/exception/FiliDataExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright 2018 Oath Inc. | ||
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms. | ||
package com.yahoo.bard.webservice.exception; | ||
|
||
import static javax.ws.rs.core.Response.Status.BAD_REQUEST; | ||
import static javax.ws.rs.core.Response.Status.GATEWAY_TIMEOUT; | ||
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; | ||
|
||
import com.yahoo.bard.webservice.data.dimension.TimeoutException; | ||
import com.yahoo.bard.webservice.table.resolver.NoMatchFoundException; | ||
import com.yahoo.bard.webservice.web.RequestValidationException; | ||
import com.yahoo.bard.webservice.web.apirequest.DataApiRequest; | ||
import com.yahoo.bard.webservice.web.handlers.RequestHandlerUtils; | ||
|
||
import com.fasterxml.jackson.databind.ObjectWriter; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.Optional; | ||
|
||
import javax.ws.rs.container.AsyncResponse; | ||
import javax.ws.rs.container.ContainerRequestContext; | ||
import javax.ws.rs.core.UriInfo; | ||
|
||
/** | ||
* The default implementation of {@link DataExceptionHandler}. | ||
* | ||
* This class handles the following cases: | ||
* | ||
* <ol> | ||
* <li> RequestValidationException - builds an error response and returns the HTTP status stored in the | ||
* exception | ||
* <li> NoMatchFoundException - Returns a 500 (Internal Server Error) | ||
* <li> TimeoutException - Returns a 504 (Gateway Timeout) | ||
* <li> Error | Exception - A 400 with an response payload containing the throwable's message | ||
* </ol> | ||
*/ | ||
public class FiliDataExceptionHandler implements DataExceptionHandler { | ||
private static final Logger LOG = LoggerFactory.getLogger(FiliDataExceptionHandler.class); | ||
|
||
@Override | ||
public void handleException( | ||
Throwable e, | ||
AsyncResponse asyncResponse, | ||
Optional<DataApiRequest> apiRequest, | ||
ContainerRequestContext containerRequestContext, | ||
UriInfo uriInfo, | ||
ObjectWriter writer | ||
) { | ||
if (e instanceof RequestValidationException) { | ||
LOG.debug(e.getMessage(), e); | ||
RequestValidationException rve = (RequestValidationException) e; | ||
asyncResponse.resume(RequestHandlerUtils.makeErrorResponse(rve.getStatus(), rve, writer)); | ||
} else if (e instanceof NoMatchFoundException) { | ||
LOG.info("Exception processing request", e); | ||
asyncResponse.resume(RequestHandlerUtils.makeErrorResponse(INTERNAL_SERVER_ERROR, e, writer)); | ||
} else if (e instanceof TimeoutException) { | ||
LOG.info("Exception processing request", e); | ||
asyncResponse.resume(RequestHandlerUtils.makeErrorResponse(GATEWAY_TIMEOUT, e, writer)); | ||
} else { | ||
LOG.info("Exception processing request", e); | ||
asyncResponse.resume(RequestHandlerUtils.makeErrorResponse(BAD_REQUEST, e, writer)); | ||
} | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
...core/src/main/java/com/yahoo/bard/webservice/exception/FiliDimensionExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright 2018 Oath Inc. | ||
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms. | ||
package com.yahoo.bard.webservice.exception; | ||
|
||
import static com.yahoo.bard.webservice.web.ResponseCode.INSUFFICIENT_STORAGE; | ||
|
||
import static javax.ws.rs.core.Response.Status.BAD_REQUEST; | ||
|
||
import com.yahoo.bard.webservice.web.ErrorMessageFormat; | ||
import com.yahoo.bard.webservice.web.RequestValidationException; | ||
import com.yahoo.bard.webservice.web.RowLimitReachedException; | ||
import com.yahoo.bard.webservice.web.apirequest.ApiRequest; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.Optional; | ||
|
||
import javax.ws.rs.container.ContainerRequestContext; | ||
import javax.ws.rs.core.Response; | ||
import javax.ws.rs.core.Response.Status; | ||
import javax.ws.rs.core.UriInfo; | ||
|
||
/** | ||
* Default implementation of the MetadataExceptionHandler for the DimensionServlet. | ||
*/ | ||
public class FiliDimensionExceptionHandler implements MetadataExceptionHandler { | ||
private static final Logger LOG = LoggerFactory.getLogger(FiliDimensionExceptionHandler.class); | ||
|
||
@Override | ||
public Response handleThrowable( | ||
Throwable e, | ||
Optional<ApiRequest> request, | ||
UriInfo uriInfo, | ||
ContainerRequestContext requestContext, | ||
String metadataEntityName | ||
) { | ||
if (e instanceof RequestValidationException) { | ||
LOG.debug(e.getMessage(), e); | ||
RequestValidationException rve = (RequestValidationException) e; | ||
return Response.status(rve.getStatus()).entity(rve.getErrorHttpMsg()).build(); | ||
} else if (e instanceof RowLimitReachedException) { | ||
String msg = String.format("Row limit exceeded for dimension %s: %s", metadataEntityName, e.getMessage()); | ||
LOG.debug(msg, e); | ||
return Response.status(INSUFFICIENT_STORAGE).entity(msg).build(); | ||
} else if (e instanceof JsonProcessingException) { | ||
String msg = ErrorMessageFormat.INTERNAL_SERVER_ERROR_ON_JSON_PROCESSING.format(e.getMessage()); | ||
LOG.error(msg, e); | ||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(msg).build(); | ||
} else { | ||
String msg = ErrorMessageFormat.REQUEST_PROCESSING_EXCEPTION.format(e.getMessage()); | ||
LOG.debug(msg, e); | ||
return Response.status(BAD_REQUEST).entity(msg).build(); | ||
} | ||
} | ||
} |
Oops, something went wrong.