From da2a5753c53b801f96a161d26cc0fd951beb3905 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 23 Nov 2024 13:49:05 -0500 Subject: [PATCH 1/3] refactor error handling --- .../src/main/java/io/avaje/jex/DJex.java | 31 +------------- .../io/avaje/jex/DefaultErrorHandling.java | 40 ------------------ .../java/io/avaje/jex/DefaultRouting.java | 19 ++++++++- .../main/java/io/avaje/jex/ErrorHandling.java | 42 ------------------- avaje-jex/src/main/java/io/avaje/jex/Jex.java | 20 --------- .../src/main/java/io/avaje/jex/Routing.java | 13 +++++- .../main/java/io/avaje/jex/ServerConfig.java | 7 ---- .../{internal => }/CoreServiceLoader.java | 2 +- .../{internal => }/CoreServiceManager.java | 39 ++++++++++------- .../core/{internal => }/ExceptionManager.java | 32 ++++++++++---- .../core/{internal => }/HttpMethodMap.java | 6 +-- .../{internal => }/SpiServiceManager.java | 2 +- .../core/{ => json}/JacksonJsonService.java | 2 +- .../jex/core/{ => json}/JsonbJsonService.java | 2 +- .../io/avaje/jex/jdk/CtxServiceManager.java | 2 +- .../java/io/avaje/jex/jdk/JdkServerStart.java | 2 +- avaje-jex/src/main/java/module-info.java | 2 +- .../avaje/jex/DefaultErrorHandlingTest.java | 25 ++++++----- .../core/{internal => }/ContextUtilTest.java | 4 +- .../io/avaje/jex/jdk/JdkJexServerTest.java | 11 ++--- .../test/java/io/avaje/jex/jdk/JsonTest.java | 13 +++--- 21 files changed, 118 insertions(+), 198 deletions(-) delete mode 100644 avaje-jex/src/main/java/io/avaje/jex/DefaultErrorHandling.java delete mode 100644 avaje-jex/src/main/java/io/avaje/jex/ErrorHandling.java delete mode 100644 avaje-jex/src/main/java/io/avaje/jex/ServerConfig.java rename avaje-jex/src/main/java/io/avaje/jex/core/{internal => }/CoreServiceLoader.java (96%) rename avaje-jex/src/main/java/io/avaje/jex/core/{internal => }/CoreServiceManager.java (88%) rename avaje-jex/src/main/java/io/avaje/jex/core/{internal => }/ExceptionManager.java (71%) rename avaje-jex/src/main/java/io/avaje/jex/core/{internal => }/HttpMethodMap.java (91%) rename avaje-jex/src/main/java/io/avaje/jex/core/{internal => }/SpiServiceManager.java (97%) rename avaje-jex/src/main/java/io/avaje/jex/core/{ => json}/JacksonJsonService.java (98%) rename avaje-jex/src/main/java/io/avaje/jex/core/{ => json}/JsonbJsonService.java (97%) rename avaje-jex/src/test/java/io/avaje/jex/core/{internal => }/ContextUtilTest.java (90%) diff --git a/avaje-jex/src/main/java/io/avaje/jex/DJex.java b/avaje-jex/src/main/java/io/avaje/jex/DJex.java index 3cd3a211..1e6beab3 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/DJex.java +++ b/avaje-jex/src/main/java/io/avaje/jex/DJex.java @@ -1,8 +1,8 @@ package io.avaje.jex; import io.avaje.inject.BeanScope; +import io.avaje.jex.core.CoreServiceManager; import io.avaje.jex.core.HealthPlugin; -import io.avaje.jex.core.internal.CoreServiceManager; import io.avaje.jex.jdk.JdkServerStart; import io.avaje.jex.routes.RoutesBuilder; import io.avaje.jex.routes.SpiRoutes; @@ -14,12 +14,10 @@ final class DJex implements Jex { private final Routing routing = new DefaultRouting(); - private final ErrorHandling errorHandling = new DefaultErrorHandling(); private final AppLifecycle lifecycle = new DefaultLifecycle(); private final StaticFileConfig staticFiles; private final Map, Object> attributes = new HashMap<>(); private final DJexConfig config = new DJexConfig(); - private ServerConfig serverConfig; DJex() { this.staticFiles = new DefaultStaticFileConfig(this); @@ -43,28 +41,6 @@ public T attribute(Class cls) { return (T) attributes.get(cls); } - @Override - public Jex errorHandling(ErrorHandling.Service service) { - service.add(errorHandling); - return this; - } - - @Override - public ErrorHandling errorHandling() { - return errorHandling; - } - - @Override - public ServerConfig serverConfig() { - return serverConfig; - } - - @Override - public Jex serverConfig(ServerConfig serverConfig) { - this.serverConfig = serverConfig; - return this; - } - @Override public Jex routing(Routing.Service routes) { routing.add(routes); @@ -100,9 +76,6 @@ public Jex configureWith(BeanScope beanScope) { for (JexPlugin plugin : beanScope.list(JexPlugin.class)) { plugin.apply(this); } - for (ErrorHandling.Service service : beanScope.list(ErrorHandling.Service.class)) { - service.add(errorHandling); - } routing.addAll(beanScope.list(Routing.Service.class)); beanScope.getOptional(JsonService.class).ifPresent(this::jsonService); return this; @@ -116,7 +89,7 @@ public Jex configure(Consumer configure) { @Override public Jex exception(Class exceptionClass, ExceptionHandler handler) { - errorHandling.exception(exceptionClass, handler); + routing.exception(exceptionClass, handler); return this; } diff --git a/avaje-jex/src/main/java/io/avaje/jex/DefaultErrorHandling.java b/avaje-jex/src/main/java/io/avaje/jex/DefaultErrorHandling.java deleted file mode 100644 index 012eaf0e..00000000 --- a/avaje-jex/src/main/java/io/avaje/jex/DefaultErrorHandling.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.avaje.jex; - -import java.util.HashMap; -import java.util.Map; - -class DefaultErrorHandling implements ErrorHandling { - - private final Map, ExceptionHandler> handlers = new HashMap<>(); - - @Override - public ErrorHandling exception(Class type, ExceptionHandler handler) { - handlers.put(type, handler); - return this; - } - - @Override - public ErrorHandling error(int statusCode, Handler handler) { - return null; - } - - @Override - public ErrorHandling error(int statusCode, String contentType, Handler handler) { - return null; - } - - @Override - @SuppressWarnings("unchecked") - public ExceptionHandler find(Class exceptionType) { - Class type = exceptionType; - do { - final ExceptionHandler handler = handlers.get(type); - if (handler != null) { - return (ExceptionHandler) handler; - } - type = type.getSuperclass(); - } while (type != null); - return null; - } - -} diff --git a/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java b/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java index 2cf07e2f..f17eaeeb 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java +++ b/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java @@ -5,10 +5,15 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; -import java.util.function.Consumer; +import io.avaje.jex.Routing.Entry; +import io.avaje.jex.Routing.Group; +import io.avaje.jex.Routing.Service; +import io.avaje.jex.Routing.Type; import io.avaje.jex.security.Role; class DefaultRouting implements Routing { @@ -16,6 +21,7 @@ class DefaultRouting implements Routing { private final List handlers = new ArrayList<>(); private final List filters = new ArrayList<>(); private final Deque pathDeque = new ArrayDeque<>(); + private final Map, ExceptionHandler> exceptionHandlers = new HashMap<>(); /** * Last entry that we can add permitted roles to. @@ -32,6 +38,11 @@ public List filters() { return filters; } + @Override + public Map, ExceptionHandler> errorHandlers() { + return exceptionHandlers; + } + private String path(String path) { return String.join("", pathDeque) + ((path.startsWith("/") || path.isEmpty()) ? path : "/" + path); } @@ -57,6 +68,12 @@ public Routing addAll(Collection routes) { return this; } + @Override + public Routing exception(Class type, ExceptionHandler handler) { + exceptionHandlers.put(type, handler); + return this; + } + @Override public Routing path(String path, Group group) { addEndpoints(path, group); diff --git a/avaje-jex/src/main/java/io/avaje/jex/ErrorHandling.java b/avaje-jex/src/main/java/io/avaje/jex/ErrorHandling.java deleted file mode 100644 index 0df47c9c..00000000 --- a/avaje-jex/src/main/java/io/avaje/jex/ErrorHandling.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.avaje.jex; - -public interface ErrorHandling { - - /** - * Register an exception handler for the given exception type. - */ - ErrorHandling exception(Class exceptionClass, ExceptionHandler handler); - - /** - * Adds an error mapper to the instance. - * Useful for turning error-codes (404, 500) into standardized messages/pages - */ - ErrorHandling error(int statusCode, Handler handler); - - /** - * Adds an error mapper for the specified content-type to the instance. - * Useful for turning error-codes (404, 500) into standardized messages/pages - */ - ErrorHandling error(int statusCode, String contentType, Handler handler); - - /** - * Return a registered exception handler given the exception type or null - * if one is not found. - *

- * This includes searching the super types of the exception. - *

- */ - ExceptionHandler find(Class exceptionType); - - /** - * Adds to the Routing. - */ - @FunctionalInterface - interface Service { - - /** - * Add to the error handling. - */ - void add(ErrorHandling errorHandling); - } -} diff --git a/avaje-jex/src/main/java/io/avaje/jex/Jex.java b/avaje-jex/src/main/java/io/avaje/jex/Jex.java index a64824ba..0f33c1fe 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/Jex.java +++ b/avaje-jex/src/main/java/io/avaje/jex/Jex.java @@ -55,26 +55,6 @@ static Jex create() { */ T attribute(Class cls); - /** - * Configure error handlers. - */ - Jex errorHandling(ErrorHandling.Service service); - - /** - * Return the Error handler to add error handlers. - */ - ErrorHandling errorHandling(); - - /** - * Return the server specific configuration. - */ - ServerConfig serverConfig(); - - /** - * Set the server specific configuration. - */ - Jex serverConfig(ServerConfig serverConfig); - /** * Add routes and handlers to the routing. */ diff --git a/avaje-jex/src/main/java/io/avaje/jex/Routing.java b/avaje-jex/src/main/java/io/avaje/jex/Routing.java index c36022f6..65d9bc65 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/Routing.java +++ b/avaje-jex/src/main/java/io/avaje/jex/Routing.java @@ -2,6 +2,7 @@ import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Consumer; @@ -49,6 +50,11 @@ public interface Routing { */ Routing withRoles(Role... permittedRoles); + /** + * Register an exception handler for the given exception type. + */ + Routing exception(Class exceptionClass, ExceptionHandler handler); + /** * Add a group of route handlers with a common path prefix. */ @@ -141,7 +147,7 @@ default Routing before(Consumer handler) { /** Add a post-processing filter for all requests. */ default Routing after(Consumer handler) { - + return filter( (ctx, chain) -> { chain.proceed(); @@ -159,6 +165,11 @@ default Routing after(Consumer handler) { */ List filters(); + /** + * Return all the registered Exception Handlers. + */ + Map, ExceptionHandler> errorHandlers(); + /** * A group of routing entries prefixed by a common path. */ diff --git a/avaje-jex/src/main/java/io/avaje/jex/ServerConfig.java b/avaje-jex/src/main/java/io/avaje/jex/ServerConfig.java deleted file mode 100644 index 7f860f57..00000000 --- a/avaje-jex/src/main/java/io/avaje/jex/ServerConfig.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.avaje.jex; - -/** - * Marker for server specific configuration. - */ -public interface ServerConfig { -} diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/internal/CoreServiceLoader.java b/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceLoader.java similarity index 96% rename from avaje-jex/src/main/java/io/avaje/jex/core/internal/CoreServiceLoader.java rename to avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceLoader.java index 14cd73b4..459f056a 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/internal/CoreServiceLoader.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceLoader.java @@ -1,4 +1,4 @@ -package io.avaje.jex.core.internal; +package io.avaje.jex.core; import java.util.ArrayList; import java.util.List; diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/internal/CoreServiceManager.java b/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceManager.java similarity index 88% rename from avaje-jex/src/main/java/io/avaje/jex/core/internal/CoreServiceManager.java rename to avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceManager.java index 142cbef5..c2376d33 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/internal/CoreServiceManager.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceManager.java @@ -1,22 +1,28 @@ -package io.avaje.jex.core.internal; - -import io.avaje.applog.AppLog; -import io.avaje.jex.*; -import io.avaje.jex.core.JacksonJsonService; -import io.avaje.jex.core.JsonbJsonService; -import io.avaje.jex.core.TemplateManager; -import io.avaje.jex.spi.HeaderKeys; -import io.avaje.jex.spi.JsonService; -import io.avaje.jex.spi.SpiContext; -import io.avaje.jex.spi.TemplateRender; +package io.avaje.jex.core; import java.io.UncheckedIOException; import java.io.UnsupportedEncodingException; import java.lang.System.Logger.Level; import java.net.URLDecoder; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Stream; +import io.avaje.applog.AppLog; +import io.avaje.jex.Context; +import io.avaje.jex.Jex; +import io.avaje.jex.Routing; +import io.avaje.jex.core.json.JacksonJsonService; +import io.avaje.jex.core.json.JsonbJsonService; +import io.avaje.jex.spi.HeaderKeys; +import io.avaje.jex.spi.JsonService; +import io.avaje.jex.spi.SpiContext; +import io.avaje.jex.spi.TemplateRender; + /** * Core implementation of SpiServiceManager provided to specific implementations like jetty etc. */ @@ -34,9 +40,9 @@ public static SpiServiceManager create(Jex jex) { return new Builder(jex).build(); } - public CoreServiceManager(JsonService jsonService, ErrorHandling errorHandling, TemplateManager templateManager) { + CoreServiceManager(JsonService jsonService, ExceptionManager manager, TemplateManager templateManager) { this.jsonService = jsonService; - this.exceptionHandler = new ExceptionManager(errorHandling); + this.exceptionHandler = manager; this.templateManager = templateManager; } @@ -142,7 +148,10 @@ private static class Builder { } SpiServiceManager build() { - return new CoreServiceManager(initJsonService(), jex.errorHandling(), initTemplateMgr()); + return new CoreServiceManager( + initJsonService(), + new ExceptionManager(jex.routing().errorHandlers()), + initTemplateMgr()); } JsonService initJsonService() { diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/internal/ExceptionManager.java b/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java similarity index 71% rename from avaje-jex/src/main/java/io/avaje/jex/core/internal/ExceptionManager.java rename to avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java index 767277fe..b328a4b9 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/internal/ExceptionManager.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java @@ -1,29 +1,43 @@ -package io.avaje.jex.core.internal; +package io.avaje.jex.core; + +import static java.lang.System.Logger.Level.WARNING; + +import java.util.Map; import io.avaje.applog.AppLog; -import io.avaje.jex.ErrorHandling; import io.avaje.jex.ExceptionHandler; import io.avaje.jex.http.ErrorCode; import io.avaje.jex.http.HttpResponseException; import io.avaje.jex.spi.HeaderKeys; import io.avaje.jex.spi.SpiContext; -import static java.lang.System.Logger.Level.WARNING; - -class ExceptionManager { +public class ExceptionManager { private static final String APPLICATION_JSON = "application/json"; private static final System.Logger log = AppLog.getLogger("io.avaje.jex"); - private final ErrorHandling errorHandling; + private final Map, ExceptionHandler> handlers; + + public ExceptionManager(Map, ExceptionHandler> handlers) { + this.handlers = handlers; + } - ExceptionManager(ErrorHandling errorHandling) { - this.errorHandling = errorHandling; + @SuppressWarnings("unchecked") + public ExceptionHandler find(Class exceptionType) { + Class type = exceptionType; + do { + final ExceptionHandler handler = handlers.get(type); + if (handler != null) { + return (ExceptionHandler) handler; + } + type = type.getSuperclass(); + } while (type != null); + return null; } void handle(SpiContext ctx, Exception e) { - final ExceptionHandler handler = errorHandling.find(e.getClass()); + final ExceptionHandler handler = find(e.getClass()); if (handler != null) { handler.handle(e, ctx); } else if (e instanceof HttpResponseException ex) { diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/internal/HttpMethodMap.java b/avaje-jex/src/main/java/io/avaje/jex/core/HttpMethodMap.java similarity index 91% rename from avaje-jex/src/main/java/io/avaje/jex/core/internal/HttpMethodMap.java rename to avaje-jex/src/main/java/io/avaje/jex/core/HttpMethodMap.java index f8d1c2c5..5f76650c 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/internal/HttpMethodMap.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/HttpMethodMap.java @@ -1,10 +1,10 @@ -package io.avaje.jex.core.internal; - -import io.avaje.jex.Routing; +package io.avaje.jex.core; import java.util.HashMap; import java.util.Map; +import io.avaje.jex.Routing; + final class HttpMethodMap { private final Map map = new HashMap<>(); diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/internal/SpiServiceManager.java b/avaje-jex/src/main/java/io/avaje/jex/core/SpiServiceManager.java similarity index 97% rename from avaje-jex/src/main/java/io/avaje/jex/core/internal/SpiServiceManager.java rename to avaje-jex/src/main/java/io/avaje/jex/core/SpiServiceManager.java index 7eed68f8..b6b4822c 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/internal/SpiServiceManager.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/SpiServiceManager.java @@ -1,4 +1,4 @@ -package io.avaje.jex.core.internal; +package io.avaje.jex.core; import io.avaje.jex.Context; import io.avaje.jex.Routing; diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/JacksonJsonService.java b/avaje-jex/src/main/java/io/avaje/jex/core/json/JacksonJsonService.java similarity index 98% rename from avaje-jex/src/main/java/io/avaje/jex/core/JacksonJsonService.java rename to avaje-jex/src/main/java/io/avaje/jex/core/json/JacksonJsonService.java index 81b06cda..5b3f8d20 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/JacksonJsonService.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/json/JacksonJsonService.java @@ -1,4 +1,4 @@ -package io.avaje.jex.core; +package io.avaje.jex.core.json; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.DeserializationFeature; diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/JsonbJsonService.java b/avaje-jex/src/main/java/io/avaje/jex/core/json/JsonbJsonService.java similarity index 97% rename from avaje-jex/src/main/java/io/avaje/jex/core/JsonbJsonService.java rename to avaje-jex/src/main/java/io/avaje/jex/core/json/JsonbJsonService.java index a3825c50..77eaca95 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/JsonbJsonService.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/json/JsonbJsonService.java @@ -1,4 +1,4 @@ -package io.avaje.jex.core; +package io.avaje.jex.core.json; import io.avaje.jex.spi.JsonService; import io.avaje.jex.spi.SpiContext; diff --git a/avaje-jex/src/main/java/io/avaje/jex/jdk/CtxServiceManager.java b/avaje-jex/src/main/java/io/avaje/jex/jdk/CtxServiceManager.java index 68926fe0..93e93c33 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/jdk/CtxServiceManager.java +++ b/avaje-jex/src/main/java/io/avaje/jex/jdk/CtxServiceManager.java @@ -2,7 +2,7 @@ import io.avaje.jex.Context; import io.avaje.jex.Routing; -import io.avaje.jex.core.internal.SpiServiceManager; +import io.avaje.jex.core.SpiServiceManager; import io.avaje.jex.spi.SpiContext; import java.io.OutputStream; diff --git a/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkServerStart.java b/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkServerStart.java index a331f46e..157c4890 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkServerStart.java +++ b/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkServerStart.java @@ -13,7 +13,7 @@ import io.avaje.applog.AppLog; import io.avaje.jex.AppLifecycle; import io.avaje.jex.Jex; -import io.avaje.jex.core.internal.SpiServiceManager; +import io.avaje.jex.core.SpiServiceManager; import io.avaje.jex.routes.SpiRoutes; public class JdkServerStart { diff --git a/avaje-jex/src/main/java/module-info.java b/avaje-jex/src/main/java/module-info.java index d01cc5e0..ee1b7c88 100644 --- a/avaje-jex/src/main/java/module-info.java +++ b/avaje-jex/src/main/java/module-info.java @@ -4,7 +4,7 @@ exports io.avaje.jex; exports io.avaje.jex.http; - exports io.avaje.jex.core; + exports io.avaje.jex.core.json; exports io.avaje.jex.security; exports io.avaje.jex.spi; diff --git a/avaje-jex/src/test/java/io/avaje/jex/DefaultErrorHandlingTest.java b/avaje-jex/src/test/java/io/avaje/jex/DefaultErrorHandlingTest.java index bed06272..67dbf84d 100644 --- a/avaje-jex/src/test/java/io/avaje/jex/DefaultErrorHandlingTest.java +++ b/avaje-jex/src/test/java/io/avaje/jex/DefaultErrorHandlingTest.java @@ -1,10 +1,12 @@ package io.avaje.jex; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.nio.file.DirectoryIteratorException; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; + +import io.avaje.jex.core.ExceptionManager; class DefaultErrorHandlingTest { @@ -14,8 +16,10 @@ class DefaultErrorHandlingTest { @Test void exception() { - DefaultErrorHandling handling = new DefaultErrorHandling(); - handling.exception(RuntimeException.class, rt); + Routing router = new DefaultRouting(); + router.exception(RuntimeException.class, rt); + + var handling = new ExceptionManager(router.errorHandlers()); assertThat(handling.find(RuntimeException.class)).isSameAs(rt); assertThat(handling.find(IllegalStateException.class)).isSameAs(rt); @@ -24,10 +28,11 @@ void exception() { @Test void exception_expect_highestMatch() { + Routing router = new DefaultRouting(); + router.exception(RuntimeException.class, rt); + router.exception(IllegalStateException.class, ise); - DefaultErrorHandling handling = new DefaultErrorHandling(); - handling.exception(RuntimeException.class, rt); - handling.exception(IllegalStateException.class, ise); + var handling = new ExceptionManager(router.errorHandlers()); assertThat(handling.find(IllegalStateException.class)).isSameAs(ise); assertThat(handling.find(RuntimeException.class)).isSameAs(rt); @@ -37,14 +42,12 @@ void exception_expect_highestMatch() { private static class RT implements ExceptionHandler { @Override - public void handle(RuntimeException exception, Context ctx) { - } + public void handle(RuntimeException exception, Context ctx) {} } private static class ISE implements ExceptionHandler { @Override - public void handle(IllegalStateException exception, Context ctx) { - } + public void handle(IllegalStateException exception, Context ctx) {} } } diff --git a/avaje-jex/src/test/java/io/avaje/jex/core/internal/ContextUtilTest.java b/avaje-jex/src/test/java/io/avaje/jex/core/ContextUtilTest.java similarity index 90% rename from avaje-jex/src/test/java/io/avaje/jex/core/internal/ContextUtilTest.java rename to avaje-jex/src/test/java/io/avaje/jex/core/ContextUtilTest.java index ada6e09f..79dcb785 100644 --- a/avaje-jex/src/test/java/io/avaje/jex/core/internal/ContextUtilTest.java +++ b/avaje-jex/src/test/java/io/avaje/jex/core/ContextUtilTest.java @@ -1,8 +1,8 @@ -package io.avaje.jex.core.internal; +package io.avaje.jex.core; import org.junit.jupiter.api.Test; -import io.avaje.jex.core.internal.CoreServiceManager; +import io.avaje.jex.core.CoreServiceManager; import static org.assertj.core.api.Assertions.assertThat; diff --git a/avaje-jex/src/test/java/io/avaje/jex/jdk/JdkJexServerTest.java b/avaje-jex/src/test/java/io/avaje/jex/jdk/JdkJexServerTest.java index f284afcf..d13b5401 100644 --- a/avaje-jex/src/test/java/io/avaje/jex/jdk/JdkJexServerTest.java +++ b/avaje-jex/src/test/java/io/avaje/jex/jdk/JdkJexServerTest.java @@ -1,13 +1,14 @@ package io.avaje.jex.jdk; -import io.avaje.http.client.HttpClient; -import io.avaje.http.client.JacksonBodyAdapter; -import io.avaje.jex.Jex; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.net.http.HttpResponse; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; + +import io.avaje.http.client.HttpClient; +import io.avaje.http.client.JacksonBodyAdapter; +import io.avaje.jex.Jex; class JdkJexServerTest { diff --git a/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java b/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java index 8a61e434..e52c8f14 100644 --- a/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java +++ b/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java @@ -1,17 +1,18 @@ package io.avaje.jex.jdk; -import io.avaje.jex.Jex; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Test; +import static java.util.Arrays.asList; +import static java.util.stream.Collectors.toList; +import static org.assertj.core.api.Assertions.assertThat; import java.net.http.HttpHeaders; import java.net.http.HttpResponse; import java.util.List; import java.util.stream.Stream; -import static java.util.Arrays.asList; -import static java.util.stream.Collectors.toList; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import io.avaje.jex.Jex; class JsonTest { From 1ebf10d29e9f6bf10cb1e85ea503f0d9b7404a91 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 23 Nov 2024 14:02:40 -0500 Subject: [PATCH 2/3] seal interfaces --- .../main/java/io/avaje/jex/AppLifecycle.java | 2 +- .../main/java/io/avaje/jex/BootJexState.java | 4 +- .../main/java/io/avaje/jex/DJexConfig.java | 2 +- .../java/io/avaje/jex/DefaultRouting.java | 2 +- .../io/avaje/jex/DefaultStaticFileConfig.java | 2 +- avaje-jex/src/main/java/io/avaje/jex/Jex.java | 2 +- .../src/main/java/io/avaje/jex/JexConfig.java | 2 +- .../src/main/java/io/avaje/jex/Routing.java | 2 +- .../java/io/avaje/jex/StaticFileConfig.java | 2 +- .../java/io/avaje/jex/StaticFileSource.java | 56 +----------------- .../main/java/io/avaje/jex/UploadConfig.java | 59 +------------------ .../io/avaje/jex/core/CoreServiceLoader.java | 2 +- .../io/avaje/jex/core/ExceptionManager.java | 4 +- .../io/avaje/jex/core/TemplateManager.java | 2 +- 14 files changed, 20 insertions(+), 123 deletions(-) diff --git a/avaje-jex/src/main/java/io/avaje/jex/AppLifecycle.java b/avaje-jex/src/main/java/io/avaje/jex/AppLifecycle.java index 469f6f56..3eb8eafe 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/AppLifecycle.java +++ b/avaje-jex/src/main/java/io/avaje/jex/AppLifecycle.java @@ -3,7 +3,7 @@ /** * Application lifecycle support. */ -public interface AppLifecycle { +public sealed interface AppLifecycle permits DefaultLifecycle { enum Status { STARTING, diff --git a/avaje-jex/src/main/java/io/avaje/jex/BootJexState.java b/avaje-jex/src/main/java/io/avaje/jex/BootJexState.java index 34d9a0cb..49fb66c7 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/BootJexState.java +++ b/avaje-jex/src/main/java/io/avaje/jex/BootJexState.java @@ -3,7 +3,7 @@ import io.avaje.config.Config; import io.avaje.inject.BeanScope; -class BootJexState { +final class BootJexState { private static State state; @@ -32,7 +32,7 @@ State create(BeanScope beanScope) { return new State(jex.start()); } - private static class State { + private static final class State { private final Jex.Server server; diff --git a/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java b/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java index 51fe8356..50fc794b 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java +++ b/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java @@ -9,7 +9,7 @@ import io.avaje.jex.spi.JsonService; import io.avaje.jex.spi.TemplateRender; -class DJexConfig implements JexConfig { +final class DJexConfig implements JexConfig { private int port = 8080; private String host; diff --git a/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java b/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java index f17eaeeb..4b2ef8a9 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java +++ b/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java @@ -16,7 +16,7 @@ import io.avaje.jex.Routing.Type; import io.avaje.jex.security.Role; -class DefaultRouting implements Routing { +final class DefaultRouting implements Routing { private final List handlers = new ArrayList<>(); private final List filters = new ArrayList<>(); diff --git a/avaje-jex/src/main/java/io/avaje/jex/DefaultStaticFileConfig.java b/avaje-jex/src/main/java/io/avaje/jex/DefaultStaticFileConfig.java index 9e332a6d..3cd40916 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/DefaultStaticFileConfig.java +++ b/avaje-jex/src/main/java/io/avaje/jex/DefaultStaticFileConfig.java @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -class DefaultStaticFileConfig implements StaticFileConfig { +final class DefaultStaticFileConfig implements StaticFileConfig { private final List sources = new ArrayList<>(); private final Jex jex; diff --git a/avaje-jex/src/main/java/io/avaje/jex/Jex.java b/avaje-jex/src/main/java/io/avaje/jex/Jex.java index 0f33c1fe..14140b23 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/Jex.java +++ b/avaje-jex/src/main/java/io/avaje/jex/Jex.java @@ -23,7 +23,7 @@ * * } */ -public interface Jex { +public sealed interface Jex permits DJex { /** * Create Jex. diff --git a/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java b/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java index bbf3dbd1..2bec8634 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java +++ b/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java @@ -12,7 +12,7 @@ /** * Jex configuration. */ -public interface JexConfig { +public sealed interface JexConfig permits DJexConfig { /** * Set the port to use. Defaults to 7001. diff --git a/avaje-jex/src/main/java/io/avaje/jex/Routing.java b/avaje-jex/src/main/java/io/avaje/jex/Routing.java index 65d9bc65..064715a6 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/Routing.java +++ b/avaje-jex/src/main/java/io/avaje/jex/Routing.java @@ -8,7 +8,7 @@ import io.avaje.jex.security.Role; -public interface Routing { +public sealed interface Routing permits DefaultRouting { /** * Add the routes provided by the Routing Service. diff --git a/avaje-jex/src/main/java/io/avaje/jex/StaticFileConfig.java b/avaje-jex/src/main/java/io/avaje/jex/StaticFileConfig.java index 8138e0bb..a14f4f07 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/StaticFileConfig.java +++ b/avaje-jex/src/main/java/io/avaje/jex/StaticFileConfig.java @@ -2,7 +2,7 @@ import java.util.List; -public interface StaticFileConfig { +public sealed interface StaticFileConfig permits DefaultStaticFileConfig { Jex addClasspath(String path); diff --git a/avaje-jex/src/main/java/io/avaje/jex/StaticFileSource.java b/avaje-jex/src/main/java/io/avaje/jex/StaticFileSource.java index 327264b2..e5bc6a3b 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/StaticFileSource.java +++ b/avaje-jex/src/main/java/io/avaje/jex/StaticFileSource.java @@ -1,59 +1,9 @@ package io.avaje.jex; -import java.util.Objects; - -public class StaticFileSource { +public record StaticFileSource(String urlPathPrefix, String path, Location location) { public enum Location { - CLASSPATH, EXTERNAL + CLASSPATH, + EXTERNAL } - - private final String urlPathPrefix; - private final String path; - private final Location location; - - public StaticFileSource(String urlPathPrefix, String path, Location location) { - this.urlPathPrefix = urlPathPrefix; - this.path = path; - this.location = location; - } - - public String getUrlPathPrefix() { - return urlPathPrefix; - } - - public String getPath() { - return path; - } - - public Location getLocation() { - return location; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - StaticFileSource that = (StaticFileSource) o; - return urlPathPrefix.equals(that.urlPathPrefix) && - path.equals(that.path) && - location == that.location; - } - - @Override - public int hashCode() { - return Objects.hash(urlPathPrefix, path, location); - } - - @Override - public String toString() { - return "urlPathPrefix: " + urlPathPrefix - + ", path: " + path - + ", location: " + location; - } - } diff --git a/avaje-jex/src/main/java/io/avaje/jex/UploadConfig.java b/avaje-jex/src/main/java/io/avaje/jex/UploadConfig.java index 640bc08a..751c8172 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/UploadConfig.java +++ b/avaje-jex/src/main/java/io/avaje/jex/UploadConfig.java @@ -1,58 +1,5 @@ package io.avaje.jex; -/** - * Configuration for server handling of Multipart file uploads etc. - */ -public class UploadConfig { - - private String location; - private long maxFileSize; - private long maxRequestSize; - private int fileSizeThreshold; - - public UploadConfig() { - } - - public UploadConfig(String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold) { - this.location = location; - this.maxFileSize = maxFileSize; - this.maxRequestSize = maxRequestSize; - this.fileSizeThreshold = fileSizeThreshold; - } - - public String location() { - return location; - } - - public UploadConfig location(String location) { - this.location = location; - return this; - } - - public long maxFileSize() { - return maxFileSize; - } - - public UploadConfig maxFileSize(long maxFileSize) { - this.maxFileSize = maxFileSize; - return this; - } - - public long maxRequestSize() { - return maxRequestSize; - } - - public UploadConfig maxRequestSize(long maxRequestSize) { - this.maxRequestSize = maxRequestSize; - return this; - } - - public int fileSizeThreshold() { - return fileSizeThreshold; - } - - public UploadConfig fileSizeThreshold(int fileSizeThreshold) { - this.fileSizeThreshold = fileSizeThreshold; - return this; - } -} +/** Configuration for server handling of Multipart file uploads etc. */ +public record UploadConfig( + String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold) {} diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceLoader.java b/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceLoader.java index 459f056a..56fe2962 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceLoader.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/CoreServiceLoader.java @@ -10,7 +10,7 @@ import io.avaje.jex.spi.TemplateRender; /** Core implementation of SpiServiceManager provided to specific implementations like jetty etc. */ -class CoreServiceLoader { +final class CoreServiceLoader { private static final CoreServiceLoader INSTANCE = new CoreServiceLoader(); diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java b/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java index b328a4b9..18db0f79 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java @@ -11,7 +11,7 @@ import io.avaje.jex.spi.HeaderKeys; import io.avaje.jex.spi.SpiContext; -public class ExceptionManager { +public final class ExceptionManager { private static final String APPLICATION_JSON = "application/json"; @@ -24,7 +24,7 @@ public ExceptionManager(Map, ExceptionHandler> handlers) { } @SuppressWarnings("unchecked") - public ExceptionHandler find(Class exceptionType) { + private ExceptionHandler find(Class exceptionType) { Class type = exceptionType; do { final ExceptionHandler handler = handlers.get(type); diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/TemplateManager.java b/avaje-jex/src/main/java/io/avaje/jex/core/TemplateManager.java index 4de183ac..5bd38274 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/TemplateManager.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/TemplateManager.java @@ -11,7 +11,7 @@ /** * Render templates typically as html. */ -public class TemplateManager { +public final class TemplateManager { private final Map map = new HashMap<>(); From 5cbc23e5381419430cd0d61284f5188352c0c4eb Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 23 Nov 2024 14:03:47 -0500 Subject: [PATCH 3/3] Update ExceptionManager.java --- avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java b/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java index 18db0f79..481944ce 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/ExceptionManager.java @@ -24,7 +24,7 @@ public ExceptionManager(Map, ExceptionHandler> handlers) { } @SuppressWarnings("unchecked") - private ExceptionHandler find(Class exceptionType) { + public ExceptionHandler find(Class exceptionType) { Class type = exceptionType; do { final ExceptionHandler handler = handlers.get(type);