diff --git a/aws-serverless-java-container-springboot2/pom.xml b/aws-serverless-java-container-springboot2/pom.xml new file mode 100644 index 000000000..f0a8258a3 --- /dev/null +++ b/aws-serverless-java-container-springboot2/pom.xml @@ -0,0 +1,171 @@ + + + + aws-serverless-java-container + com.amazonaws.serverless + 1.4-SNAPSHOT + + 4.0.0 + + com.amazonaws.serverless + aws-serverless-java-container-springboot2 + AWS Serverless Java container support - SpringBoot 2 implementation + Allows Java applications written for SpringBoot 2 to run in AWS Lambda + https://aws.amazon.com/lambda + 1.4-SNAPSHOT + + + 5.1.9.RELEASE + 2.1.8.RELEASE + + 1.8 + 1.8 + + + + + + com.amazonaws.serverless + aws-serverless-java-container-core + 1.4-SNAPSHOT + + + + org.springframework + spring-webflux + ${spring.version} + true + + + org.springframework.boot + spring-boot + ${springboot.version} + true + + + org.springframework.boot + spring-boot-autoconfigure + ${springboot.version} + true + + + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.1 + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + default-prepare-agent + + prepare-agent + + + + jacoco-site + package + + report + + + + jacoco-check + test + + check + + + true + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + ${jacoco.minCoverage} + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.9 + + always + + + + com.github.spotbugs + spotbugs-maven-plugin + 3.1.1 + + + Max + + Low + + true + + ${project.build.directory}/spotbugs + + + + com.h3xstream.findsecbugs + findsecbugs-plugin + 1.7.1 + + + + + + + analyze-compile + compile + + check + + + + + + org.owasp + dependency-check-maven + ${dependencyCheck.version} + + true + + ${project.basedir}/../owasp-suppression.xml + + 7 + + + + + check + + + + + + + diff --git a/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandler.java b/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandler.java new file mode 100644 index 000000000..c111b2c87 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandler.java @@ -0,0 +1,204 @@ +/* + * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance + * with the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES + * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.serverless.proxy.spring; + +import com.amazonaws.serverless.exceptions.ContainerInitializationException; +import com.amazonaws.serverless.proxy.*; +import com.amazonaws.serverless.proxy.internal.servlet.*; +import com.amazonaws.serverless.proxy.internal.testutils.Timer; +import com.amazonaws.serverless.proxy.model.AwsProxyRequest; +import com.amazonaws.serverless.proxy.model.AwsProxyResponse; +import com.amazonaws.serverless.proxy.spring.embedded.ServerlessReactiveEmbeddedServerFactory; +import com.amazonaws.serverless.proxy.spring.embedded.ServerlessServletEmbeddedServerFactory; +import com.amazonaws.services.lambda.runtime.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.StandardEnvironment; + +import javax.servlet.Servlet; +import java.util.concurrent.CountDownLatch; + +/** + * SpringBoot 1.x implementation of the `LambdaContainerHandler` abstract class. This class uses the `LambdaSpringApplicationInitializer` + * object behind the scenes to proxy requests. The default implementation leverages the `AwsProxyHttpServletRequest` and + * `AwsHttpServletResponse` implemented in the `aws-serverless-java-container-core` package. + * + * Important: Make sure to add LambdaFlushResponseListener in your SpringBootServletInitializer subclass configure(). + * + * @param The incoming event type + * @param The expected return type + */ +public class SpringBootLambdaContainerHandler extends AwsLambdaServletContainerHandler { + private final Class springBootInitializer; + private static final Logger log = LoggerFactory.getLogger(SpringBootLambdaContainerHandler.class); + private String[] springProfiles = null; + + private static SpringBootLambdaContainerHandler instance; + + // State vars + private boolean initialized; + + /** + * We need to rely on the static instance of this for SpringBoot because we need it to access the ServletContext. + * Normally, SpringBoot would initialize its own embedded container through the SpringApplication.run() + * method. However, in our case we need to rely on the pre-initialized handler and need to fetch information from it + * for our mock {@link com.amazonaws.serverless.proxy.spring.embedded.ServerlessReactiveEmbeddedServerFactory}. + * + * @return The initialized instance + */ + public static SpringBootLambdaContainerHandler getInstance() { + return instance; + } + + /** + * Creates a default SpringLambdaContainerHandler initialized with the `AwsProxyRequest` and `AwsProxyResponse` objects + * @param springBootInitializer {@code SpringBootServletInitializer} class + * @return An initialized instance of the `SpringLambdaContainerHandler` + * @throws ContainerInitializationException If an error occurs while initializing the Spring framework + */ + public static SpringBootLambdaContainerHandler getAwsProxyHandler(Class springBootInitializer) + throws ContainerInitializationException { + SpringBootLambdaContainerHandler newHandler = new SpringBootLambdaContainerHandler<>( + AwsProxyRequest.class, + AwsProxyResponse.class, + new AwsProxyHttpServletRequestReader(), + new AwsProxyHttpServletResponseWriter(), + new AwsProxySecurityContextWriter(), + new AwsProxyExceptionHandler(), + springBootInitializer); + newHandler.initialize(); + return newHandler; + } + + /** + * Creates a default SpringLambdaContainerHandler initialized with the `AwsProxyRequest` and `AwsProxyResponse` objects and the given Spring profiles + * @param springBootInitializer {@code SpringBootServletInitializer} class + * @param profiles A list of Spring profiles to activate + * @return An initialized instance of the `SpringLambdaContainerHandler` + * @throws ContainerInitializationException If an error occurs while initializing the Spring framework + */ + public static SpringBootLambdaContainerHandler getAwsProxyHandler(Class springBootInitializer, String... profiles) + throws ContainerInitializationException { + SpringBootLambdaContainerHandler newHandler = new SpringBootLambdaContainerHandler<>( + AwsProxyRequest.class, + AwsProxyResponse.class, + new AwsProxyHttpServletRequestReader(), + new AwsProxyHttpServletResponseWriter(), + new AwsProxySecurityContextWriter(), + new AwsProxyExceptionHandler(), + springBootInitializer); + newHandler.activateSpringProfiles(profiles); + newHandler.initialize(); + return newHandler; + } + + /** + * Creates a new container handler with the given reader and writer objects + * + * @param requestTypeClass The class for the incoming Lambda event + * @param requestReader An implementation of `RequestReader` + * @param responseWriter An implementation of `ResponseWriter` + * @param securityContextWriter An implementation of `SecurityContextWriter` + * @param exceptionHandler An implementation of `ExceptionHandler` + * @param springBootInitializer {@code SpringBootServletInitializer} class + * @throws ContainerInitializationException If an error occurs while initializing the Spring framework + */ + public SpringBootLambdaContainerHandler(Class requestTypeClass, + Class responseTypeClass, + RequestReader requestReader, + ResponseWriter responseWriter, + SecurityContextWriter securityContextWriter, + ExceptionHandler exceptionHandler, + Class springBootInitializer) + throws ContainerInitializationException { + super(requestTypeClass, responseTypeClass, requestReader, responseWriter, securityContextWriter, exceptionHandler); + Timer.start("SPRINGBOOT_CONTAINER_HANDLER_CONSTRUCTOR"); + initialized = false; + this.springBootInitializer = springBootInitializer; + SpringBootLambdaContainerHandler.setInstance(this); + + Timer.stop("SPRINGBOOT_CONTAINER_HANDLER_CONSTRUCTOR"); + } + + // this is not pretty. However, because SpringBoot wants to control all of the initialization + // we need to access this handler as a singleton from the EmbeddedContainer to set the servlet + // context and from the ServletConfigurationSupport implementation + private static void setInstance(SpringBootLambdaContainerHandler h) { + SpringBootLambdaContainerHandler.instance = h; + } + + public void activateSpringProfiles(String... profiles) { + springProfiles = profiles; + // force a re-initialization + initialized = false; + } + + @Override + protected AwsHttpServletResponse getContainerResponse(AwsProxyHttpServletRequest request, CountDownLatch latch) { + return new AwsHttpServletResponse(request, latch); + } + + @Override + protected void handleRequest(AwsProxyHttpServletRequest containerRequest, AwsHttpServletResponse containerResponse, Context lambdaContext) throws Exception { + // this method of the AwsLambdaServletContainerHandler sets the servlet context + Timer.start("SPRINGBOOT_HANDLE_REQUEST"); + + // wire up the application context on the first invocation + if (!initialized) { + initialize(); + } + + containerRequest.setServletContext(getServletContext()); + + // process filters & invoke servlet + Servlet reqServlet = ((AwsServletContext)getServletContext()).getServletForPath(containerRequest.getPathInfo()); + doFilter(containerRequest, containerResponse, reqServlet); + Timer.stop("SPRINGBOOT_HANDLE_REQUEST"); + } + + + @Override + public void initialize() + throws ContainerInitializationException { + Timer.start("SPRINGBOOT_COLD_START"); + + SpringApplication app = new SpringApplication(getEmbeddedContainerClasses()); + if (springProfiles != null && springProfiles.length > 0) { + ConfigurableEnvironment springEnv = new StandardEnvironment(); + springEnv.setActiveProfiles(springProfiles); + app.setEnvironment(springEnv); + } + + app.run(); + + initialized = true; + Timer.stop("SPRINGBOOT_COLD_START"); + } + + private Class[] getEmbeddedContainerClasses() { + Class[] classes = new Class[2]; + try { + // if HandlerAdapter is available we assume they are using WebFlux. Otherwise plain servlet. + this.getClass().getClassLoader().loadClass("org.springframework.web.reactive.HandlerAdapter"); + log.debug("Found WebFlux HandlerAdapter on classpath, using reactive server factory"); + classes[0] = ServerlessReactiveEmbeddedServerFactory.class; + } catch (ClassNotFoundException e) { + classes[0] = ServerlessServletEmbeddedServerFactory.class; + } + + classes[1] = springBootInitializer; + return classes; + } +} diff --git a/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessReactiveEmbeddedServerFactory.java b/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessReactiveEmbeddedServerFactory.java new file mode 100644 index 000000000..94a9d2074 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessReactiveEmbeddedServerFactory.java @@ -0,0 +1,93 @@ +package com.amazonaws.serverless.proxy.spring.embedded; + +import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.WebServerException; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; + +import javax.servlet.*; +import java.io.IOException; +import java.util.Enumeration; + +@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) +public class ServerlessReactiveEmbeddedServerFactory extends AbstractReactiveWebServerFactory implements WebServer, Servlet { + private ServletHttpHandlerAdapter handler; + private ServletConfig config; + static final String SERVLET_NAME = "com.amazonaws.serverless.proxy.spring.embedded.ServerlessReactiveEmbeddedServerFactory"; + static final String SERVLET_INFO = "ServerlessReactiveEmbeddedServerFactory"; + + @Override + @SuppressFBWarnings("MTIA_SUSPECT_SERVLET_INSTANCE_FIELD") + public WebServer getWebServer(HttpHandler httpHandler) { + handler = new ServletHttpHandlerAdapter(httpHandler); + return this; + } + + @Override + public void start() throws WebServerException { + // register this object as the main handler servlet with a mapping of / + SpringBootLambdaContainerHandler + .getInstance() + .getServletContext() + .addServlet(SERVLET_NAME, this) + .addMapping("/"); + handler.init(new ServletAdapterConfig()); + } + + @Override + public void stop() throws WebServerException { + // nothing to do here. + } + + @Override + public void init(ServletConfig servletConfig) throws ServletException { + config = servletConfig; + } + + @Override + public ServletConfig getServletConfig() { + return config; + } + + @Override + public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { + handler.service(servletRequest, servletResponse); + } + + @Override + public String getServletInfo() { + return SERVLET_INFO; + } + + @Override + public void destroy() { + + } + + private static class ServletAdapterConfig implements ServletConfig { + @Override + public String getServletName() { + return SERVLET_NAME; + } + + @Override + public ServletContext getServletContext() { + return SpringBootLambdaContainerHandler.getInstance().getServletContext(); + } + + @Override + public String getInitParameter(String s) { + return null; + } + + @Override + public Enumeration getInitParameterNames() { + return null; + } + } +} diff --git a/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactory.java b/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactory.java new file mode 100644 index 000000000..b47b081c7 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactory.java @@ -0,0 +1,55 @@ +package com.amazonaws.serverless.proxy.spring.embedded; + +import com.amazonaws.serverless.exceptions.ContainerInitializationException; +import com.amazonaws.serverless.proxy.internal.servlet.AwsLambdaServletContainerHandler; +import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.WebServerException; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.core.Ordered; + +import javax.servlet.ServletException; + +@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) +public class ServerlessServletEmbeddedServerFactory implements ServletWebServerFactory, WebServer { + private ServletContextInitializer[] initializers; + private AwsLambdaServletContainerHandler handler; + + public ServerlessServletEmbeddedServerFactory() { + super(); + handler = SpringBootLambdaContainerHandler.getInstance(); + } + + @Override + public WebServer getWebServer(ServletContextInitializer... initializers) { + this.initializers = initializers; + for (ServletContextInitializer i : initializers) { + try { + if (handler.getServletContext() == null) { + throw new WebServerException("Attempting to initialize ServletEmbeddedWebServer without ServletContext in Handler", null); + } + i.onStartup(handler.getServletContext()); + } catch (ServletException e) { + throw new WebServerException("Could not initialize Servlets", e); + } + } + return this; + } + + @Override + public void start() throws WebServerException { + + } + + @Override + public void stop() throws WebServerException { + + } + + @Override + public int getPort() { + return 0; + } +} diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/ServletAppTest.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/ServletAppTest.java new file mode 100644 index 000000000..b7353cd82 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/ServletAppTest.java @@ -0,0 +1,24 @@ +package com.amazonaws.servlerss.proxy.spring; + +import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; +import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext; +import com.amazonaws.serverless.proxy.model.AwsProxyRequest; +import com.amazonaws.serverless.proxy.model.AwsProxyResponse; +import com.amazonaws.servlerss.proxy.spring.servletapp.LambdaHandler; +import com.amazonaws.servlerss.proxy.spring.servletapp.MessageController; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ServletAppTest { + + LambdaHandler handler = new LambdaHandler(); + MockLambdaContext lambdaContext = new MockLambdaContext(); + + @Test + public void helloRequest_respondsWithSingleMessage() { + AwsProxyRequest req = new AwsProxyRequestBuilder("/hello", "GET").build(); + AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); + assertEquals(MessageController.HELLO_MESSAGE, resp.getBody()); + } +} diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/WebFluxAppTest.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/WebFluxAppTest.java new file mode 100644 index 000000000..ffdb98e41 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/WebFluxAppTest.java @@ -0,0 +1,32 @@ +package com.amazonaws.servlerss.proxy.spring; + +import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; +import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext; +import com.amazonaws.serverless.proxy.model.AwsProxyRequest; +import com.amazonaws.serverless.proxy.model.AwsProxyResponse; +import com.amazonaws.servlerss.proxy.spring.webfluxapp.LambdaHandler; +import com.amazonaws.servlerss.proxy.spring.webfluxapp.MessageController; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class WebFluxAppTest { + + LambdaHandler handler = new LambdaHandler(); + MockLambdaContext lambdaContext = new MockLambdaContext(); + + @Test + public void helloRequest_respondsWithSingleMessage() { + AwsProxyRequest req = new AwsProxyRequestBuilder("/single", "GET").build(); + AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); + assertEquals(MessageController.MESSAGE, resp.getBody()); + } + + @Test + public void helloDoubleRequest_respondsWithDoubleMessage() { + AwsProxyRequest req = new AwsProxyRequestBuilder("/double", "GET").build(); + AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); + + assertEquals(MessageController.MESSAGE + MessageController.MESSAGE, resp.getBody()); + } +} diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/LambdaHandler.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/LambdaHandler.java new file mode 100644 index 000000000..c6b4e0b76 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/LambdaHandler.java @@ -0,0 +1,25 @@ +package com.amazonaws.servlerss.proxy.spring.servletapp; + +import com.amazonaws.serverless.exceptions.ContainerInitializationException; +import com.amazonaws.serverless.proxy.model.AwsProxyRequest; +import com.amazonaws.serverless.proxy.model.AwsProxyResponse; +import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +public class LambdaHandler implements RequestHandler { + private static SpringBootLambdaContainerHandler handler; + + static { + try { + handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(ServletApplication.class); + } catch (ContainerInitializationException e) { + e.printStackTrace(); + } + } + + @Override + public AwsProxyResponse handleRequest(AwsProxyRequest awsProxyRequest, Context context) { + return handler.proxy(awsProxyRequest, context); + } +} diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/MessageController.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/MessageController.java new file mode 100644 index 000000000..48731347b --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/MessageController.java @@ -0,0 +1,15 @@ +package com.amazonaws.servlerss.proxy.spring.servletapp; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class MessageController { + public static final String HELLO_MESSAGE = "Hello"; + + @RequestMapping(path="/hello", method= RequestMethod.GET) + public String hello() { + return HELLO_MESSAGE; + } +} diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/ServletApplication.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/ServletApplication.java new file mode 100644 index 000000000..c7050f1b3 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/servletapp/ServletApplication.java @@ -0,0 +1,8 @@ +package com.amazonaws.servlerss.proxy.spring.servletapp; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class ServletApplication extends SpringBootServletInitializer { +} diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/LambdaHandler.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/LambdaHandler.java new file mode 100644 index 000000000..60dcbd4a3 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/LambdaHandler.java @@ -0,0 +1,25 @@ +package com.amazonaws.servlerss.proxy.spring.webfluxapp; + +import com.amazonaws.serverless.exceptions.ContainerInitializationException; +import com.amazonaws.serverless.proxy.model.AwsProxyRequest; +import com.amazonaws.serverless.proxy.model.AwsProxyResponse; +import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +public class LambdaHandler implements RequestHandler { + private static SpringBootLambdaContainerHandler handler; + + static { + try { + handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(WebFluxTestApplication.class); + } catch (ContainerInitializationException e) { + e.printStackTrace(); + } + } + + @Override + public AwsProxyResponse handleRequest(AwsProxyRequest awsProxyRequest, Context context) { + return handler.proxy(awsProxyRequest, context); + } +} diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/MessageController.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/MessageController.java new file mode 100644 index 000000000..a507ff978 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/MessageController.java @@ -0,0 +1,26 @@ +package com.amazonaws.servlerss.proxy.spring.webfluxapp; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; + +@RestController +public class MessageController { + public static final String MESSAGE = "Hello"; + + @RequestMapping(path="/single", method= RequestMethod.GET) + Flux singleMessage(){ + return Flux.just( + MESSAGE + ); + } + + @RequestMapping(path="/double", method= RequestMethod.GET) + Flux doubleMessage(){ + return Flux.just( + MESSAGE, + MESSAGE + ); + } +} \ No newline at end of file diff --git a/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/WebFluxTestApplication.java b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/WebFluxTestApplication.java new file mode 100644 index 000000000..ec06ac4d8 --- /dev/null +++ b/aws-serverless-java-container-springboot2/src/test/java/com/amazonaws/servlerss/proxy/spring/webfluxapp/WebFluxTestApplication.java @@ -0,0 +1,8 @@ +package com.amazonaws.servlerss.proxy.spring.webfluxapp; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.reactive.config.EnableWebFlux; + +@SpringBootApplication +public class WebFluxTestApplication { +} diff --git a/pom.xml b/pom.xml index 807aecd9b..00617337b 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ aws-serverless-spring-archetype aws-serverless-springboot-archetype aws-serverless-springboot2-archetype + aws-serverless-java-container-springboot2