From 22cefa4f5b498c7eac7ff38e633dcbcb071b8d1a Mon Sep 17 00:00:00 2001 From: Joshua Bauer Date: Tue, 21 May 2019 13:51:26 -0700 Subject: [PATCH] Support for wrapper DI. --- .../sinistral/proteus/ProteusApplication.java | 10 +-- .../proteus/modules/ApplicationModule.java | 7 +- .../proteus/server/ServerResponse.java | 2 +- .../server/handlers/HandlerGenerator.java | 79 +++++++------------ .../proteus/test/controllers/Tests.java | 13 ++- .../test/server/TestControllerEndpoints.java | 2 +- .../test/wrappers/TestClassWrapper.java | 23 ++++++ .../proteus/test/wrappers/TestWrapper.java | 38 +++++++++ core/src/test/resources/application.conf | 2 +- 9 files changed, 111 insertions(+), 65 deletions(-) create mode 100644 core/src/test/java/io/sinistral/proteus/test/wrappers/TestClassWrapper.java create mode 100644 core/src/test/java/io/sinistral/proteus/test/wrappers/TestWrapper.java diff --git a/core/src/main/java/io/sinistral/proteus/ProteusApplication.java b/core/src/main/java/io/sinistral/proteus/ProteusApplication.java index ed1595a..5fb8e74 100644 --- a/core/src/main/java/io/sinistral/proteus/ProteusApplication.java +++ b/core/src/main/java/io/sinistral/proteus/ProteusApplication.java @@ -14,14 +14,10 @@ import com.google.inject.name.Named; import com.typesafe.config.Config; import io.sinistral.proteus.modules.ConfigModule; -import io.sinistral.proteus.modules.JacksonModule; -import io.sinistral.proteus.server.Extractors; -import io.sinistral.proteus.server.ServerResponse; import io.sinistral.proteus.server.endpoints.EndpointInfo; import io.sinistral.proteus.server.handlers.HandlerGenerator; import io.sinistral.proteus.server.handlers.ServerDefaultHttpHandler; import io.sinistral.proteus.services.BaseService; -import io.sinistral.proteus.services.DefaultService; import io.sinistral.proteus.utilities.SecurityOps; import io.sinistral.proteus.utilities.TablePrinter; import io.undertow.Undertow; @@ -48,7 +44,11 @@ import java.nio.file.Paths; import java.security.KeyStore; import java.time.Duration; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/core/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java b/core/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java index 0d5bb9e..841cb02 100644 --- a/core/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java +++ b/core/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java @@ -1,12 +1,8 @@ package io.sinistral.proteus.modules; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; -import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; -import com.fasterxml.jackson.module.afterburner.AfterburnerModule; import com.google.inject.AbstractModule; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; @@ -16,7 +12,6 @@ import io.sinistral.proteus.server.ServerResponse; import io.sinistral.proteus.server.endpoints.EndpointInfo; import io.sinistral.proteus.services.BaseService; -import io.sinistral.proteus.services.DefaultService; import io.sinistral.proteus.wrappers.JsonViewWrapper; import io.undertow.server.DefaultResponseListener; import io.undertow.server.HandlerWrapper; @@ -39,6 +34,7 @@ public class ApplicationModule extends AbstractModule protected Set> registeredControllers = new HashSet<>(); protected Set> registeredServices = new HashSet<>(); protected Map registeredHandlerWrappers = new HashMap<>(); + protected Config config; public ApplicationModule(Config config) @@ -148,6 +144,7 @@ protected void configure() this.bind(new TypeLiteral>() { }).annotatedWith(Names.named("registeredHandlerWrappers")).toInstance(registeredHandlerWrappers); + } } diff --git a/core/src/main/java/io/sinistral/proteus/server/ServerResponse.java b/core/src/main/java/io/sinistral/proteus/server/ServerResponse.java index 9b76490..92b0379 100644 --- a/core/src/main/java/io/sinistral/proteus/server/ServerResponse.java +++ b/core/src/main/java/io/sinistral/proteus/server/ServerResponse.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.google.inject.Inject; import io.sinistral.proteus.server.predicates.ServerPredicates; -import io.sinistral.proteus.wrappers.JsonViewWrapper; +import io.sinistral.proteus.test.wrappers.JsonViewWrapper; import io.undertow.io.IoCallback; import io.undertow.server.DefaultResponseListener; import io.undertow.server.HttpHandler; diff --git a/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java b/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java index 4047942..e8364f7 100644 --- a/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java +++ b/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java @@ -84,9 +84,9 @@ public enum StatementParameterType @Named("registeredHandlerWrappers") protected Map registeredHandlerWrappers; - protected Map, String> typeLevelHandlerWrapperMap = new LinkedHashMap<>(); + protected Map> registeredWrapperTypes = new HashMap<>(); - protected Map, String> handlerWrapperMap = new LinkedHashMap<>(); + protected Map, String> typeLevelHandlerWrapperMap = new LinkedHashMap<>(); /** * Create a new {@code HandlerGenerator} instance used to generate a @@ -129,51 +129,6 @@ protected void generateRoutes() { try { -// Optional typeLevelWrapAnnotation = Optional.ofNullable(controllerClass.getAnnotation(io.sinistral.proteus.annotations.Chain.class)); -// -// typeLevelWrapAnnotation.ifPresent( a -> { -// -// io.sinistral.proteus.annotations.Chain w = typeLevelWrapAnnotation.get(); -// -// Class wrapperClasses[] = w.value(); -// -// for (int i = 0; i < wrapperClasses.length; i++) -// { -// Class wrapperClass = wrapperClasses[i]; -// -// String wrapperName = generateFieldName(wrapperClass.getCanonicalName()); -// -// handlerWrapperMap.put(wrapperClass, wrapperName); -// } -// -// }); -// -// for(Method m : this.controllerClass.getDeclaredMethods()) -// { -// -// Optional methodLevelWrapAnnotation = Optional.ofNullable(m.getAnnotation(io.sinistral.proteus.annotations.Chain.class)); -// -// methodLevelWrapAnnotation.ifPresent( a -> { -// -// io.sinistral.proteus.annotations.Chain w = methodLevelWrapAnnotation.get(); -// -// Class wrapperClasses[] = w.value(); -// -// for (int i = 0; i < wrapperClasses.length; i++) -// { -// Class wrapperClass = wrapperClasses[i]; -// -// String wrapperName = generateFieldName(wrapperClass.getCanonicalName()); -// -// handlerWrapperMap.put(wrapperClass, wrapperName); -// } -// -// }); -// -// } -// -// log.info("handlerWrapperMap: " + handlerWrapperMap); - TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC) .addSuperinterface(ParameterizedTypeName.get(Supplier.class, RoutingHandler.class)); @@ -199,7 +154,6 @@ protected void generateRoutes() typeBuilder.addField(mapOfWrappers, "registeredHandlerWrappers", Modifier.PROTECTED, Modifier.FINAL); - constructor.addParameter(this.controllerClass, className); constructor.addParameter(annotatedMapOfWrappers, "registeredHandlerWrappers"); @@ -208,6 +162,17 @@ protected void generateRoutes() addClassMethodHandlers(typeBuilder, this.controllerClass); + registeredWrapperTypes.forEach((key, value) -> { + + TypeName typeName = TypeName.get(value); + + typeBuilder.addField(typeName, key, Modifier.PROTECTED, Modifier.FINAL); + + constructor.addParameter(typeName, key); + + constructor.addStatement("this.$N = $N", key, key); + }); + typeBuilder.addMethod(constructor.build()); JavaFile javaFile = JavaFile.builder(packageName, typeBuilder.build()).addStaticImport(extractorClass, "*").build(); @@ -329,6 +294,9 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla Optional typeLevelWrapAnnotation = Optional.ofNullable(clazz.getAnnotation(io.sinistral.proteus.annotations.Chain.class)); + /* + CLASS LEVEL WRAPPERS + */ if (typeLevelWrapAnnotation.isPresent()) { io.sinistral.proteus.annotations.Chain w = typeLevelWrapAnnotation.get(); @@ -336,9 +304,10 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla Class[] wrapperClasses = w.value(); for (Class wrapperClass : wrapperClasses) { + String wrapperName = generateFieldName(wrapperClass.getCanonicalName()); - initBuilder.addStatement("final $T $L = new $T()", wrapperClass, wrapperName, wrapperClass); + registeredWrapperTypes.put(wrapperName,wrapperClass); typeLevelHandlerWrapperMap.put(wrapperClass, wrapperName); } @@ -821,6 +790,8 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla } + + if (wrapAnnotation.isPresent() || typeLevelHandlerWrapperMap.size() > 0 || securityDefinitions.size() > 0) { initBuilder.addStatement("currentHandler = $L", handlerName); @@ -835,16 +806,22 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla if (wrapperName == null) { wrapperName = String.format("%s_%d", generateFieldName(wrapperClass.getCanonicalName()), handlerWrapperIndex++); - initBuilder.addStatement("final $T $L = new $T()", wrapperClass, wrapperName, wrapperClass); + } initBuilder.addStatement("currentHandler = $L.wrap($L)", wrapperName, "currentHandler"); + + registeredWrapperTypes.put(wrapperName,wrapperClass); + } } for (Class wrapperClass : typeLevelHandlerWrapperMap.keySet()) { String wrapperName = typeLevelHandlerWrapperMap.get(wrapperClass); initBuilder.addStatement("currentHandler = $L.wrap($L)", wrapperName, "currentHandler"); + + registeredWrapperTypes.put(wrapperName,wrapperClass); + } for (String securityDefinitionName : securityDefinitions) { @@ -856,6 +833,8 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla initBuilder.addStatement("$L.add(io.undertow.util.Methods.$L,$S,$L)", "router", httpMethod, methodPath, handlerName); } + + initBuilder.addCode("$L", "\n"); registeredEndpoints.add(endpointInfo); diff --git a/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java b/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java index aa852b6..8d43c66 100644 --- a/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java +++ b/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java @@ -4,6 +4,7 @@ package io.sinistral.proteus.test.controllers; import static io.sinistral.proteus.server.ServerResponse.response; +import static io.sinistral.proteus.test.wrappers.TestWrapper.DEBUG_TEST_KEY; import java.io.File; import java.nio.ByteBuffer; @@ -37,10 +38,13 @@ import com.google.inject.Singleton; import io.sinistral.proteus.annotations.Blocking; +import io.sinistral.proteus.annotations.Chain; import io.sinistral.proteus.server.ServerRequest; import io.sinistral.proteus.server.ServerResponse; import io.sinistral.proteus.test.models.User; +import io.sinistral.proteus.test.wrappers.TestClassWrapper; +import io.sinistral.proteus.test.wrappers.TestWrapper; import io.undertow.server.HttpServerExchange; /** @@ -53,6 +57,7 @@ @Produces((MediaType.APPLICATION_JSON)) @Consumes((MediaType.MEDIA_TYPE_WILDCARD)) @Singleton +@Chain({TestClassWrapper.class}) public class Tests { private static final ByteBuffer buffer; @@ -351,13 +356,17 @@ public ServerResponse pathParamEndpoint(ServerRequest request, @Path @GET @Path("response/debug") - public ServerResponse> debugEndpoint(ServerRequest request) + @Chain({TestWrapper.class}) + public ServerResponse> debugEndpoint(ServerRequest request) { try { - Map map = ImmutableMap.of("message", "Hello, World!"); + String testString = request.getExchange().getAttachment(DEBUG_TEST_KEY); + + Map map = ImmutableMap.of("message", "Hello, World!","attachment",testString); return response( map ).applicationJson(); + } catch(Exception e) { return response().badRequest(e); diff --git a/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java b/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java index 64aaf53..a34e872 100644 --- a/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java +++ b/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java @@ -81,7 +81,7 @@ public void setUp() @Test public void testDebugEndpoint() { - given().accept(ContentType.JSON).when().get("tests/response/debug").then().statusCode(200); + given().accept(ContentType.JSON).when().get("tests/response/debug").then().statusCode(200).body(containsString("testValue")); } @Test diff --git a/core/src/test/java/io/sinistral/proteus/test/wrappers/TestClassWrapper.java b/core/src/test/java/io/sinistral/proteus/test/wrappers/TestClassWrapper.java new file mode 100644 index 0000000..c2a5c59 --- /dev/null +++ b/core/src/test/java/io/sinistral/proteus/test/wrappers/TestClassWrapper.java @@ -0,0 +1,23 @@ +package io.sinistral.proteus.test.wrappers; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import io.undertow.server.HandlerWrapper; +import io.undertow.server.HttpHandler; +import io.undertow.util.AttachmentKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestClassWrapper implements HandlerWrapper +{ + + + @Override + public HttpHandler wrap(HttpHandler handler) + { + return exchange -> { + + handler.handleRequest(exchange); + }; + } +} diff --git a/core/src/test/java/io/sinistral/proteus/test/wrappers/TestWrapper.java b/core/src/test/java/io/sinistral/proteus/test/wrappers/TestWrapper.java new file mode 100644 index 0000000..0452c21 --- /dev/null +++ b/core/src/test/java/io/sinistral/proteus/test/wrappers/TestWrapper.java @@ -0,0 +1,38 @@ +package io.sinistral.proteus.test.wrappers; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import io.undertow.server.HandlerWrapper; +import io.undertow.server.HttpHandler; +import io.undertow.util.AttachmentKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestWrapper implements HandlerWrapper +{ + private static final Logger log = LoggerFactory.getLogger(TestWrapper.class.getName()); + + public static AttachmentKey DEBUG_TEST_KEY = AttachmentKey.create(String.class); + + public TestWrapper() + { + super(); + } + + @Inject + @Named("test.wrapper.value") + private String wrapperValue; + + @Override + public HttpHandler wrap(HttpHandler handler) + { + return exchange -> { + + log.debug("Test wrapper"); + + exchange.putAttachment(DEBUG_TEST_KEY,wrapperValue); + + handler.handleRequest(exchange); + }; + } +} diff --git a/core/src/test/resources/application.conf b/core/src/test/resources/application.conf index ddd47d4..c912960 100644 --- a/core/src/test/resources/application.conf +++ b/core/src/test/resources/application.conf @@ -54,7 +54,7 @@ assets { } - +test.wrapper.value = "testValue"