Skip to content

Instantly share code, notes, and snippets.

@imasahiro
Created November 21, 2017 11:03
Show Gist options
  • Save imasahiro/53dc8747cb6594bbbc9a5935123805c3 to your computer and use it in GitHub Desktop.
Save imasahiro/53dc8747cb6594bbbc9a5935123805c3 to your computer and use it in GitHub Desktop.
public final class ExceptionHandlingHttpService extends SimpleDecoratingService<HttpRequest, HttpResponse> {
@Value(staticConstructor = "of")
private static class ExceptionHandler {
Class<? extends Throwable> exceptionType;
BiFunction<HttpRequest, Throwable, HttpResponse> exceptionHandler;
}
private final ExceptionHandler defaultExceptionHandler =
ExceptionHandler.of(Throwable.class, ExceptionHandlingHttpService::error);
private final List<ExceptionHandler> exceptionHandlers = ImmutableList.of(
// bad request
ExceptionHandler.of(IllegalArgumentException.class, this::badRequest),
// not found
ExceptionHandler.of(ResourceNotFoundException.class, this::notFound),
ExceptionHandler.of(PageNotFoundException.class, this::notFound),
// Network error.
ExceptionHandler.of(IOException.class, this::serverError)
);
//...
private HttpResponse notFound(HttpRequest request, Throwable ex) {
log.warn("Not found, request:{}", request.path(), ex);
return HttpResponse.of(HttpStatus.NOT_FOUND);
}
//...
private HttpResponse handleException(HttpRequest req, Throwable thrown) {
Throwable rootCause = Throwables.getRootCause(thrown);
return exceptionHandlers.stream()
.filter(handler -> rootCause.getClass()
.isAssignableFrom(handler.getExceptionType()))
.findFirst()
.orElse(defaultExceptionHandler)
.getExceptionHandler().apply(req, rootCause);
}
@Override
public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) {
final HttpResponse res;
try {
res = delegate().serve(ctx, req);
} catch (Exception e) {
return handleException(req, e);
}
return HttpResponse.from(res.aggregate().handle((message, thrown) -> {
if (thrown != null) {
return handleException(req, thrown);
}
return message.toHttpResponse();
}));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment