Interface ServiceErrorHandler

Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@UnstableApi @FunctionalInterface public interface ServiceErrorHandler
Provides the error responses in case of unexpected exceptions. Implement this interface to customize Armeria's error responses.

 ServiceErrorHandler errorHandler = (ctx, cause) -> {
     if (cause instanceof IllegalArgumentException) {
         return HttpResponse.of(HttpStatus.BAD_REQUEST);
     }

     // Return null to let ServerErrorHandler.ofDefault() handle the exception.
     return null;
 }

 Server.builder().route().errorHandler(errorHandler)...
 

Recording a service exception (or not)

By default, an exception raised by a service or a decorator is captured and recorded into RequestLog.responseCause(). You can keep Armeria from recording it while sending the desired response by returning a failed response whose cause is an HttpStatusException or HttpResponseException:


 ServiceErrorHandler errorHandler = (ctx, cause) -> {
     if (cause instanceof IllegalArgumentException) {
         // IllegalArgumentException is captured into RequestLog#responseCause().
         return HttpResponse.of(HttpStatus.BAD_REQUEST);
     }

     if (cause instanceof NotFoundException) {
         // NotFoundException is NOT captured into RequestLog#responseCause().
         return HttpResponse.ofFailure(HttpStatusException.of(HttpStatus.NOT_FOUND));
     }
     ...
 }
 
See Also:
  • Method Details

    • onServiceException

      Returns an HttpResponse for the given Throwable raised by a service. This method is invoked once for each request failed with a service-level exception.
      Parameters:
      ctx - the ServiceRequestContext of the current request.
      cause - the Throwable raised by the service that handled the current request.
      Returns:
      an HttpResponse to send to the client, or null to let the next handler specified with orElse(ServiceErrorHandler) handle the event.
    • renderStatus

      Returns an AggregatedHttpResponse generated from the given HttpStatus, message and Throwable. When null is returned, the next ServiceErrorHandler in the invocation chain will be used as a fallback (See orElse(ServiceErrorHandler) for more information).
      Parameters:
      config - the ServiceConfig that provides the configuration properties.
      headers - the received RequestHeaders.
      status - the desired HttpStatus of the error response.
      description - an optional human-readable description of the error.
      cause - an optional exception that may contain additional information about the error, such as IllegalArgumentException.
      Returns:
      an AggregatedHttpResponse, or null to let the next handler specified with orElse(ServiceErrorHandler) handle the event.
    • orElse

      default ServiceErrorHandler orElse(ServiceErrorHandler other)
      Returns a newly created ServiceErrorHandler that tries this ServiceErrorHandler first and then the specified ServiceErrorHandler when the first call returns null.
      
       ServiceErrorHandler handler = (ctx, cause) -> {
           if (cause instanceof FirstException) {
               return HttpResponse.of(200);
           }
           return null;
       }
       assert handler.onServiceException(ctx, new FirstException()) != null;
       assert handler.onServiceException(ctx, new SecondException()) == null;
       assert handler.onServiceException(ctx, new ThirdException()) == null;
      
       ServiceErrorHandler combinedHandler = handler.orElse((ctx, cause) -> {
           if (cause instanceof SecondException) {
               return HttpResponse.of(200);
           }
           return null;
       });
      
       assert combinedHandler.onServiceException(ctx, new FirstException()) != null;
       assert combinedHandler.onServiceException(ctx, new SecondException()) != null;
       assert combinedHandler.onServiceException(ctx, new ThirdException()) == null;
      
       // The default handler never returns null.
       ServiceErrorHandler nonNullHandler = combinedHandler.orElse(ServiceErrorHandler.ofDefault());
       assert nonNullHandler.onServiceException(ctx, new FirstException()) != null;
       assert nonNullHandler.onServiceException(ctx, new SecondException()) != null;
       assert nonNullHandler.onServiceException(ctx, new ThirdException()) != null;