package io.undertow.server.handlers;

import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.AttachmentKey;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

Handler that dispatches to a given handler and allows mapping exceptions to be handled by additional handlers. The order the exception handlers are added is important because of inheritance. Add all child classes before their parents in order to use different handlers.
/** * Handler that dispatches to a given handler and allows mapping exceptions * to be handled by additional handlers. The order the exception handlers are * added is important because of inheritance. Add all child classes before their * parents in order to use different handlers. */
public class ExceptionHandler implements HttpHandler { public static final AttachmentKey<Throwable> THROWABLE = AttachmentKey.create(Throwable.class); private final HttpHandler handler; private final List<ExceptionHandlerHolder<?>> exceptionHandlers = new CopyOnWriteArrayList<>(); public ExceptionHandler(HttpHandler handler) { this.handler = handler; } @Override public void handleRequest(HttpServerExchange exchange) throws Exception { try { handler.handleRequest(exchange); } catch (Throwable throwable) { for (ExceptionHandlerHolder<?> holder : exceptionHandlers) { if (holder.getClazz().isInstance(throwable)) { exchange.putAttachment(THROWABLE, throwable); holder.getHandler().handleRequest(exchange); return; } } throw throwable; } } public <T extends Throwable> ExceptionHandler addExceptionHandler(Class<T> clazz, HttpHandler handler) { exceptionHandlers.add(new ExceptionHandlerHolder<>(clazz, handler)); return this; } private static class ExceptionHandlerHolder<T extends Throwable> { private final Class<T> clazz; private final HttpHandler handler; ExceptionHandlerHolder(Class<T> clazz, HttpHandler handler) { super(); this.clazz = clazz; this.handler = handler; } public Class<T> getClazz() { return clazz; } public HttpHandler getHandler() { return handler; } } }