diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index 3e8daaf1e..68d7a2f3d 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -65,25 +65,6 @@ jobs: # - name: Build with Spring 6.0.x # run: ./gha_build.sh spring false false -Dspring.version=6.0.16 -Dspring-security.version=6.1.10 -Ddependency-check.skip=true - build_springboot3: - name: Build and test SpringBoot 3 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - distribution: 'corretto' - java-version: 17 - - name: Build latest - run: ./gha_build.sh springboot3 true true - # Build with additional supported versions https://spring.io/projects/spring-boot#support - - name: Build with Spring Boot 3.1.x - run: ./gha_build.sh springboot3 false false -Dspringboot.version=3.1.12 -Dspring.version=6.0.21 -Dspringsecurity.version=6.1.9 -Ddependency-check.skip=true - - name: Build with Spring Boot 3.2.x - run: ./gha_build.sh springboot3 false false -Dspringboot.version=3.2.7 -Dspring.version=6.1.10 -Dspringsecurity.version=6.2.5 -Ddependency-check.skip=true - - name: Build with Spring Boot 3.3.x - run: ./gha_build.sh springboot3 false false -Dspringboot.version=3.3.6 -Dspring.version=6.1.15 -Dspringsecurity.version=6.3.5 -Ddependency-check.skip=true build_springboot4: name: Build and test SpringBoot 4 diff --git a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContext.java b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContext.java index 7c128cabe..83b3e85aa 100644 --- a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContext.java +++ b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContext.java @@ -87,7 +87,7 @@ public Principal getUserPrincipal() { case API_GATEWAY: return event.getRequestContext().getAuthorizer().getPrincipalId(); case ALB: - return event.getMultiValueHeaders().getFirst(ALB_IDENTITY_HEADER); + return event.getMultiValueHeaders().getLast(ALB_IDENTITY_HEADER); } } else if (getAuthenticationScheme().equals(AUTH_SCHEME_AWS_IAM)) { // if we received credentials from Cognito Federated Identities then we return the identity id diff --git a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/model/MultiValuedTreeMap.java b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/model/MultiValuedTreeMap.java index ad0593a1f..f6439e823 100644 --- a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/model/MultiValuedTreeMap.java +++ b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/model/MultiValuedTreeMap.java @@ -61,6 +61,14 @@ public Value getFirst(Key key) { return values.get(0); } + public Value getLast(Key key) { + List values = get(key); + if (values == null || values.isEmpty()) { + return null; + } + return values.get(values.size() - 1); + } + @Override public void putSingle(Key key, Value value) { List values = findKey(key); diff --git a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContextTest.java b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContextTest.java index ed89bf86c..f4641f36e 100644 --- a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContextTest.java +++ b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/jaxrs/AwsProxySecurityContextTest.java @@ -25,6 +25,12 @@ public class AwsProxySecurityContextTest { .header(ALB_ACESS_TOKEN_HEADER, "xxxxx") .header(ALB_IDENTITY_HEADER, COGNITO_IDENTITY_ID) .build(); + private static final AwsProxyRequest ALB_REQUEST_MULTIPLE_HEADERS = new AwsProxyRequestBuilder("/hello", "GET") + .alb() + .header(ALB_ACESS_TOKEN_HEADER, "xxxxx") + .header(ALB_IDENTITY_HEADER, "test-identity") + .header(ALB_IDENTITY_HEADER, COGNITO_IDENTITY_ID) + .build(); @Test void localVars_constructor_nullValues() { @@ -71,6 +77,12 @@ void alb_cognitoAuth_expectCustomSchemeAndCorrectPrincipal() { assertEquals(COGNITO_IDENTITY_ID, context.getUserPrincipal().getName()); } + @Test + void alb_multipleIdentityHeaders_usesLastValue() { + AwsProxySecurityContext context = new AwsProxySecurityContext(null, ALB_REQUEST_MULTIPLE_HEADERS); + assertEquals(COGNITO_IDENTITY_ID, context.getUserPrincipal().getName()); + } + @Test void userPool_getClaims_retrieveCustomClaim() { AwsProxySecurityContext context = new AwsProxySecurityContext(null, REQUEST_COGNITO_USER_POOL); diff --git a/aws-serverless-java-container-springboot3/pom.xml b/aws-serverless-java-container-springboot3/pom.xml deleted file mode 100644 index 13b54f95f..000000000 --- a/aws-serverless-java-container-springboot3/pom.xml +++ /dev/null @@ -1,363 +0,0 @@ - - - - aws-serverless-java-container - com.amazonaws.serverless - 3.0.1-SNAPSHOT - .. - - 4.0.0 - - com.amazonaws.serverless - aws-serverless-java-container-springboot3 - 2.1.5 - AWS Serverless Java container support - SpringBoot 3 implementation - Allows Java applications written for SpringBoot 3 to run in AWS Lambda - https://aws.amazon.com/lambda - - - 6.2.8 - 3.5.8 - 6.4.5 - - - - - - org.springframework.cloud - spring-cloud-function-serverless-web - 4.1.5 - - - com.amazonaws.serverless - aws-serverless-java-container-core - 2.1.5 - - - com.amazonaws.serverless - aws-serverless-java-container-core - 2.1.5 - tests - test-jar - test - - - com.github.spotbugs - spotbugs-annotations - 4.9.3 - provided - - - org.springframework - spring-webflux - ${spring.version} - true - - - org.springframework.boot - spring-boot - ${springboot.version} - true - - - org.springframework - spring-context - - - org.springframework - spring-core - - - - - org.springframework.boot - spring-boot-autoconfigure - ${springboot.version} - true - - - org.springframework - spring-core - ${spring.version} - true - - - org.springframework - spring-context - ${spring.version} - true - - - org.springframework - spring-webmvc - ${spring.version} - true - - - org.springframework - spring-aop - - - org.springframework - spring-expression - - - - - - org.springframework.security - spring-security-config - ${springsecurity.version} - - - org.springframework - spring-context - - - org.springframework - spring-beans - - - org.springframework - spring-core - - - org.springframework - spring-expression - - - org.springframework - spring-aop - - - test - - - org.springframework.security - spring-security-web - ${springsecurity.version} - - - org.springframework - spring-core - - - org.springframework - spring-web - - - org.springframework - spring-beans - - - org.springframework - spring-context - - - org.springframework - spring-expression - - - org.springframework - spring-aop - - - test - - - org.hibernate.validator - hibernate-validator - 8.0.2.Final - test - - - - org.junit.jupiter - junit-jupiter - test - - - - jakarta.validation - jakarta.validation-api - 3.1.1 - test - - - - jakarta.websocket - jakarta.websocket-api - 2.2.0 - test - - - - jakarta.websocket - jakarta.websocket-client-api - 2.2.0 - test - - - - org.springframework.boot - spring-boot-starter-data-jpa - ${springboot.version} - test - - - org.springframework.boot - spring-boot-starter-aop - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-logging - - - org.springframework.boot - spring-boot-starter-tomcat - - - org.apache.tomcat.embed - tomcat-embed-core - - - org.apache.tomcat.embed - tomcat-embed-websocket - - - - - com.h2database - h2 - 2.3.232 - test - - - - - - - - - org.jacoco - jacoco-maven-plugin - - ${basedir}/target/coverage-reports/jacoco-unit.exec - ${basedir}/target/coverage-reports/jacoco-unit.exec - - - com/amazonaws/serverless/proxy/spring/AwsSpringWebCustomRuntimeEventLoop* - com/amazonaws/serverless/proxy/spring/AwsSpringAotTypesProcessor* - - - - - 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 - - false - - - - com.github.spotbugs - spotbugs-maven-plugin - - ${project.basedir}/spotbugs-excludeFilter.xml - - - - - analyze-compile - compile - - check - - - - - - org.owasp - dependency-check-maven - ${dependencyCheck.version} - - true - - ${project.basedir}/../owasp-suppression.xml - - 7 - false - - - - org.apache.maven.plugins - maven-compiler-plugin - - 17 - 17 - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - diff --git a/aws-serverless-java-container-springboot3/spotbugs-excludeFilter.xml b/aws-serverless-java-container-springboot3/spotbugs-excludeFilter.xml deleted file mode 100644 index b26b1ad24..000000000 --- a/aws-serverless-java-container-springboot3/spotbugs-excludeFilter.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringAotTypesProcessor.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringAotTypesProcessor.java deleted file mode 100644 index 87e9ead04..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringAotTypesProcessor.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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.proxy.model.*; -import org.springframework.aot.generate.GenerationContext; -import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; -import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; -import org.springframework.beans.factory.aot.BeanFactoryInitializationCode; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; - -import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletResponse; -import com.fasterxml.jackson.core.JsonToken; - -/** - * AOT Initialization processor required to register reflective hints for GraalVM. - * This is necessary to ensure proper JSON serialization/deserialization. - * It is registered with META-INF/spring/aot.factories - * - * @author Oleg Zhurakousky - */ -public class AwsSpringAotTypesProcessor implements BeanFactoryInitializationAotProcessor { - - @Override - public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { - return new ReflectiveProcessorBeanFactoryInitializationAotContribution(); - } - - private static final class ReflectiveProcessorBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution { - @Override - public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) { - RuntimeHints runtimeHints = generationContext.getRuntimeHints(); - // known static types - - runtimeHints.reflection().registerType(AwsProxyRequest.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(AwsProxyResponse.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(SingleValueHeaders.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(JsonToken.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(MultiValuedTreeMap.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(Headers.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(AwsProxyRequestContext.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(ApiGatewayRequestIdentity.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES); - runtimeHints.reflection().registerType(AwsHttpServletResponse.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2ProxyRequest.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2HttpContext.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2ProxyRequestContext.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2AuthorizerMap.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2AuthorizerMap.HttpApiV2AuthorizerDeserializer.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2AuthorizerMap.HttpApiV2AuthorizerSerializer.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2IamAuthorizer.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - runtimeHints.reflection().registerType(HttpApiV2JwtAuthorizer.class, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, - MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES, MemberCategory.INTROSPECT_DECLARED_METHODS); - } - - } -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtils.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtils.java deleted file mode 100644 index c94de3057..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtils.java +++ /dev/null @@ -1,246 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import java.io.InputStream; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import com.amazonaws.serverless.proxy.internal.HttpUtils; -import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest; -import com.amazonaws.serverless.proxy.model.RequestSource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.function.serverless.web.ServerlessHttpServletRequest; -import org.springframework.cloud.function.serverless.web.ServerlessMVC; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.util.CollectionUtils; -import org.springframework.util.FileCopyUtils; -import org.springframework.util.MultiValueMapAdapter; -import org.springframework.util.StringUtils; - -import com.amazonaws.serverless.proxy.AwsHttpApiV2SecurityContextWriter; -import com.amazonaws.serverless.proxy.AwsProxySecurityContextWriter; -import com.amazonaws.serverless.proxy.RequestReader; -import com.amazonaws.serverless.proxy.SecurityContextWriter; -import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletResponse; -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest; -import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.databind.ObjectMapper; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.http.HttpServletRequest; - -import static com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest.decodeValueIfEncoded; -import static com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest.getQueryParamValuesAsList; - -class AwsSpringHttpProcessingUtils { - - private static Log logger = LogFactory.getLog(AwsSpringHttpProcessingUtils.class); - private static final int LAMBDA_MAX_REQUEST_DURATION_MINUTES = 15; - - private AwsSpringHttpProcessingUtils() { - - } - - public static AwsProxyResponse processRequest(HttpServletRequest request, ServerlessMVC mvc, - AwsProxyHttpServletResponseWriter responseWriter) { - CountDownLatch latch = new CountDownLatch(1); - AwsHttpServletResponse response = new AwsHttpServletResponse(request, latch); - try { - mvc.service(request, response); - boolean requestTimedOut = !latch.await(LAMBDA_MAX_REQUEST_DURATION_MINUTES, TimeUnit.MINUTES); // timeout is potentially lower as user configures it - if (requestTimedOut) { - logger.warn("request timed out after " + LAMBDA_MAX_REQUEST_DURATION_MINUTES + " minutes"); - } - AwsProxyResponse awsResponse = responseWriter.writeResponse(response, null); - return awsResponse; - } - catch (Exception e) { - e.printStackTrace(); - throw new IllegalStateException(e); - } - } - - public static String extractVersion() { - try { - String path = AwsSpringHttpProcessingUtils.class.getProtectionDomain().getCodeSource().getLocation().toString(); - int endIndex = path.lastIndexOf('.'); - if (endIndex < 0) { - return "UNKNOWN-VERSION"; - } - int startIndex = path.lastIndexOf("/") + 1; - return path.substring(startIndex, endIndex).replace("spring-cloud-function-serverless-web-", ""); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to detect version", e); - } - return "UNKNOWN-VERSION"; - } - - } - - public static HttpServletRequest generateHttpServletRequest(InputStream jsonRequest, Context lambdaContext, - ServletContext servletContext, ObjectMapper mapper) { - try { - String text = new String(FileCopyUtils.copyToByteArray(jsonRequest), StandardCharsets.UTF_8); - if (logger.isDebugEnabled()) { - logger.debug("Creating HttpServletRequest from: " + text); - } - return generateHttpServletRequest(text, lambdaContext, servletContext, mapper); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static HttpServletRequest generateHttpServletRequest(String jsonRequest, Context lambdaContext, - ServletContext servletContext, ObjectMapper mapper) { - Map _request = readValue(jsonRequest, Map.class, mapper); - SecurityContextWriter securityWriter = "2.0".equals(_request.get("version")) - ? new AwsHttpApiV2SecurityContextWriter() - : new AwsProxySecurityContextWriter(); - HttpServletRequest httpServletRequest = "2.0".equals(_request.get("version")) - ? AwsSpringHttpProcessingUtils.generateRequest2(jsonRequest, lambdaContext, securityWriter, mapper, servletContext) - : AwsSpringHttpProcessingUtils.generateRequest1(jsonRequest, lambdaContext, securityWriter, mapper, servletContext); - return httpServletRequest; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static HttpServletRequest generateRequest1(String request, Context lambdaContext, - SecurityContextWriter securityWriter, ObjectMapper mapper, ServletContext servletContext) { - AwsProxyRequest v1Request = readValue(request, AwsProxyRequest.class, mapper); - - ServerlessHttpServletRequest httpRequest = new ServerlessHttpServletRequest(servletContext, v1Request.getHttpMethod(), v1Request.getPath()); - - populateQueryStringParametersV1(v1Request, httpRequest); - populateMultiValueQueryStringParametersV1(v1Request, httpRequest); - - String contentType = null; - if (v1Request.getMultiValueHeaders() != null) { - MultiValueMapAdapter headers = new MultiValueMapAdapter(v1Request.getMultiValueHeaders()); - httpRequest.setHeaders(headers); - contentType = v1Request.getMultiValueHeaders().getFirst(HttpHeaders.CONTENT_TYPE); - } - populateContentAndContentType( - v1Request.getBody(), - contentType, - v1Request.isBase64Encoded(), - httpRequest - ); - if (v1Request.getRequestContext() != null) { - httpRequest.setAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY, v1Request.getRequestContext()); - httpRequest.setAttribute(RequestReader.ALB_CONTEXT_PROPERTY, v1Request.getRequestContext().getElb()); - } - httpRequest.setAttribute(RequestReader.API_GATEWAY_STAGE_VARS_PROPERTY, v1Request.getStageVariables()); - httpRequest.setAttribute(RequestReader.API_GATEWAY_EVENT_PROPERTY, v1Request); - httpRequest.setAttribute(RequestReader.LAMBDA_CONTEXT_PROPERTY, lambdaContext); - httpRequest.setAttribute(RequestReader.JAX_SECURITY_CONTEXT_PROPERTY, - securityWriter.writeSecurityContext(v1Request, lambdaContext)); - return httpRequest; - } - - - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private static HttpServletRequest generateRequest2(String request, Context lambdaContext, - SecurityContextWriter securityWriter, ObjectMapper mapper, ServletContext servletContext) { - HttpApiV2ProxyRequest v2Request = readValue(request, HttpApiV2ProxyRequest.class, mapper); - - - ServerlessHttpServletRequest httpRequest = new ServerlessHttpServletRequest(servletContext, - v2Request.getRequestContext().getHttp().getMethod(), v2Request.getRequestContext().getHttp().getPath()); - populateQueryStringParametersV2(v2Request.getQueryStringParameters(), httpRequest); - - v2Request.getHeaders().forEach(httpRequest::setHeader); - - populateContentAndContentType( - v2Request.getBody(), - v2Request.getHeaders().get(HttpHeaders.CONTENT_TYPE), - v2Request.isBase64Encoded(), - httpRequest - ); - - httpRequest.setAttribute(RequestReader.HTTP_API_CONTEXT_PROPERTY, v2Request.getRequestContext()); - httpRequest.setAttribute(RequestReader.HTTP_API_STAGE_VARS_PROPERTY, v2Request.getStageVariables()); - httpRequest.setAttribute(RequestReader.HTTP_API_EVENT_PROPERTY, v2Request); - httpRequest.setAttribute(RequestReader.LAMBDA_CONTEXT_PROPERTY, lambdaContext); - httpRequest.setAttribute(RequestReader.JAX_SECURITY_CONTEXT_PROPERTY, - securityWriter.writeSecurityContext(v2Request, lambdaContext)); - return httpRequest; - } - - private static void populateQueryStringParametersV2(Map requestParameters, ServerlessHttpServletRequest httpRequest) { - if (!CollectionUtils.isEmpty(requestParameters)) { - for (Entry entry : requestParameters.entrySet()) { - // fix according to parseRawQueryString - httpRequest.setParameter(entry.getKey(), entry.getValue()); - } - } - } - - private static void populateQueryStringParametersV1(AwsProxyRequest v1Request, ServerlessHttpServletRequest httpRequest) { - Map requestParameters = v1Request.getQueryStringParameters(); - if (!CollectionUtils.isEmpty(requestParameters)) { - // decode all keys and values in map - for (Entry entry : requestParameters.entrySet()) { - String k = v1Request.getRequestSource() == RequestSource.ALB ? decodeValueIfEncoded(entry.getKey()) : entry.getKey(); - String v = v1Request.getRequestSource() == RequestSource.ALB ? decodeValueIfEncoded(entry.getValue()) : entry.getValue(); - httpRequest.setParameter(k, v); - } - } - } - - private static void populateMultiValueQueryStringParametersV1(AwsProxyRequest v1Request, ServerlessHttpServletRequest httpRequest) { - if (v1Request.getMultiValueQueryStringParameters() != null) { - MultiValueMapAdapter queryStringParameters = new MultiValueMapAdapter<>(v1Request.getMultiValueQueryStringParameters()); - queryStringParameters.forEach((k, v) -> { - String key = v1Request.getRequestSource() == RequestSource.ALB - ? decodeValueIfEncoded(k) - : k; - List value = v1Request.getRequestSource() == RequestSource.ALB - ? getQueryParamValuesAsList(v1Request.getMultiValueQueryStringParameters(), k, false).stream() - .map(AwsHttpServletRequest::decodeValueIfEncoded) - .toList() - : v; - httpRequest.setParameter(key, value.toArray(new String[0])); - }); - } - } - - private static T readValue(String json, Class clazz, ObjectMapper mapper) { - try { - return mapper.readValue(json, clazz); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - - private static void populateContentAndContentType( - String body, - String contentType, - boolean base64Encoded, - ServerlessHttpServletRequest httpRequest) { - if (StringUtils.hasText(body)) { - httpRequest.setContentType(contentType == null ? MediaType.APPLICATION_JSON_VALUE : contentType); - if (base64Encoded) { - httpRequest.setContent(Base64.getMimeDecoder().decode(body)); - } else { - Charset charseEncoding = HttpUtils.parseCharacterEncoding(contentType,StandardCharsets.UTF_8); - httpRequest.setContent(body.getBytes(charseEncoding)); - } - } - } - - - -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringWebCustomRuntimeEventLoop.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringWebCustomRuntimeEventLoop.java deleted file mode 100644 index c015a8024..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringWebCustomRuntimeEventLoop.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 java.io.PrintWriter; -import java.io.StringWriter; -import java.net.URI; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; -import org.springframework.cloud.function.serverless.web.ServerlessMVC; -import org.springframework.context.SmartLifecycle; -import org.springframework.core.env.Environment; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; - -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; - -/** - * Event loop and necessary configurations to support AWS Lambda Custom Runtime - * - https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html. - * - * @author Oleg Zhurakousky - * @author Mark Sailes - * - */ -public final class AwsSpringWebCustomRuntimeEventLoop implements SmartLifecycle { - - private static Log logger = LogFactory.getLog(AwsSpringWebCustomRuntimeEventLoop.class); - - static final String LAMBDA_VERSION_DATE = "2018-06-01"; - private static final String LAMBDA_ERROR_URL_TEMPLATE = "http://{0}/{1}/runtime/invocation/{2}/error"; - private static final String LAMBDA_RUNTIME_URL_TEMPLATE = "http://{0}/{1}/runtime/invocation/next"; - private static final String LAMBDA_INVOCATION_URL_TEMPLATE = "http://{0}/{1}/runtime/invocation/{2}/response"; - private static final String USER_AGENT_VALUE = String.format("spring-cloud-function/%s-%s", - System.getProperty("java.runtime.version"), AwsSpringHttpProcessingUtils.extractVersion()); - - private final ServletWebServerApplicationContext applicationContext; - - private volatile boolean running; - - private final ExecutorService executor = Executors.newSingleThreadExecutor(); - - public AwsSpringWebCustomRuntimeEventLoop(ServletWebServerApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - - public void run() { - this.running = true; - this.executor.execute(() -> { - eventLoop(this.applicationContext); - }); - } - - @Override - public void start() { - this.run(); - } - - @Override - public void stop() { - this.executor.shutdownNow(); - this.running = false; - } - - @Override - public boolean isRunning() { - return this.running; - } - - private void eventLoop(ServletWebServerApplicationContext context) { - ServerlessMVC mvc = ServerlessMVC.INSTANCE(context); - - Environment environment = context.getEnvironment(); - logger.info("Starting AWSWebRuntimeEventLoop"); - - String runtimeApi = environment.getProperty("AWS_LAMBDA_RUNTIME_API"); - String eventUri = MessageFormat.format(LAMBDA_RUNTIME_URL_TEMPLATE, runtimeApi, LAMBDA_VERSION_DATE); - if (logger.isDebugEnabled()) { - logger.debug("Event URI: " + eventUri); - } - - RequestEntity requestEntity = RequestEntity.get(URI.create(eventUri)) - .header("User-Agent", USER_AGENT_VALUE).build(); - RestTemplate rest = new RestTemplate(); - ObjectMapper mapper = new ObjectMapper();//.getBean(ObjectMapper.class); - mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); - AwsProxyHttpServletResponseWriter responseWriter = new AwsProxyHttpServletResponseWriter(); - - logger.info("Entering event loop"); - while (this.isRunning()) { - logger.debug("Attempting to get new event"); - ResponseEntity incomingEvent = rest.exchange(requestEntity, String.class); - - if (incomingEvent != null && incomingEvent.hasBody()) { - if (logger.isDebugEnabled()) { - logger.debug("New Event received from AWS Gateway: " + incomingEvent.getBody()); - } - String requestId = incomingEvent.getHeaders().getFirst("Lambda-Runtime-Aws-Request-Id"); - - try { - logger.debug("Submitting request to the user's web application"); - - AwsProxyResponse awsResponse = AwsSpringHttpProcessingUtils.processRequest( - AwsSpringHttpProcessingUtils.generateHttpServletRequest(incomingEvent.getBody(), - null, mvc.getServletContext(), mapper), mvc, responseWriter); - if (logger.isDebugEnabled()) { - logger.debug("Received response - body: " + awsResponse.getBody() + - "; status: " + awsResponse.getStatusCode() + "; headers: " + awsResponse.getHeaders()); - } - - String invocationUrl = MessageFormat.format(LAMBDA_INVOCATION_URL_TEMPLATE, runtimeApi, - LAMBDA_VERSION_DATE, requestId); - - ResponseEntity result = rest.exchange(RequestEntity.post(URI.create(invocationUrl)) - .header("User-Agent", USER_AGENT_VALUE).body(awsResponse), byte[].class); - if (logger.isDebugEnabled()) { - logger.debug("Response sent: body: " + result.getBody() + - "; status: " + result.getStatusCode() + "; headers: " + result.getHeaders()); - } - if (logger.isInfoEnabled()) { - logger.info("Result POST status: " + result); - } - } - catch (Exception e) { - logger.error(e); - this.propagateAwsError(requestId, e, mapper, runtimeApi, rest); - } - } - } - } - - private void propagateAwsError(String requestId, Exception e, ObjectMapper mapper, String runtimeApi, RestTemplate rest) { - String errorMessage = e.getMessage(); - String errorType = e.getClass().getSimpleName(); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - String stackTrace = sw.toString(); - Map em = new HashMap<>(); - em.put("errorMessage", errorMessage); - em.put("errorType", errorType); - em.put("stackTrace", stackTrace); - try { - byte[] outputBody = mapper.writeValueAsBytes(em); - String errorUrl = MessageFormat.format(LAMBDA_ERROR_URL_TEMPLATE, runtimeApi, LAMBDA_VERSION_DATE, requestId); - ResponseEntity result = rest.exchange(RequestEntity.post(URI.create(errorUrl)) - .header("User-Agent", USER_AGENT_VALUE) - .body(outputBody), Object.class); - if (logger.isInfoEnabled()) { - logger.info("Result ERROR status: " + result.getStatusCode()); - } - } - catch (Exception e2) { - throw new IllegalArgumentException("Failed to report error", e2); - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringWebRuntimeInitializer.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringWebRuntimeInitializer.java deleted file mode 100644 index 992bc635e..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringWebRuntimeInitializer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.SmartLifecycle; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.env.Environment; -import org.springframework.util.StringUtils; - -/** - * Initializer to optionally start Custom Runtime to process web workloads. - * Registered with META-INF/spring.factories - * - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class AwsSpringWebRuntimeInitializer implements ApplicationContextInitializer { - - private static Log logger = LogFactory.getLog(AwsSpringWebRuntimeInitializer.class); - - @Override - public void initialize(GenericApplicationContext context) { - Environment environment = context.getEnvironment(); - - if (context instanceof ServletWebServerApplicationContext && isCustomRuntime(environment)) { - if (context.getBeanFactory().getBeanNamesForType(AwsSpringWebCustomRuntimeEventLoop.class, false, false).length == 0) { - context.registerBean(StringUtils.uncapitalize(AwsSpringWebCustomRuntimeEventLoop.class.getSimpleName()), - SmartLifecycle.class, () -> new AwsSpringWebCustomRuntimeEventLoop((ServletWebServerApplicationContext) context)); - } - } - } - - private boolean isCustomRuntime(Environment environment) { - String handler = environment.getProperty("_HANDLER"); - if (StringUtils.hasText(handler)) { - handler = handler.split(":")[0]; - logger.info("AWS Handler: " + handler); - try { - Thread.currentThread().getContextClassLoader().loadClass(handler); - } - catch (Exception e) { - logger.debug("Will execute Lambda in Custom Runtime"); - return true; - } - } - return false; - } -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootAwsProxyExceptionHandler.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootAwsProxyExceptionHandler.java deleted file mode 100644 index 127ef6684..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootAwsProxyExceptionHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import com.amazonaws.serverless.proxy.AwsProxyExceptionHandler; -import com.amazonaws.serverless.proxy.ExceptionHandler; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import org.springframework.web.ErrorResponse; - -/** - * This ExceptionHandler implementation enhances the standard AwsProxyExceptionHandler - * by mapping additional details from org.springframework.web.ErrorResponse - * - * As of now this class is identical with SpringAwsProxyExceptionHandler. We may consider - * moving it to a common module to share it in the future. - */ -public class SpringBootAwsProxyExceptionHandler extends AwsProxyExceptionHandler - implements ExceptionHandler { - @Override - public AwsProxyResponse handle(Throwable ex) { - if (ex instanceof ErrorResponse) { - return new AwsProxyResponse(((ErrorResponse) ex).getStatusCode().value(), - HEADERS, getErrorJson(ex.getMessage())); - } else { - return super.handle(ex); - } - } - -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandler.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandler.java deleted file mode 100644 index 45bf28efe..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandler.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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 java.util.concurrent.CountDownLatch; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.web.context.ConfigurableWebApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.ExceptionHandler; -import com.amazonaws.serverless.proxy.InitializationWrapper; -import com.amazonaws.serverless.proxy.RequestReader; -import com.amazonaws.serverless.proxy.ResponseWriter; -import com.amazonaws.serverless.proxy.SecurityContextWriter; -import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest; -import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletResponse; -import com.amazonaws.serverless.proxy.internal.servlet.AwsLambdaServletContainerHandler; -import com.amazonaws.serverless.proxy.internal.servlet.AwsServletContext; -import com.amazonaws.serverless.proxy.internal.servlet.AwsServletRegistration; -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.model.HttpApiV2ProxyRequest; -import com.amazonaws.serverless.proxy.spring.embedded.ServerlessReactiveServletEmbeddedServerFactory; -import com.amazonaws.serverless.proxy.spring.embedded.ServerlessServletEmbeddedServerFactory; -import com.amazonaws.services.lambda.runtime.Context; - -import jakarta.servlet.Servlet; -import jakarta.servlet.http.HttpServletRequest; - -/** - * SpringBoot 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 static final String DISPATCHER_SERVLET_REGISTRATION_NAME = "dispatcherServlet"; - - private final Class springBootInitializer; - private static final Logger log = LoggerFactory.getLogger(SpringBootLambdaContainerHandler.class); - private String[] springProfiles = null; - private WebApplicationType springWebApplicationType; - private ConfigurableApplicationContext applicationContext; - - 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 ServerlessReactiveServletEmbeddedServerFactory}. - * - * @return The initialized instance - */ - public static SpringBootLambdaContainerHandler getInstance() { - return instance; - } - - /** - * 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 { - return new SpringBootProxyHandlerBuilder() - .defaultProxy() - .initializationWrapper(new InitializationWrapper()) - .springBootApplication(springBootInitializer) - .profiles(profiles) - .buildAndInitialize(); - } - - /** - * Creates a default SpringLambdaContainerHandler initialized with the `AwsProxyRequest` and `HttpApiV2ProxyRequest` 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 getHttpApiV2ProxyHandler(Class springBootInitializer, String... profiles) - throws ContainerInitializationException { - return new SpringBootProxyHandlerBuilder() - .defaultHttpApiV2Proxy() - .initializationWrapper(new InitializationWrapper()) - .springBootApplication(springBootInitializer) - .profiles(profiles) - .buildAndInitialize(); - } - - /** - * Creates a new container handler with the given reader and writer objects - * - * @param requestTypeClass The class for the incoming Lambda event - * @param responseTypeClass The class for the Lambda function output - * @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 - * @param init The initialization Wrapper that will be used to start Spring Boot - * @param applicationType The Spring Web Application Type - */ - public SpringBootLambdaContainerHandler(Class requestTypeClass, - Class responseTypeClass, - RequestReader requestReader, - ResponseWriter responseWriter, - SecurityContextWriter securityContextWriter, - ExceptionHandler exceptionHandler, - Class springBootInitializer, - InitializationWrapper init, - WebApplicationType applicationType) { - super(requestTypeClass, responseTypeClass, requestReader, responseWriter, securityContextWriter, exceptionHandler); - Timer.start("SPRINGBOOT2_CONTAINER_HANDLER_CONSTRUCTOR"); - initialized = false; - this.springBootInitializer = springBootInitializer; - springWebApplicationType = applicationType; - setInitializationWrapper(init); - SpringBootLambdaContainerHandler.setInstance(this); - - Timer.stop("SPRINGBOOT2_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(HttpServletRequest request, CountDownLatch latch) { - return new AwsHttpServletResponse(request, latch); - } - - @Override - protected void handleRequest(HttpServletRequest containerRequest, AwsHttpServletResponse containerResponse, Context lambdaContext) throws Exception { - // this method of the AwsLambdaServletContainerHandler sets the servlet context - Timer.start("SPRINGBOOT2_HANDLE_REQUEST"); - - // wire up the application context on the first invocation - if (!initialized) { - initialize(); - } - - // process filters & invoke servlet - Servlet reqServlet = ((AwsServletContext)getServletContext()).getServletForPath(containerRequest.getPathInfo()); - if (AwsHttpServletRequest.class.isAssignableFrom(containerRequest.getClass())) { - ((AwsHttpServletRequest)containerRequest).setServletContext(getServletContext()); - ((AwsHttpServletRequest)containerRequest).setResponse(containerResponse); - } - doFilter(containerRequest, containerResponse, reqServlet); - Timer.stop("SPRINGBOOT2_HANDLE_REQUEST"); - } - - SpringApplicationBuilder getSpringApplicationBuilder(Class... sources) { - return new SpringApplicationBuilder(sources); - } - - @Override - public void initialize() - throws ContainerInitializationException { - Timer.start("SPRINGBOOT2_COLD_START"); - - SpringApplicationBuilder builder = getSpringApplicationBuilder(getEmbeddedContainerClasses()) - .web(springWebApplicationType); // .REACTIVE, .SERVLET - if(springBootInitializer != null) { - builder.main(springBootInitializer); - } - if (springProfiles != null) { - builder.profiles(springProfiles); - } - applicationContext = builder.run(); - if (springWebApplicationType == WebApplicationType.SERVLET) { - ((ConfigurableWebApplicationContext)applicationContext).setServletContext(getServletContext()); - AwsServletRegistration reg = (AwsServletRegistration)getServletContext().getServletRegistration(DISPATCHER_SERVLET_REGISTRATION_NAME); - if (reg != null) { - reg.setLoadOnStartup(1); - } - } - super.initialize(); - initialized = true; - Timer.stop("SPRINGBOOT2_COLD_START"); - } - - private Class[] getEmbeddedContainerClasses() { - Class[] classes = new Class[2]; - if (springWebApplicationType == WebApplicationType.REACTIVE) { - 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] = ServerlessReactiveServletEmbeddedServerFactory.class; - } catch (ClassNotFoundException e) { - springWebApplicationType = WebApplicationType.SERVLET; - classes[0] = ServerlessServletEmbeddedServerFactory.class; - } - } else { - classes[0] = ServerlessServletEmbeddedServerFactory.class; - } - - classes[1] = springBootInitializer; - return classes; - } -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootProxyHandlerBuilder.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootProxyHandlerBuilder.java deleted file mode 100644 index e7ad017f1..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootProxyHandlerBuilder.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2020 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.ExceptionHandler; -import com.amazonaws.serverless.proxy.internal.servlet.ServletLambdaContainerHandlerBuilder; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import org.springframework.boot.WebApplicationType; - -import jakarta.servlet.http.HttpServletRequest; - -public final class SpringBootProxyHandlerBuilder extends ServletLambdaContainerHandlerBuilder< - RequestType, - AwsProxyResponse, - HttpServletRequest, - SpringBootLambdaContainerHandler, - SpringBootProxyHandlerBuilder> { - private Class springBootInitializer; - private String[] profiles; - private WebApplicationType applicationType = WebApplicationType.REACTIVE; - - @Override - protected SpringBootProxyHandlerBuilder self() { - return this; - } - - - public SpringBootProxyHandlerBuilder springBootApplication(Class app) { - springBootInitializer = app; - return self(); - } - - public SpringBootProxyHandlerBuilder profiles(String... profiles) { - this.profiles = profiles; - return self(); - } - - public SpringBootProxyHandlerBuilder servletApplication() { - this.applicationType = WebApplicationType.SERVLET; - return self(); - } - - @Override - public SpringBootLambdaContainerHandler build() throws ContainerInitializationException { - validate(); - if (springBootInitializer == null) { - throw new ContainerInitializationException("Missing spring boot application class in builder", null); - } - SpringBootLambdaContainerHandler handler = new SpringBootLambdaContainerHandler( - requestTypeClass, - responseTypeClass, - requestReader, - responseWriter, - securityContextWriter, - exceptionHandler, - springBootInitializer, - initializationWrapper, - applicationType - ); - if (profiles != null) { - handler.activateSpringProfiles(profiles); - } - return handler; - } - - @Override - public SpringBootLambdaContainerHandler buildAndInitialize() throws ContainerInitializationException { - SpringBootLambdaContainerHandler handler = build(); - initializationWrapper.start(handler); - return handler; - } - - @Override - protected ExceptionHandler defaultExceptionHandler() { - return new SpringBootAwsProxyExceptionHandler(); - } -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringDelegatingLambdaContainerHandler.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringDelegatingLambdaContainerHandler.java deleted file mode 100644 index 765c4befe..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/SpringDelegatingLambdaContainerHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.AsyncInitializationWrapper; -import com.amazonaws.serverless.proxy.InitializationTypeHelper; -import com.amazonaws.serverless.proxy.internal.InitializableLambdaContainerHandler; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import org.springframework.cloud.function.serverless.web.FunctionClassUtils; -import org.springframework.cloud.function.serverless.web.ServerlessMVC; - -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; - -import jakarta.servlet.http.HttpServletRequest; - -/* - * Copyright 2023 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. - */ - -/** - * An implementation of {@link RequestStreamHandler} which delegates to - * Spring Cloud Function serverless web module managed by Spring team. - * - * It requires no sub-classing from the user other then being identified as "Handler". - * The configuration class(es) should be provided via MAIN_CLASS environment variable. - * - */ -public class SpringDelegatingLambdaContainerHandler implements RequestStreamHandler { - private final ServerlessMVC mvc; - private final ObjectMapper mapper; - private final AwsProxyHttpServletResponseWriter responseWriter; - - public SpringDelegatingLambdaContainerHandler() throws ContainerInitializationException { - this(new Class[] {FunctionClassUtils.getStartClass()}); - } - - public SpringDelegatingLambdaContainerHandler(final Class... startupClasses) throws ContainerInitializationException { - SpringDelegatingInitHandler initHandler = new SpringDelegatingInitHandler(startupClasses); - if (InitializationTypeHelper.isAsyncInitializationDisabled()) { - initHandler.initialize(); - } else { - AsyncInitializationWrapper asyncInitWrapper = new AsyncInitializationWrapper(); - asyncInitWrapper.start(initHandler); - } - this.mvc = initHandler.getMvc(); - this.mapper = new ObjectMapper(); - this.responseWriter = new AwsProxyHttpServletResponseWriter(); - } - - @Override - public void handleRequest(InputStream input, OutputStream output, Context lambdaContext) throws IOException { - HttpServletRequest httpServletRequest = AwsSpringHttpProcessingUtils - .generateHttpServletRequest(input, lambdaContext, this.mvc.getServletContext(), this.mapper); - AwsProxyResponse awsProxyResponse = AwsSpringHttpProcessingUtils.processRequest(httpServletRequest, mvc, responseWriter); - this.mapper.writeValue(output, awsProxyResponse); - } - - private static final class SpringDelegatingInitHandler implements InitializableLambdaContainerHandler { - private ServerlessMVC mvc; - private final Class[] startupClasses; - - public SpringDelegatingInitHandler(final Class... startupClasses) { - this.startupClasses = startupClasses; - } - - @Override - public void initialize() throws ContainerInitializationException { - this.mvc = ServerlessMVC.INSTANCE(this.startupClasses); - this.mvc.waitForContext(); - } - - public ServerlessMVC getMvc() { - return this.mvc; - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessReactiveServletEmbeddedServerFactory.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessReactiveServletEmbeddedServerFactory.java deleted file mode 100644 index 3376452e2..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessReactiveServletEmbeddedServerFactory.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2020 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.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 jakarta.servlet.*; -import java.io.IOException; -import java.util.Enumeration; - -@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) -public class ServerlessReactiveServletEmbeddedServerFactory 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-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactory.java b/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactory.java deleted file mode 100644 index 76ee919dc..000000000 --- a/aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactory.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2020 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.embedded; - -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 jakarta.servlet.ServletException; - -@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) -public class ServerlessServletEmbeddedServerFactory implements ServletWebServerFactory, WebServer { - @SuppressWarnings("rawtypes") - private AwsLambdaServletContainerHandler handler; - - public ServerlessServletEmbeddedServerFactory() { - super(); - handler = SpringBootLambdaContainerHandler.getInstance(); - } - - @Override - public WebServer getWebServer(ServletContextInitializer... 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-springboot3/src/main/resources/META-INF/spring.factories b/aws-serverless-java-container-springboot3/src/main/resources/META-INF/spring.factories deleted file mode 100644 index cd5c2e70b..000000000 --- a/aws-serverless-java-container-springboot3/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.context.ApplicationContextInitializer=\ -com.amazonaws.serverless.proxy.spring.AwsSpringWebRuntimeInitializer diff --git a/aws-serverless-java-container-springboot3/src/main/resources/META-INF/spring/aot.factories b/aws-serverless-java-container-springboot3/src/main/resources/META-INF/spring/aot.factories deleted file mode 100644 index 44acc0d83..000000000 --- a/aws-serverless-java-container-springboot3/src/main/resources/META-INF/spring/aot.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=com.amazonaws.serverless.proxy.spring.AwsSpringAotTypesProcessor \ No newline at end of file diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/AWSWebRuntimeTests.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/AWSWebRuntimeTests.java deleted file mode 100644 index 9903e8f8b..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/AWSWebRuntimeTests.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.ConfigurableApplicationContext; - -public class AWSWebRuntimeTests { - - @AfterEach - public void after() { - System.clearProperty("_HANDLER"); - } - - @Test - public void testWebRuntimeInitialization() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run(EmptyApplication.class);) { - assertFalse(context.getBeansOfType(AwsSpringWebCustomRuntimeEventLoop.class).size() > 0); - } - System.setProperty("_HANDLER", "foo"); - AwsSpringWebCustomRuntimeEventLoop loop = null; - try (ConfigurableApplicationContext context = SpringApplication.run(EmptyApplication.class);) { - Thread.sleep(100); - assertTrue(context.getBeansOfType(AwsSpringWebCustomRuntimeEventLoop.class).size() > 0); - loop = context.getBean(AwsSpringWebCustomRuntimeEventLoop.class); - assertTrue(loop.isRunning()); - } - assertFalse(loop.isRunning()); - } - - @EnableAutoConfiguration - private static class EmptyApplication { - - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtilsTests.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtilsTests.java deleted file mode 100644 index d09a40796..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtilsTests.java +++ /dev/null @@ -1,349 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; - -import com.amazonaws.serverless.proxy.RequestReader; -import com.amazonaws.serverless.proxy.model.AlbContext; -import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; -import org.springframework.cloud.function.serverless.web.ServerlessMVC; -import org.springframework.cloud.function.serverless.web.ServerlessServletContext; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.fasterxml.jackson.databind.ObjectMapper; - -import jakarta.servlet.http.HttpServletRequest; - -import static org.junit.jupiter.api.Assertions.*; - -public class AwsSpringHttpProcessingUtilsTests { - - private static String API_GATEWAY_EVENT = "{\n" - + " \"version\": \"1.0\",\n" - + " \"resource\": \"$default\",\n" - + " \"path\": \"/async\",\n" - + " \"httpMethod\": \"POST\",\n" - + " \"headers\": {\n" - + " \"Content-Length\": \"45\",\n" - + " \"Content-Type\": \"application/json\",\n" - + " \"Host\": \"i76bfh111.execute-api.eu-west-3.amazonaws.com\",\n" - + " \"User-Agent\": \"curl/7.79.1\",\n" - + " \"X-Amzn-Trace-Id\": \"Root=1-64087690-2151375b219d3ba3389ea84e\",\n" - + " \"X-Forwarded-For\": \"109.210.252.44\",\n" - + " \"X-Forwarded-Port\": \"443\",\n" - + " \"X-Forwarded-Proto\": \"https\",\n" - + " \"accept\": \"*/*\"\n" - + " },\n" - + " \"multiValueHeaders\": {\n" - + " \"Content-Length\": [\n" - + " \"45\"\n" - + " ],\n" - + " \"Content-Type\": [\n" - + " \"application/json\"\n" - + " ],\n" - + " \"Host\": [\n" - + " \"i76bfhczs0.execute-api.eu-west-3.amazonaws.com\"\n" - + " ],\n" - + " \"User-Agent\": [\n" - + " \"curl/7.79.1\"\n" - + " ],\n" - + " \"X-Amzn-Trace-Id\": [\n" - + " \"Root=1-64087690-2151375b219d3ba3389ea84e\"\n" - + " ],\n" - + " \"X-Forwarded-For\": [\n" - + " \"109.210.252.44\"\n" - + " ],\n" - + " \"X-Forwarded-Port\": [\n" - + " \"443\"\n" - + " ],\n" - + " \"X-Forwarded-Proto\": [\n" - + " \"https\"\n" - + " ],\n" - + " \"accept\": [\n" - + " \"*/*\"\n" - + " ]\n" - + " },\n" - + " \"queryStringParameters\": {\n" - + " \"abc\": \"xyz\",\n" - + " \"parameter1\": \"value2\"\n" - + " },\n" - + " \"multiValueQueryStringParameters\": {\n" - + " \"abc\": [\n" - + " \"xyz\"\n" - + " ],\n" - + " \"parameter1\": [\n" - + " \"value1\",\n" - + " \"value2\"\n" - + " ]\n" - + " },\n" - + " \"requestContext\": {\n" - + " \"accountId\": \"123456789098\",\n" - + " \"apiId\": \"i76bfhczs0\",\n" - + " \"domainName\": \"i76bfhc111.execute-api.eu-west-3.amazonaws.com\",\n" - + " \"domainPrefix\": \"i76bfhczs0\",\n" - + " \"extendedRequestId\": \"Bdd2ngt5iGYEMIg=\",\n" - + " \"httpMethod\": \"POST\",\n" - + " \"path\": \"/pets\",\n" - + " \"protocol\": \"HTTP/1.1\",\n" - + " \"requestId\": \"Bdd2ngt5iGYEMIg=\",\n" - + " \"requestTime\": \"08/Mar/2023:11:50:40 +0000\",\n" - + " \"requestTimeEpoch\": 1678276240455,\n" - + " \"resourceId\": \"$default\",\n" - + " \"resourcePath\": \"$default\",\n" - + " \"stage\": \"$default\"\n" - + " },\n" - + " \"pathParameters\": null,\n" - + " \"stageVariables\": null,\n" - + " \"body\": \"{\\\"name\\\":\\\"bob\\\"}\",\n" - + " \"isBase64Encoded\": false\n" - + "}"; - - private static String API_GATEWAY_EVENT_V2 = "{\n" + - " \"version\": \"2.0\",\n" + - " \"routeKey\": \"$default\",\n" + - " \"rawPath\": \"/async\",\n" + - " \"rawQueryString\": \"parameter1=value1¶meter1=value2¶meter2=value\",\n" + - " \"cookies\": [\n" + - " \"cookie1\",\n" + - " \"cookie2\"\n" + - " ],\n" + - " \"headers\": {\n" + - " \"header1\": \"value1\",\n" + - " \"header2\": \"value1,value2\",\n" + - " \"User-Agent\": \"curl/7.79.1\",\n" + - " \"X-Forwarded-Port\": \"443\"\n" + - " },\n" + - " \"queryStringParameters\": {\n" + - " \"parameter1\": \"value1,value2\",\n" + - " \"parameter2\": \"value\"\n" + - " },\n" + - " \"requestContext\": {\n" + - " \"accountId\": \"123456789012\",\n" + - " \"apiId\": \"api-id\",\n" + - " \"authentication\": {\n" + - " \"clientCert\": {\n" + - " \"clientCertPem\": \"CERT_CONTENT\",\n" + - " \"subjectDN\": \"www.example.com\",\n" + - " \"issuerDN\": \"Example issuer\",\n" + - " \"serialNumber\": \"a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1\",\n" + - " \"validity\": {\n" + - " \"notBefore\": \"May 28 12:30:02 2019 GMT\",\n" + - " \"notAfter\": \"Aug 5 09:36:04 2021 GMT\"\n" + - " }\n" + - " }\n" + - " },\n" + - " \"authorizer\": {\n" + - " \"jwt\": {\n" + - " \"claims\": {\n" + - " \"claim1\": \"value1\",\n" + - " \"claim2\": \"value2\"\n" + - " },\n" + - " \"scopes\": [\n" + - " \"scope1\",\n" + - " \"scope2\"\n" + - " ]\n" + - " }\n" + - " },\n" + - " \"domainName\": \"id.execute-api.us-east-1.amazonaws.com\",\n" + - " \"domainPrefix\": \"id\",\n" + - " \"http\": {\n" + - " \"method\": \"POST\",\n" + - " \"path\": \"/async\",\n" + - " \"protocol\": \"HTTP/1.1\",\n" + - " \"sourceIp\": \"IP\",\n" + - " \"userAgent\": \"agent\"\n" + - " },\n" + - " \"requestId\": \"id\",\n" + - " \"routeKey\": \"$default\",\n" + - " \"stage\": \"$default\",\n" + - " \"time\": \"12/Mar/2020:19:03:58 +0000\",\n" + - " \"timeEpoch\": 1583348638390\n" + - " },\n" + - " \"body\": \"Hello from Lambda\",\n" + - " \"pathParameters\": {\n" + - " \"parameter1\": \"value1\"\n" + - " },\n" + - " \"isBase64Encoded\": false,\n" + - " \"stageVariables\": {\n" + - " \"stageVariable1\": \"value1\",\n" + - " \"stageVariable2\": \"value2\"\n" + - " }\n" + - "}"; - - private static final String ALB_EVENT = "{\n" + - " \"requestContext\": {\n" + - " \"elb\": {\n" + - " \"targetGroupArn\": \"arn:aws:elasticloadbalancing:region:123456789012:targetgroup/my-target-group/6d0ecf831eec9f09\"\n" + - " }\n" + - " },\n" + - " \"httpMethod\": \"POST\",\n" + - " \"path\": \"/async\",\n" + - " \"multiValueQueryStringParameters\": { \"parameter1\": [\"value1\", \"value2\"], \"parameter2\": [\"1970-01-01T00%3A00%3A00.004Z\"]},\n" + - " \"multiValueHeaders\": {\n" + - " \"accept\": [\"text/html,application/xhtml+xml\"],\n" + - " \"accept-language\": [\"en-US,en;q=0.8\"],\n" + - " \"content-type\": [\"text/plain\"],\n" + - " \"cookie\": [\"cookies\"],\n" + - " \"host\": [\"lambda-846800462-us-east-2.elb.amazonaws.com\"],\n" + - " \"User-Agent\": [\"curl/7.79.1\"],\n" + - " \"x-amzn-trace-id\": [\"Root=1-5bdb40ca-556d8b0c50dc66f0511bf520\"],\n" + - " \"x-forwarded-for\": [\"72.21.198.66\"],\n" + - " \"x-forwarded-port\": [\"443\"],\n" + - " \"x-forwarded-proto\": [\"https\"]\n" + - " },\n" + - " \"isBase64Encoded\": false,\n" + - " \"body\": \"request_body\"\n" + - "}"; - - private final ObjectMapper mapper = new ObjectMapper(); - - public static Collection data() { - return Arrays.asList(new String[]{API_GATEWAY_EVENT, API_GATEWAY_EVENT_V2, ALB_EVENT}); - } - - public static Collection v1Data() { - return Arrays.asList(new String[]{API_GATEWAY_EVENT, ALB_EVENT}); - } - - public static Collection v2Data() { - return Arrays.asList(new String[]{API_GATEWAY_EVENT_V2}); - } - - @MethodSource("data") - @ParameterizedTest - public void validateHttpServletRequestGenerationWithInputStream(String jsonEvent) { - ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonEvent.getBytes(StandardCharsets.UTF_8)); - ServerlessServletContext servletContext = new ServerlessServletContext(); - HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(inputStream, null, servletContext, mapper); - assertRequest(request); - } - - private static void assertRequest(HttpServletRequest request) { - assertEquals("curl/7.79.1", request.getHeader("User-Agent")); - assertEquals("443", request.getHeader("X-Forwarded-Port")); - assertEquals("POST", request.getMethod()); - assertEquals("/async", request.getRequestURI()); - assertNotNull(request.getServletContext()); - // parameter handling for 2.0 requests is currently not spec compliant and to be fixed in future version - // see also GitHub issue https://github.com/aws/serverless-java-container/issues/1278 - if (!(request.getAttribute(RequestReader.HTTP_API_EVENT_PROPERTY) instanceof HttpApiV2ProxyRequest)) { - assertEquals("value1", request.getParameter("parameter1")); - assertArrayEquals(new String[]{"value1", "value2"}, request.getParameterValues("parameter1")); - } - if (request.getAttribute(RequestReader.ALB_CONTEXT_PROPERTY) instanceof AlbContext) { - // query params should be decoded - assertEquals("1970-01-01T00:00:00.004Z", request.getParameter("parameter2")); - } - } - - @MethodSource("data") - @ParameterizedTest - public void validateHttpServletRequestGenerationWithJson(String jsonEvent) { - ServerlessServletContext servletContext = new ServerlessServletContext(); - HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(jsonEvent, null, servletContext, mapper); - // spot check some headers - assertRequest(request); - } - - @MethodSource("data") - @ParameterizedTest - public void validateRequestResponse(String jsonEvent) throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run(EmptyApplication.class);) { - ServerlessMVC mvc = ServerlessMVC.INSTANCE((ServletWebServerApplicationContext) context); - AwsProxyHttpServletResponseWriter responseWriter = new AwsProxyHttpServletResponseWriter(); - AwsProxyResponse awsResponse = AwsSpringHttpProcessingUtils.processRequest( - AwsSpringHttpProcessingUtils.generateHttpServletRequest(jsonEvent, null, - mvc.getServletContext(), mapper), mvc, responseWriter); - assertEquals("hello", awsResponse.getBody()); - assertEquals(200, awsResponse.getStatusCode()); - } - - } - - @MethodSource("v1Data") - @ParameterizedTest - public void validateLambdaContextAttribute(String jsonEvent) { - ServerlessServletContext servletContext = new ServerlessServletContext(); - HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(jsonEvent, null, servletContext, mapper); - assertNotNull(request.getAttribute(RequestReader.API_GATEWAY_EVENT_PROPERTY)); - } - - @MethodSource("data") - @ParameterizedTest - public void validateSecurityContextAttribute(String jsonEvent) { - ServerlessServletContext servletContext = new ServerlessServletContext(); - HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(jsonEvent, null, servletContext, mapper); - assertNotNull(request.getAttribute(RequestReader.JAX_SECURITY_CONTEXT_PROPERTY)); - } - - @MethodSource("v1Data") - @ParameterizedTest - public void validateNullMultiValueHeaders(String jsonEvent) throws Exception { - Map event = mapper.readValue(jsonEvent, Map.class); - event.put("multiValueHeaders", null); - String modifiedEvent = mapper.writeValueAsString(event); - ServerlessServletContext servletContext = new ServerlessServletContext(); - HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(modifiedEvent, null, servletContext, mapper); - assertNotNull(request); - } - - @MethodSource("data") - @ParameterizedTest - public void validateBase64EncodedBody(String jsonEvent) throws Exception { - String base64Body = java.util.Base64.getEncoder().encodeToString("test body".getBytes(StandardCharsets.UTF_8)); - Map event = mapper.readValue(jsonEvent, Map.class); - event.put("body", base64Body); - event.put("isBase64Encoded", true); - String modifiedEvent = mapper.writeValueAsString(event); - ServerlessServletContext servletContext = new ServerlessServletContext(); - HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(modifiedEvent, null, servletContext, mapper); - assertNotNull(request); - } - - @MethodSource("v2Data") - @ParameterizedTest - public void validateHttpApiContextAttribute(String jsonEvent) { - ServerlessServletContext servletContext = new ServerlessServletContext(); - HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(jsonEvent, null, servletContext, mapper); - assertNotNull(request.getAttribute(RequestReader.HTTP_API_CONTEXT_PROPERTY)); - assertNotNull(request.getAttribute(RequestReader.HTTP_API_STAGE_VARS_PROPERTY)); - assertNotNull(request.getAttribute(RequestReader.HTTP_API_EVENT_PROPERTY)); - } - - @EnableAutoConfiguration - @Configuration - public static class EmptyApplication { - @RestController - @EnableWebMvc - public static class MyController { - @PostMapping(path = "/async") - public String async(@RequestBody String body) { - return "hello"; - } - } - - @Bean - SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.csrf((csrf) -> csrf.disable()); - return http.build(); - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/JpaAppTest.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/JpaAppTest.java deleted file mode 100644 index a111e510a..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/JpaAppTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.spring.jpaapp.LambdaHandler; -import com.amazonaws.serverless.proxy.spring.jpaapp.MessageController; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Arrays; -import java.util.Collection; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class JpaAppTest { - - LambdaHandler handler; - MockLambdaContext lambdaContext = new MockLambdaContext(); - - private String type; - - public static Collection data() { - return Arrays.asList(new Object[]{"API_GW", "ALB", "HTTP_API"}); - } - - public void initJpaAppTest(String reqType) { - type = reqType; - handler = new LambdaHandler(type); - } - - @MethodSource("data") - @ParameterizedTest - void asyncRequest(String reqType) { - initJpaAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/async", "POST") - .json() - .body("{\"name\":\"kong\"}"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertEquals("{\"name\":\"KONG\"}", resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void helloRequest_respondsWithSingleMessage(String reqType) { - initJpaAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/hello", "GET"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertEquals(MessageController.HELLO_MESSAGE, resp.getBody()); - } - -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SecurityAppTest.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SecurityAppTest.java deleted file mode 100644 index d0b579509..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SecurityAppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.amazonaws.serverless.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.serverless.proxy.spring.securityapp.LambdaHandler; -import com.amazonaws.serverless.proxy.spring.securityapp.SecurityConfig; -import org.junit.jupiter.api.Test; - -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class SecurityAppTest { - - LambdaHandler handler = new LambdaHandler(); - MockLambdaContext lambdaContext = new MockLambdaContext(); - - public SecurityAppTest() { - System.setProperty("logging.level.root", "DEBUG"); - } - - @Test - void helloRequest_withAuth_respondsWithSingleMessage() { - AwsProxyRequest req = new AwsProxyRequestBuilder("/hello", "GET").build(); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertEquals(401, resp.getStatusCode()); - assertTrue(resp.getMultiValueHeaders().containsKey(HttpHeaders.WWW_AUTHENTICATE)); - req = new AwsProxyRequestBuilder("/hello", "GET") - .basicAuth(SecurityConfig.USERNAME, SecurityConfig.PASSWORD) - .header(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN) - .build(); - resp = handler.handleRequest(req, lambdaContext); - assertEquals(200, resp.getStatusCode()); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/ServletAppTest.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/ServletAppTest.java deleted file mode 100644 index b87c80ce6..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/ServletAppTest.java +++ /dev/null @@ -1,236 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import com.amazonaws.serverless.proxy.internal.LambdaContainerHandler; -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.model.ContainerConfig; -import com.amazonaws.serverless.proxy.spring.servletapp.*; -import com.fasterxml.jackson.core.JsonProcessingException; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.stream.Collectors; - -import static org.junit.jupiter.api.Assertions.*; - -public class ServletAppTest { - - LambdaHandler handler; - MockLambdaContext lambdaContext = new MockLambdaContext(); - - private String type; - - public static Collection data() { - return Arrays.asList(new Object[]{"API_GW", "ALB", "HTTP_API"}); - } - - public void initServletAppTest(String reqType) { - type = reqType; - handler = new LambdaHandler(type); - } - - @MethodSource("data") - @ParameterizedTest - void asyncRequest(String reqType) { - initServletAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/async", "POST") - .json() - .body("{\"name\":\"bob\"}"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertEquals("{\"name\":\"BOB\"}", resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void helloRequest_respondsWithSingleMessage(String reqType) { - initServletAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/hello", "GET"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertEquals(MessageController.HELLO_MESSAGE, resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void validateRequest_invalidData_respondsWith400(String reqType) { - initServletAppTest(reqType); - UserData ud = new UserData(); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/validate", "POST") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN) - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) - .body(ud); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - try { - System.out.println(LambdaContainerHandler.getObjectMapper().writeValueAsString(resp)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - assertEquals("3", resp.getBody()); - assertEquals(400, resp.getStatusCode()); - - UserData ud2 = new UserData(); - ud2.setFirstName("Test"); - ud2.setLastName("Test"); - ud2.setEmail("Test"); - req = new AwsProxyRequestBuilder("/validate", "POST") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN) - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) - .body(ud2); - resp = handler.handleRequest(req, lambdaContext); - assertEquals("1", resp.getBody()); - assertEquals(400, resp.getStatusCode()); - } - - @MethodSource("data") - @ParameterizedTest - void messageObject_parsesObject_returnsCorrectMessage(String reqType) { - initServletAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/message", "POST") - .json() - .body(new MessageData("test message")); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals("test message", resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void messageObject_propertiesInContentType_returnsCorrectMessage(String reqType) { - initServletAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/message", "POST") - .header(HttpHeaders.CONTENT_TYPE, "application/json;v=1") - .header(HttpHeaders.ACCEPT, "application/json;v=1") - .body(new MessageData("test message")); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals("test message", resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void echoMessage_fileNameLikeParameter_returnsMessage(String reqType) { - initServletAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/echo/test.test.test", "GET"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals("test.test.test", resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void getUtf8String_returnsValidUtf8String(String reqType) { - initServletAppTest(reqType); - // We expect strings to come back as UTF-8 correctly because Spring itself will call the setCharacterEncoding - // method on the response to set it to UTF- - LambdaContainerHandler.getContainerConfig().setDefaultContentCharset(ContainerConfig.DEFAULT_CONTENT_CHARSET); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/content-type/utf8", "GET") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals("text/plain; charset=UTF-8", resp.getMultiValueHeaders().get(HttpHeaders.CONTENT_TYPE).stream().collect(Collectors.joining(","))); - assertEquals(MessageController.UTF8_RESPONSE, resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void getUtf8Json_returnsValidUtf8String(String reqType) { - initServletAppTest(reqType); - LambdaContainerHandler.getContainerConfig().setDefaultContentCharset(ContainerConfig.DEFAULT_CONTENT_CHARSET); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/content-type/jsonutf8", "GET"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals("{\"s\":\"" + MessageController.UTF8_RESPONSE + "\"}", resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void stream_getUtf8String_returnsValidUtf8String(String reqType) throws IOException { - initServletAppTest(reqType); - LambdaContainerHandler.getContainerConfig().setDefaultContentCharset(ContainerConfig.DEFAULT_CONTENT_CHARSET); - LambdaStreamHandler streamHandler = new LambdaStreamHandler(type); - AwsProxyRequestBuilder reqBuilder = new AwsProxyRequestBuilder("/content-type/utf8", "GET") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN); - InputStream req = null; - switch (type) { - case "ALB": - req = reqBuilder.alb().buildStream(); - break; - case "API_GW": - req = reqBuilder.buildStream(); - break; - case "HTTP_API": - req = reqBuilder.toHttpApiV2RequestStream(); - } - ByteArrayOutputStream out = new ByteArrayOutputStream(); - streamHandler.handleRequest(req, out, lambdaContext); - AwsProxyResponse resp = LambdaContainerHandler.getObjectMapper().readValue(out.toByteArray(), AwsProxyResponse.class); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals(MessageController.UTF8_RESPONSE, resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void stream_getUtf8Json_returnsValidUtf8String(String reqType) throws IOException { - initServletAppTest(reqType); - LambdaContainerHandler.getContainerConfig().setDefaultContentCharset(ContainerConfig.DEFAULT_CONTENT_CHARSET); - LambdaStreamHandler streamHandler = new LambdaStreamHandler(type); - AwsProxyRequestBuilder reqBuilder = new AwsProxyRequestBuilder("/content-type/jsonutf8", "GET"); - InputStream req = null; - switch (type) { - case "ALB": - req = reqBuilder.alb().buildStream(); - break; - case "API_GW": - req = reqBuilder.buildStream(); - break; - case "HTTP_API": - req = reqBuilder.toHttpApiV2RequestStream(); - } - ByteArrayOutputStream out = new ByteArrayOutputStream(); - streamHandler.handleRequest(req, out, lambdaContext); - AwsProxyResponse resp = LambdaContainerHandler.getObjectMapper().readValue(out.toByteArray(), AwsProxyResponse.class); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals("{\"s\":\"" + MessageController.UTF8_RESPONSE + "\"}", resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void springExceptionMapping_throw404Ex_expectMappedTo404(String reqType) { - initServletAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/ex/customstatus", "GET"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertNotNull(resp); - assertEquals(404, resp.getStatusCode()); - } - - @MethodSource("data") - @ParameterizedTest - void echoMessage_populatesSingleValueHeadersForHttpApiV2(String reqType) { - initServletAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/message", "POST") - .header(HttpHeaders.CONTENT_TYPE, "application/json;v=1") - .header(HttpHeaders.ACCEPT, "application/json;v=1") - .body(new MessageData("test message")); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - if ("HTTP_API".equals(type)) { - assertNotNull(resp.getHeaders()); - } else { - assertNull(resp.getHeaders()); - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SlowAppTest.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SlowAppTest.java deleted file mode 100644 index f5e83e85e..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SlowAppTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.amazonaws.serverless.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.serverless.proxy.spring.slowapp.LambdaHandler; -import com.amazonaws.serverless.proxy.spring.slowapp.MessageController; -import com.amazonaws.serverless.proxy.spring.slowapp.SlowTestApplication; -import org.junit.jupiter.api.Test; - -import java.time.Instant; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class SlowAppTest { - - @Test - void slowAppInit_continuesInBackgroundThread_returnsCorrect() { - LambdaHandler slowApp = new LambdaHandler(); - System.out.println("Start time: " + slowApp.getConstructorTime()); - assertTrue(slowApp.getConstructorTime() < 10_000); - AwsProxyRequest req = new AwsProxyRequestBuilder("/hello", "GET").build(); - long startRequestTime = Instant.now().toEpochMilli(); - AwsProxyResponse resp = slowApp.handleRequest(req, new MockLambdaContext()); - long endRequestTime = Instant.now().toEpochMilli(); - assertTrue(endRequestTime - startRequestTime > SlowTestApplication.SlowDownInit.INIT_SLEEP_TIME_MS - 10_000); - assertEquals(200, resp.getStatusCode()); - assertEquals(MessageController.HELLO_MESSAGE, resp.getBody()); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandlerTest.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandlerTest.java deleted file mode 100644 index 871a751bb..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandlerTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.AwsProxyExceptionHandler; -import com.amazonaws.serverless.proxy.AwsProxySecurityContextWriter; -import com.amazonaws.serverless.proxy.InitializationWrapper; -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequestReader; -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.spring.servletapp.ServletApplication; -import com.amazonaws.serverless.proxy.spring.webfluxapp.WebFluxTestApplication; -import java.util.Collection; -import java.util.List; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mockito; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.builder.SpringApplicationBuilder; - -class SpringBootLambdaContainerHandlerTest { - - SpringBootLambdaContainerHandler handler; - SpringApplicationBuilder springApplicationBuilder; - - public static Collection data() { - return List.of(new TestData(WebApplicationType.SERVLET, ServletApplication.class), - new TestData(WebApplicationType.REACTIVE, WebFluxTestApplication.class)); - } - - private void initSpringBootLambdaContainerHandlerTest(Class springBootInitializer, - WebApplicationType applicationType) { - handler = Mockito.spy(new SpringBootLambdaContainerHandler<>(AwsProxyRequest.class, - AwsProxyResponse.class, - new AwsProxyHttpServletRequestReader(), - new AwsProxyHttpServletResponseWriter(), - new AwsProxySecurityContextWriter(), - new AwsProxyExceptionHandler(), - springBootInitializer, - new InitializationWrapper(), - applicationType)); - - doAnswer(d -> { - springApplicationBuilder = ((SpringApplicationBuilder) Mockito.spy(d.callRealMethod())); - return springApplicationBuilder; - }).when(handler).getSpringApplicationBuilder(any(Class[].class)); - } - - @ParameterizedTest - @MethodSource("data") - void initialize_withSpringBootInitializer(TestData data) throws ContainerInitializationException { - initSpringBootLambdaContainerHandlerTest(data.springBootApplication(), data.applicationType()); - handler.initialize(); - - verify(springApplicationBuilder, times(1)).main(data.springBootApplication()); - } - - @ParameterizedTest - @EnumSource(WebApplicationType.class) - void initialize_withoutSpringBootInitializer(WebApplicationType webApplicationType) { - initSpringBootLambdaContainerHandlerTest(null, webApplicationType); - assertThrows(IllegalArgumentException.class, handler::initialize, "Source must not be null"); - - verify(springApplicationBuilder, never()).main(any()); - } - - record TestData(WebApplicationType applicationType, Class springBootApplication) {} -} \ No newline at end of file diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SpringDelegatingLambdaContainerHandlerTests.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SpringDelegatingLambdaContainerHandlerTests.java deleted file mode 100644 index 02ef21d9e..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SpringDelegatingLambdaContainerHandlerTests.java +++ /dev/null @@ -1,350 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.*; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.springframework.util.CollectionUtils; - -import com.amazonaws.serverless.proxy.spring.servletapp.MessageData; -import com.amazonaws.serverless.proxy.spring.servletapp.ServletApplication; -import com.amazonaws.serverless.proxy.spring.servletapp.UserData; -import com.fasterxml.jackson.databind.ObjectMapper; - -import jakarta.ws.rs.core.HttpHeaders; - -@SuppressWarnings("rawtypes") -public class SpringDelegatingLambdaContainerHandlerTests { - - private static String API_GATEWAY_EVENT = "{\n" - + " \"version\": \"1.0\",\n" - + " \"resource\": \"$default\",\n" - + " \"path\": \"/async\",\n" - + " \"httpMethod\": \"POST\",\n" - + " \"headers\": {\n" - + " \"Content-Length\": \"45\",\n" - + " \"Content-Type\": \"application/json\",\n" - + " \"Host\": \"i76bfh111.execute-api.eu-west-3.amazonaws.com\",\n" - + " \"User-Agent\": \"curl/7.79.1\",\n" - + " \"X-Amzn-Trace-Id\": \"Root=1-64087690-2151375b219d3ba3389ea84e\",\n" - + " \"X-Forwarded-For\": \"109.210.252.44\",\n" - + " \"X-Forwarded-Port\": \"443\",\n" - + " \"X-Forwarded-Proto\": \"https\",\n" - + " \"accept\": \"*/*\"\n" - + " },\n" - + " \"multiValueHeaders\": {\n" - + " \"Content-Length\": [\n" - + " \"45\"\n" - + " ],\n" - + " \"Content-Type\": [\n" - + " \"application/json\"\n" - + " ],\n" - + " \"Host\": [\n" - + " \"i76bfhczs0.execute-api.eu-west-3.amazonaws.com\"\n" - + " ],\n" - + " \"User-Agent\": [\n" - + " \"curl/7.79.1\"\n" - + " ],\n" - + " \"X-Amzn-Trace-Id\": [\n" - + " \"Root=1-64087690-2151375b219d3ba3389ea84e\"\n" - + " ],\n" - + " \"X-Forwarded-For\": [\n" - + " \"109.210.252.44\"\n" - + " ],\n" - + " \"X-Forwarded-Port\": [\n" - + " \"443\"\n" - + " ],\n" - + " \"X-Forwarded-Proto\": [\n" - + " \"https\"\n" - + " ],\n" - + " \"accept\": [\n" - + " \"*/*\"\n" - + " ]\n" - + " },\n" - + " \"queryStringParameters\": {\n" - + " \"abc\": \"xyz\",\n" - + " \"name\": \"Ricky\",\n" - + " \"foo\": \"baz\"\n" - + " },\n" - + " \"multiValueQueryStringParameters\": {\n" - + " \"abc\": [\n" - + " \"xyz\"\n" - + " ],\n" - + " \"name\": [\n" - + " \"Ricky\"\n" - + " ],\n" - + " \"foo\": [\n" - + " \"bar\",\n" - + " \"baz\"\n" - + " ]\n" - + " },\n" - + " \"requestContext\": {\n" - + " \"accountId\": \"123456789098\",\n" - + " \"apiId\": \"i76bfhczs0\",\n" - + " \"domainName\": \"i76bfhc111.execute-api.eu-west-3.amazonaws.com\",\n" - + " \"domainPrefix\": \"i76bfhczs0\",\n" - + " \"extendedRequestId\": \"Bdd2ngt5iGYEMIg=\",\n" - + " \"httpMethod\": \"POST\",\n" - + " \"identity\": {\n" - + " \"accessKey\": null,\n" - + " \"accountId\": null,\n" - + " \"caller\": null,\n" - + " \"cognitoAmr\": null,\n" - + " \"cognitoAuthenticationProvider\": null,\n" - + " \"cognitoAuthenticationType\": null,\n" - + " \"cognitoIdentityId\": null,\n" - + " \"cognitoIdentityPoolId\": null,\n" - + " \"principalOrgId\": null,\n" - + " \"sourceIp\": \"109.210.252.44\",\n" - + " \"user\": null,\n" - + " \"userAgent\": \"curl/7.79.1\",\n" - + " \"userArn\": null\n" - + " },\n" - + " \"path\": \"/pets\",\n" - + " \"protocol\": \"HTTP/1.1\",\n" - + " \"requestId\": \"Bdd2ngt5iGYEMIg=\",\n" - + " \"requestTime\": \"08/Mar/2023:11:50:40 +0000\",\n" - + " \"requestTimeEpoch\": 1678276240455,\n" - + " \"resourceId\": \"$default\",\n" - + " \"resourcePath\": \"$default\",\n" - + " \"stage\": \"$default\"\n" - + " },\n" - + " \"pathParameters\": null,\n" - + " \"stageVariables\": null,\n" - + " \"body\": \"{\\\"name\\\":\\\"bob\\\"}\",\n" - + " \"isBase64Encoded\": false\n" - + "}"; - - private static String API_GATEWAY_EVENT_V2 = "{\n" + - " \"version\": \"2.0\",\n" + - " \"routeKey\": \"$default\",\n" + - " \"rawPath\": \"/my/path\",\n" + - " \"rawQueryString\": \"parameter1=value1¶meter1=value2&name=Ricky¶meter2=value\",\n" + - " \"cookies\": [\n" + - " \"cookie1\",\n" + - " \"cookie2\"\n" + - " ],\n" + - " \"headers\": {\n" + - " \"header1\": \"value1\",\n" + - " \"header2\": \"value1,value2\"\n" + - " },\n" + - " \"queryStringParameters\": {\n" + - " \"parameter1\": \"value1,value2\",\n" + - " \"name\": \"Ricky\",\n" + - " \"parameter2\": \"value\"\n" + - " },\n" + - " \"requestContext\": {\n" + - " \"accountId\": \"123456789012\",\n" + - " \"apiId\": \"api-id\",\n" + - " \"authentication\": {\n" + - " \"clientCert\": {\n" + - " \"clientCertPem\": \"CERT_CONTENT\",\n" + - " \"subjectDN\": \"www.example.com\",\n" + - " \"issuerDN\": \"Example issuer\",\n" + - " \"serialNumber\": \"a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1\",\n" + - " \"validity\": {\n" + - " \"notBefore\": \"May 28 12:30:02 2019 GMT\",\n" + - " \"notAfter\": \"Aug 5 09:36:04 2021 GMT\"\n" + - " }\n" + - " }\n" + - " },\n" + - " \"authorizer\": {\n" + - " \"jwt\": {\n" + - " \"claims\": {\n" + - " \"claim1\": \"value1\",\n" + - " \"claim2\": \"value2\"\n" + - " },\n" + - " \"scopes\": [\n" + - " \"scope1\",\n" + - " \"scope2\"\n" + - " ]\n" + - " }\n" + - " },\n" + - " \"domainName\": \"id.execute-api.us-east-1.amazonaws.com\",\n" + - " \"domainPrefix\": \"id\",\n" + - " \"http\": {\n" + - " \"method\": \"POST\",\n" + - " \"path\": \"/my/path\",\n" + - " \"protocol\": \"HTTP/1.1\",\n" + - " \"sourceIp\": \"IP\",\n" + - " \"userAgent\": \"agent\"\n" + - " },\n" + - " \"requestId\": \"id\",\n" + - " \"routeKey\": \"$default\",\n" + - " \"stage\": \"$default\",\n" + - " \"time\": \"12/Mar/2020:19:03:58 +0000\",\n" + - " \"timeEpoch\": 1583348638390\n" + - " },\n" + - " \"body\": \"Hello from Lambda\",\n" + - " \"pathParameters\": {\n" + - " \"parameter1\": \"value1\"\n" + - " },\n" + - " \"isBase64Encoded\": false,\n" + - " \"stageVariables\": {\n" + - " \"stageVariable1\": \"value1\",\n" + - " \"stageVariable2\": \"value2\"\n" + - " }\n" + - "}"; - - private SpringDelegatingLambdaContainerHandler handler; - - private ObjectMapper mapper = new ObjectMapper(); - - public void initServletAppTest() throws ContainerInitializationException { - this.handler = new SpringDelegatingLambdaContainerHandler(ServletApplication.class); - } - - public static Collection data() { - return Arrays.asList(new String[]{API_GATEWAY_EVENT, API_GATEWAY_EVENT_V2}); - } - - @MethodSource("data") - @ParameterizedTest - public void validateComplesrequest(String jsonEvent) throws Exception { - initServletAppTest(); - InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST", - "/foo/male/list/24", "{\"name\":\"bob\"}", false,null)); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - handler.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class); - assertEquals(200, result.get("statusCode")); - String[] responseBody = ((String) result.get("body")).split("/"); - assertEquals("male", responseBody[0]); - assertEquals("24", responseBody[1]); - assertEquals("Ricky", responseBody[2]); - } - - @MethodSource("data") - @ParameterizedTest - public void testAsyncPost(String jsonEvent) throws Exception { - initServletAppTest(); - InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST", "/async", "{\"name\":\"bob\"}",false, null)); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - handler.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class); - assertEquals(200, result.get("statusCode")); - assertEquals("{\"name\":\"BOB\"}", result.get("body")); - } - - @MethodSource("data") - @ParameterizedTest - public void testValidate400(String jsonEvent) throws Exception { - initServletAppTest(); - UserData ud = new UserData(); - InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST", "/validate", mapper.writeValueAsString(ud),false, null)); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - handler.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class); - assertEquals(400, result.get("statusCode")); - assertEquals("3", result.get("body")); - } - - @MethodSource("data") - @ParameterizedTest - public void testValidate200(String jsonEvent) throws Exception { - initServletAppTest(); - UserData ud = new UserData(); - ud.setFirstName("bob"); - ud.setLastName("smith"); - ud.setEmail("foo@bar.com"); - InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST", "/validate", mapper.writeValueAsString(ud),false, null)); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - handler.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class); - assertEquals(200, result.get("statusCode")); - assertEquals("VALID", result.get("body")); - } - - @MethodSource("data") - @ParameterizedTest - public void testValidate200Base64(String jsonEvent) throws Exception { - initServletAppTest(); - UserData ud = new UserData(); - ud.setFirstName("bob"); - ud.setLastName("smith"); - ud.setEmail("foo@bar.com"); - InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST", "/validate", - Base64.getMimeEncoder().encodeToString(mapper.writeValueAsString(ud).getBytes()),true, null)); - - ByteArrayOutputStream output = new ByteArrayOutputStream(); - handler.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class); - assertEquals(200, result.get("statusCode")); - assertEquals("VALID", result.get("body")); - } - - - @MethodSource("data") - @ParameterizedTest - public void messageObject_parsesObject_returnsCorrectMessage(String jsonEvent) throws Exception { - initServletAppTest(); - InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST", "/message", - mapper.writeValueAsString(new MessageData("test message")),false, null)); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - handler.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class); - assertEquals(200, result.get("statusCode")); - assertEquals("test message", result.get("body")); - } - - - - @SuppressWarnings({"unchecked" }) - @MethodSource("data") - @ParameterizedTest - void messageObject_propertiesInContentType_returnsCorrectMessage(String jsonEvent) throws Exception { - initServletAppTest(); - - Map headers = new HashMap<>(); - headers.put(HttpHeaders.CONTENT_TYPE, "application/json;v=1"); - headers.put(HttpHeaders.ACCEPT, "application/json;v=1"); - InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST", "/message", - mapper.writeValueAsString(new MessageData("test message")),false, headers)); - - ByteArrayOutputStream output = new ByteArrayOutputStream(); - handler.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class); - assertEquals("test message", result.get("body")); - } - - private byte[] generateHttpRequest(String jsonEvent, String method, String path, String body,boolean isBase64Encoded, Map headers) throws Exception { - Map requestMap = mapper.readValue(jsonEvent, Map.class); - if (requestMap.get("version").equals("2.0")) { - return generateHttpRequest2(requestMap, method, path, body, isBase64Encoded,headers); - } - return generateHttpRequest(requestMap, method, path, body,isBase64Encoded, headers); - } - - @SuppressWarnings({ "unchecked"}) - private byte[] generateHttpRequest(Map requestMap, String method, String path, String body,boolean isBase64Encoded, Map headers) throws Exception { - requestMap.put("path", path); - requestMap.put("httpMethod", method); - requestMap.put("body", body); - requestMap.put("isBase64Encoded", isBase64Encoded); - if (!CollectionUtils.isEmpty(headers)) { - requestMap.put("headers", headers); - } - return mapper.writeValueAsBytes(requestMap); - } - - @SuppressWarnings({ "unchecked"}) - private byte[] generateHttpRequest2(Map requestMap, String method, String path, String body,boolean isBase64Encoded, Map headers) throws Exception { - Map map = mapper.readValue(API_GATEWAY_EVENT_V2, Map.class); - Map http = (Map) ((Map) map.get("requestContext")).get("http"); - http.put("path", path); - http.put("method", method); - map.put("body", body); - map.put("isBase64Encoded", isBase64Encoded); - if (!CollectionUtils.isEmpty(headers)) { - map.put("headers", headers); - } - return mapper.writeValueAsBytes(map); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/WebFluxAppTest.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/WebFluxAppTest.java deleted file mode 100644 index 9c39fd905..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/WebFluxAppTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.amazonaws.serverless.proxy.spring; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.spring.webfluxapp.LambdaHandler; -import com.amazonaws.serverless.proxy.spring.webfluxapp.MessageController; -import com.amazonaws.serverless.proxy.spring.webfluxapp.MessageData; -import com.fasterxml.jackson.core.JsonProcessingException; - -public class WebFluxAppTest { - - LambdaHandler handler; - MockLambdaContext lambdaContext = new MockLambdaContext(); - - private String type; - - public static Collection data() { - return Arrays.asList(new Object[]{"API_GW", "ALB", "HTTP_API"}); - } - - public void initWebFluxAppTest(String reqType) { - type = reqType; - handler = new LambdaHandler(type); - } - - @MethodSource("data") - @ParameterizedTest - void helloRequest_respondsWithSingleMessage(String reqType) { - initWebFluxAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/single", "GET"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - System.out.println(resp.getBody()); - assertEquals(MessageController.MESSAGE, resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void helloDoubleRequest_respondsWithDoubleMessage(String reqType) { - initWebFluxAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/double", "GET"); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - - assertEquals(MessageController.MESSAGE + MessageController.MESSAGE, resp.getBody()); - } - - @MethodSource("data") - @ParameterizedTest - void messageObject_parsesObject_returnsCorrectMessage(String reqType) throws JsonProcessingException { - initWebFluxAppTest(reqType); - AwsProxyRequestBuilder req = new AwsProxyRequestBuilder("/message", "POST") - .json() - .body(new MessageData("test message")); - AwsProxyResponse resp = handler.handleRequest(req, lambdaContext); - assertNotNull(resp); - assertEquals(200, resp.getStatusCode()); - assertEquals("test message", resp.getBody()); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactoryTest.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactoryTest.java deleted file mode 100644 index 5ffd4a311..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/embedded/ServerlessServletEmbeddedServerFactoryTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.embedded; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.AwsProxyExceptionHandler; -import com.amazonaws.serverless.proxy.AwsProxySecurityContextWriter; -import com.amazonaws.serverless.proxy.InitializationWrapper; -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequestReader; -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; -import org.junit.jupiter.api.Test; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.web.servlet.ServletContextInitializer; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; - -import static org.junit.jupiter.api.Assertions.fail; - -public class ServerlessServletEmbeddedServerFactoryTest { - private SpringBootLambdaContainerHandler handler = new SpringBootLambdaContainerHandler<>( - AwsProxyRequest.class, - AwsProxyResponse.class, - new AwsProxyHttpServletRequestReader(), - new AwsProxyHttpServletResponseWriter(), - new AwsProxySecurityContextWriter(), - new AwsProxyExceptionHandler(), - null, - new InitializationWrapper(), - WebApplicationType.REACTIVE - ); - - public ServerlessServletEmbeddedServerFactoryTest() throws ContainerInitializationException { - } - - @Test - void getWebServer_callsInitializers() { - ServerlessServletEmbeddedServerFactory factory = new ServerlessServletEmbeddedServerFactory(); - factory.getWebServer(new ServletContextInitializer() { - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - if (servletContext == null) { - fail("Null servlet context"); - } - } - }); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/DatabaseConfig.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/DatabaseConfig.java deleted file mode 100644 index aeef7c65e..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/DatabaseConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.jpaapp; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.DriverManagerDataSource; - -import javax.sql.DataSource; - -@Configuration -public class DatabaseConfig { - - @Bean - public DataSource dataSource() { - DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setUrl("jdbc:h2:mem:testdb"); - dataSource.setUsername("sa"); - dataSource.setPassword(""); - - return dataSource; - } -} - diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/JpaApplication.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/JpaApplication.java deleted file mode 100644 index 5aced5e28..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/JpaApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.jpaapp; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.logging.LogLevel; -import org.springframework.boot.logging.LoggingSystem; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; - -@SpringBootApplication(exclude = { - org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class -}) -@Import(MessageController.class) -public class JpaApplication {} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/LambdaHandler.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/LambdaHandler.java deleted file mode 100644 index 0cf67c10f..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/LambdaHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.jpaapp; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.InitializationWrapper; -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest; -import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; -import com.amazonaws.serverless.proxy.spring.SpringBootProxyHandlerBuilder; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; - -public class LambdaHandler implements RequestHandler { - private static SpringBootLambdaContainerHandler handler; - private static SpringBootLambdaContainerHandler httpApiHandler; - private String type; - - public LambdaHandler(String reqType) { - type = reqType; - try { - switch (type) { - case "API_GW": - case "ALB": - handler = new SpringBootProxyHandlerBuilder() - .defaultProxy() - .initializationWrapper(new InitializationWrapper()) - .servletApplication() - .springBootApplication(JpaApplication.class) - .buildAndInitialize(); - break; - case "HTTP_API": - httpApiHandler = new SpringBootProxyHandlerBuilder() - .defaultHttpApiV2Proxy() - .initializationWrapper(new InitializationWrapper()) - .servletApplication() - .springBootApplication(JpaApplication.class) - .buildAndInitialize(); - break; - } - } catch (ContainerInitializationException e) { - e.printStackTrace(); - } - } - - @Override - public AwsProxyResponse handleRequest(AwsProxyRequestBuilder awsProxyRequest, Context context) { - switch (type) { - case "API_GW": - return handler.proxy(awsProxyRequest.build(), context); - case "ALB": - return handler.proxy(awsProxyRequest.alb().build(), context); - case "HTTP_API": - return httpApiHandler.proxy(awsProxyRequest.toHttpApiV2Request(), context); - default: - throw new RuntimeException("Unknown request type: " + type); - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/MessageController.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/MessageController.java deleted file mode 100644 index a85292262..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/jpaapp/MessageController.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.jpaapp; - -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.context.request.async.DeferredResult; -import java.util.Collections; -import java.util.Map; - -@RestController -public class MessageController { - - public static final String HELLO_MESSAGE = "Hello"; - - @RequestMapping(path="/hello", method=RequestMethod.GET, produces = {"text/plain"}) - public String hello() { - return HELLO_MESSAGE; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @RequestMapping(path = "/async", method = RequestMethod.POST) - @ResponseBody - public DeferredResult> asyncResult(@RequestBody Map value) { - DeferredResult result = new DeferredResult<>(); - result.setResult(Collections.singletonMap("name", value.get("name").toUpperCase())); - return result; - } - -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/LambdaHandler.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/LambdaHandler.java deleted file mode 100644 index ae8ba21ac..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/LambdaHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.securityapp; - -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(SecurityApplication.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-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/MessageController.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/MessageController.java deleted file mode 100644 index ad67d4766..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/MessageController.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.securityapp; - -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.Mono; - - -@RestController -public class MessageController { - public static final String HELLO_MESSAGE = "Hello"; - - @RequestMapping(path="/hello", method=RequestMethod.GET, produces = {"text/plain"}) - public Mono hello() { - return Mono.just(HELLO_MESSAGE); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/SecurityApplication.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/SecurityApplication.java deleted file mode 100644 index d4036dcfe..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/SecurityApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.securityapp; - -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Import; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.web.reactive.config.EnableWebFlux; - -@SpringBootApplication(exclude = { - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class, - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.class -}) -@EnableWebFluxSecurity -@EnableWebFlux -@Import(SecurityConfig.class) -public class SecurityApplication { -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/SecurityConfig.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/SecurityConfig.java deleted file mode 100644 index d83b81db6..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/securityapp/SecurityConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.securityapp; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.web.server.SecurityWebFilterChain; - -@Configuration -@EnableWebFluxSecurity -public class SecurityConfig -{ - public static final String USERNAME = "admin"; - public static final String PASSWORD = "{noop}password"; - private static BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - - @Bean - public SecurityWebFilterChain securitygWebFilterChain( - ServerHttpSecurity http) { - return http.authorizeExchange() - .anyExchange().authenticated().and().csrf().disable() - .httpBasic() - .and().build(); - } - - @Bean - public static BCryptPasswordEncoder passwordEncoder() { - return passwordEncoder; - } - - @Bean - public MapReactiveUserDetailsService userDetailsService() { - UserDetails user = User - .withUsername(USERNAME) - .password(passwordEncoder.encode(PASSWORD)) - .roles("USER") - .build(); - return new MapReactiveUserDetailsService(user); - } -} \ No newline at end of file diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/LambdaHandler.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/LambdaHandler.java deleted file mode 100644 index 88441988e..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/LambdaHandler.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.servletapp; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.InitializationWrapper; -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest; -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest; -import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; -import com.amazonaws.serverless.proxy.spring.SpringBootProxyHandlerBuilder; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; - -public class LambdaHandler implements RequestHandler { - private static SpringBootLambdaContainerHandler handler; - private static SpringBootLambdaContainerHandler httpApiHandler; - private String type; - - public LambdaHandler(String reqType) { - type = reqType; - try { - switch (type) { - case "API_GW": - case "ALB": - handler = new SpringBootProxyHandlerBuilder() - .defaultProxy() - .initializationWrapper(new InitializationWrapper()) - .servletApplication() - .springBootApplication(ServletApplication.class) - .buildAndInitialize(); - break; - case "HTTP_API": - httpApiHandler = new SpringBootProxyHandlerBuilder() - .defaultHttpApiV2Proxy() - .initializationWrapper(new InitializationWrapper()) - .servletApplication() - .springBootApplication(ServletApplication.class) - .buildAndInitialize(); - break; - } - } catch (ContainerInitializationException e) { - e.printStackTrace(); - } - } - - @Override - public AwsProxyResponse handleRequest(AwsProxyRequestBuilder awsProxyRequest, Context context) { - switch (type) { - case "API_GW": - return handler.proxy(awsProxyRequest.build(), context); - case "ALB": - return handler.proxy(awsProxyRequest.alb().build(), context); - case "HTTP_API": - return httpApiHandler.proxy(awsProxyRequest.toHttpApiV2Request(), context); - default: - throw new RuntimeException("Unknown request type: " + type); - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/LambdaStreamHandler.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/LambdaStreamHandler.java deleted file mode 100644 index fd7d71d79..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/LambdaStreamHandler.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.servletapp; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.InitializationWrapper; -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest; -import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; -import com.amazonaws.serverless.proxy.spring.SpringBootProxyHandlerBuilder; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class LambdaStreamHandler implements RequestStreamHandler { - private static SpringBootLambdaContainerHandler handler; - private static SpringBootLambdaContainerHandler httpApiHandler; - private String type; - - public LambdaStreamHandler(String reqType) { - type = reqType; - try { - switch (type) { - case "API_GW": - case "ALB": - handler = new SpringBootProxyHandlerBuilder() - .defaultProxy() - .initializationWrapper(new InitializationWrapper()) - .servletApplication() - .springBootApplication(ServletApplication.class) - .buildAndInitialize(); - break; - case "HTTP_API": - httpApiHandler = new SpringBootProxyHandlerBuilder() - .defaultHttpApiV2Proxy() - .initializationWrapper(new InitializationWrapper()) - .servletApplication() - .springBootApplication(ServletApplication.class) - .buildAndInitialize(); - break; - } - } catch (ContainerInitializationException e) { - e.printStackTrace(); - } - } - - @Override - public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { - switch (type) { - case "API_GW": - case "ALB": - handler.proxyStream(inputStream, outputStream, context); - break; - case "HTTP_API": - httpApiHandler.proxyStream(inputStream, outputStream, context); - } - - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/MessageController.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/MessageController.java deleted file mode 100644 index 1923396c6..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/MessageController.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.servletapp; - -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.Errors; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.context.request.async.DeferredResult; -import org.springframework.web.server.ResponseStatusException; - -import jakarta.validation.Valid; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -@RestController -public class MessageController { - public static final String HELLO_MESSAGE = "Hello"; - public static final String VALID_MESSAGE = "VALID"; - public static final String UTF8_RESPONSE = "öüäß фрыцшщ"; - public static final String EX_MESSAGE = "404 exception message"; - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @RequestMapping(path = "/async", method = RequestMethod.POST) - @ResponseBody - public DeferredResult> asyncResult(@RequestBody Map value) { - DeferredResult result = new DeferredResult<>(); - result.setResult(Collections.singletonMap("name", value.get("name").toUpperCase())); - return result; - } - - @RequestMapping(path="/hello", method=RequestMethod.GET, produces = {"text/plain"}) - public String hello() { - return HELLO_MESSAGE; - } - - @RequestMapping(path="/validate", method=RequestMethod.POST, produces = {"text/plain"}) - public ResponseEntity validateBody(@RequestBody @Valid UserData userData, Errors errors) { - if (errors != null && errors.hasErrors()) { - return ResponseEntity.badRequest().body(errors.getErrorCount() + ""); - } - return ResponseEntity.ok(VALID_MESSAGE); - } - - @RequestMapping(path="/message", method = RequestMethod.POST) - public String returnMessage(@RequestBody MessageData data) { - if (data == null) { - throw new RuntimeException("No message data"); - } - return data.getMessage(); - } - - @RequestMapping(path="/echo/{message}", method=RequestMethod.GET) - public String returnPathMessage(@PathVariable(value="message") String message) { - return message; - } - - @GetMapping(value = "/content-type/utf8", produces = "text/plain") - public ResponseEntity getUtf8String() { - return ResponseEntity.ok(UTF8_RESPONSE); - } - - @GetMapping(value = "/content-type/jsonutf8", produces=MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> getUtf8Json() { - Map resp = new HashMap(); - resp.put("s", UTF8_RESPONSE); - return ResponseEntity.ok(resp); - } - - @GetMapping(value = "/ex/customstatus") - public String throw404Exception() { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, EX_MESSAGE); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/MessageData.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/MessageData.java deleted file mode 100644 index 129101cbe..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/MessageData.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.servletapp; - -public class MessageData { - private String message; - - public MessageData() { - } - - public MessageData(String m) { - setMessage(m); - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/ServletApplication.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/ServletApplication.java deleted file mode 100644 index 9f01859aa..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/ServletApplication.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.servletapp; - -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Import; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@SpringBootApplication(exclude = { - org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class, - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class, - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.class -}) -@Import(MessageController.class) -@RestController -public class ServletApplication { - - @RequestMapping(path = "/foo/{gender}/list/{age}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public String complexRequest( - @PathVariable("gender") String gender, - @PathVariable("age") String age, - @RequestParam("name") String name - ) { - return gender + "/" + age + "/" + name; - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/UserData.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/UserData.java deleted file mode 100644 index 379291a39..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/UserData.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.servletapp; - - -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -public class UserData { - @NotBlank - private String firstName; - @NotBlank - private String lastName; - @NotNull @Email - private String email; - private String error; - - public UserData() { - - } - - public UserData(String err) { - error = err; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getError() { return error; } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/LambdaHandler.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/LambdaHandler.java deleted file mode 100644 index 22f75e7a9..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/LambdaHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.slowapp; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; -import com.amazonaws.serverless.proxy.spring.SpringBootProxyHandlerBuilder; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; - -import java.time.Instant; - -public class LambdaHandler implements RequestHandler { - private SpringBootLambdaContainerHandler handler; - private long constructorTime; - - public LambdaHandler() { - try { - long startTime = Instant.now().toEpochMilli(); - System.out.println("startCall: " + startTime); - handler = new SpringBootProxyHandlerBuilder() - .defaultProxy() - .springBootApplication(SlowTestApplication.class) - .buildAndInitialize(); - constructorTime = Instant.now().toEpochMilli() - startTime; - } catch (ContainerInitializationException e) { - e.printStackTrace(); - } - } - - public long getConstructorTime() { - return constructorTime; - } - - @Override - public AwsProxyResponse handleRequest(AwsProxyRequest awsProxyRequest, Context context) { - return handler.proxy(awsProxyRequest, context); - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/MessageController.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/MessageController.java deleted file mode 100644 index 098e8e7df..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/MessageController.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.slowapp; - -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-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/SlowTestApplication.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/SlowTestApplication.java deleted file mode 100644 index 006e51e45..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/slowapp/SlowTestApplication.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.slowapp; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.stereotype.Component; - -import java.time.Instant; - -@SpringBootApplication(exclude = { - org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration.class, - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class, - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.class -}) -public class SlowTestApplication { - - @Component - public static class SlowDownInit implements InitializingBean { - public static final int INIT_SLEEP_TIME_MS = 13_000; - - @Override - public void afterPropertiesSet() throws Exception { - Thread.sleep(INIT_SLEEP_TIME_MS); - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/LambdaHandler.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/LambdaHandler.java deleted file mode 100644 index 0eb52a7bc..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/LambdaHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.webfluxapp; - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -import com.amazonaws.serverless.proxy.InitializationWrapper; -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest; -import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler; -import com.amazonaws.serverless.proxy.spring.SpringBootProxyHandlerBuilder; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; - -public class LambdaHandler implements RequestHandler { - private static SpringBootLambdaContainerHandler handler; - private static SpringBootLambdaContainerHandler httpApiHandler; - - private String type; - - public LambdaHandler(String reqType) { - type = reqType; - try { - switch (type) { - case "API_GW": - case "ALB": - handler = new SpringBootProxyHandlerBuilder() - .defaultProxy() - .initializationWrapper(new InitializationWrapper()) - .springBootApplication(WebFluxTestApplication.class) - .buildAndInitialize(); - break; - case "HTTP_API": - httpApiHandler = new SpringBootProxyHandlerBuilder() - .defaultHttpApiV2Proxy() - .initializationWrapper(new InitializationWrapper()) - .springBootApplication(WebFluxTestApplication.class) - .buildAndInitialize(); - break; - } - } catch (ContainerInitializationException e) { - e.printStackTrace(); - } - } - - @Override - public AwsProxyResponse handleRequest(AwsProxyRequestBuilder awsProxyRequest, Context context) { - switch (type) { - case "API_GW": - return handler.proxy(awsProxyRequest.build(), context); - case "ALB": - return handler.proxy(awsProxyRequest.alb().build(), context); - case "HTTP_API": - return httpApiHandler.proxy(awsProxyRequest.toHttpApiV2Request(), context); - default: - throw new RuntimeException("Unknown request type: " + type); - } - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/MessageController.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/MessageController.java deleted file mode 100644 index a04604618..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/MessageController.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.webfluxapp; - -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import reactor.core.publisher.Flux; - -@RestController -public class MessageController { - public static final String MESSAGE = "Hello"; - - @RequestMapping(path="/single", method= RequestMethod.GET, produces = {"text/plain"}) - Flux singleMessage(){ - return Flux.just( - MESSAGE - ); - } - - @RequestMapping(path="/double", method= RequestMethod.GET, produces={"text/plain"}) - Flux doubleMessage(){ - return Flux.just( - MESSAGE, - MESSAGE - ); - } - - @RequestMapping(path="/message", method = RequestMethod.POST, produces={"text/plain"}, consumes = {"application/json"}) - public Flux returnMessage(@RequestBody MessageData data) { - if (data == null) { - throw new RuntimeException("No message data"); - } - return Flux.just(data.getMessage()); - } -} \ No newline at end of file diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/MessageData.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/MessageData.java deleted file mode 100644 index 2be6b4f2d..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/MessageData.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.webfluxapp; - -public class MessageData { - private String message; - - public MessageData() { - } - - public MessageData(String m) { - setMessage(m); - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/WebFluxTestApplication.java b/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/WebFluxTestApplication.java deleted file mode 100644 index fc6aecd6f..000000000 --- a/aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/webfluxapp/WebFluxTestApplication.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.amazonaws.serverless.proxy.spring.webfluxapp; - -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Import; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.web.reactive.config.EnableWebFlux; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -@SpringBootApplication(exclude = { - org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration.class, - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class, - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class, - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.class -}) -public class WebFluxTestApplication { - -} diff --git a/aws-serverless-springboot3-archetype/pom.xml b/aws-serverless-springboot3-archetype/pom.xml deleted file mode 100644 index a435098d6..000000000 --- a/aws-serverless-springboot3-archetype/pom.xml +++ /dev/null @@ -1,80 +0,0 @@ - - 4.0.0 - - - com.amazonaws.serverless - aws-serverless-java-container - 3.0.1-SNAPSHOT - - - com.amazonaws.serverless.archetypes - aws-serverless-springboot3-archetype - 2.1.5 - maven-archetype - - - https://github.com/aws/serverless-java-container.git - HEAD - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - - - src/main/resources - true - - archetype-resources/pom.xml - archetype-resources/README.md - - - - src/main/resources - false - - archetype-resources/pom.xml - - - - - - - org.apache.maven.archetype - archetype-packaging - 3.4.0 - - - - - - - org.apache.maven.plugins - maven-resources-plugin - 3.3.1 - - \ - - - - org.apache.maven.plugins - maven-archetype-plugin - 3.4.0 - - - - integration-test - - - - - - - - diff --git a/aws-serverless-springboot3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/aws-serverless-springboot3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml deleted file mode 100644 index 5379692ba..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - src/main/java - - **/*.java - - - - src/main/resources - - **/*.properties - - - - src/test/java - - **/*.java - - - - src/assembly - - * - - - - - - template.yml - README.md - build.gradle - - - - \ No newline at end of file diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/README.md b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/README.md deleted file mode 100644 index 311c40aee..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/README.md +++ /dev/null @@ -1,99 +0,0 @@ -#set($resourceName = $artifactId) -#macro(replaceChar $originalName, $char) - #if($originalName.contains($char)) - #set($tokens = $originalName.split($char)) - #set($newResourceName = "") - #foreach($token in $tokens) - #set($newResourceName = $newResourceName + $token.substring(0,1).toUpperCase() + $token.substring(1).toLowerCase()) - #end - ${newResourceName} - #else - #set($newResourceName = $originalName.substring(0,1).toUpperCase() + $originalName.substring(1)) - ${newResourceName} - #end -#end -#set($resourceName = "#replaceChar($resourceName, '-')") -#set($resourceName = "#replaceChar($resourceName, '.')") -#set($resourceName = $resourceName.replaceAll("\n", "").trim()) -# \${artifactId} serverless API -The \${artifactId} project, created with [`aws-serverless-java-container`](https://github.com/aws/serverless-java-container). - -The starter project defines a simple `/ping` resource that can accept `GET` requests with its tests. - -The project folder also includes a `template.yml` file. You can use this [SAM](https://github.com/awslabs/serverless-application-model) file to deploy the project to AWS Lambda and Amazon API Gateway or test in local with the [SAM CLI](https://github.com/awslabs/aws-sam-cli). - -#[[##]]# Pre-requisites -* [AWS CLI](https://aws.amazon.com/cli/) -* [SAM CLI](https://github.com/awslabs/aws-sam-cli) -* [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/) - -#[[##]]# Building the project -You can use the SAM CLI to quickly build the project -```bash -$ mvn archetype:generate -DartifactId=\${artifactId} -DarchetypeGroupId=com.amazonaws.serverless.archetypes -DarchetypeArtifactId=aws-serverless-jersey-archetype -DarchetypeVersion=${project.version} -DgroupId=\${groupId} -Dversion=\${version} -Dinteractive=false -$ cd \${artifactId} -$ sam build -Building resource '\${resourceName}Function' -Running JavaGradleWorkflow:GradleBuild -Running JavaGradleWorkflow:CopyArtifacts - -Build Succeeded - -Built Artifacts : .aws-sam/build -Built Template : .aws-sam/build/template.yaml - -Commands you can use next -========================= -[*] Invoke Function: sam local invoke -[*] Deploy: sam deploy --guided -``` - -#[[##]]# Testing locally with the SAM CLI - -From the project root folder - where the `template.yml` file is located - start the API with the SAM CLI. - -```bash -$ sam local start-api - -... -Mounting ${groupId}.StreamLambdaHandler::handleRequest (java11) at http://127.0.0.1:3000/{proxy+} [OPTIONS GET HEAD POST PUT DELETE PATCH] -... -``` - -Using a new shell, you can send a test ping request to your API: - -```bash -$ curl -s http://127.0.0.1:3000/ping | python -m json.tool - -{ - "pong": "Hello, World!" -} -``` - -#[[##]]# Deploying to AWS -To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen - -``` -$ sam deploy --guided -``` - -Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new application URL. You can use `curl` or a web browser to make a call to the URL - -``` -... -------------------------------------------------------------------------------------------------------------- -OutputKey-Description OutputValue -------------------------------------------------------------------------------------------------------------- -\${resourceName}Api - URL for application https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/pets -------------------------------------------------------------------------------------------------------------- -``` - -Copy the `OutputValue` into a browser or use curl to test your first request: - -```bash -$ curl -s https://xxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/ping | python -m json.tool - -{ - "pong": "Hello, World!" -} -``` diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/build.gradle b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/build.gradle deleted file mode 100644 index 3aa54825c..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/build.gradle +++ /dev/null @@ -1,37 +0,0 @@ -apply plugin: 'java' - -repositories { - mavenLocal() - mavenCentral() - maven {url "https://repo.spring.io/milestone"} - maven {url "https://repo.spring.io/snapshot"} -} - -dependencies { - implementation ( - 'org.springframework.boot:spring-boot-starter-web:3.4.5', - 'com.amazonaws.serverless:aws-serverless-java-container-springboot3:[2.0-SNAPSHOT,)', - ) - - testImplementation("com.amazonaws.serverless:aws-serverless-java-container-core:[2.0-SNAPSHOT,):tests") - testImplementation("org.apache.httpcomponents.client5:httpclient5:5.5") - testImplementation(platform("org.junit:junit-bom:5.13.1")) - testImplementation("org.junit.jupiter:junit-jupiter") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") -} - -task buildZip(type: Zip) { - from compileJava - from processResources - into('lib') { - from(configurations.compileClasspath) { - exclude 'tomcat-embed-*' - } - } -} - -test { - useJUnitPlatform() -} - -build.dependsOn buildZip diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/pom.xml b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/pom.xml deleted file mode 100644 index 39f5f6037..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/pom.xml +++ /dev/null @@ -1,180 +0,0 @@ -#set($dollar = '$') - - - 4.0.0 - - \${groupId} - \${artifactId} - \${version} - jar - - Serverless Spring Boot 3 API - https://github.com/aws/serverless-java-container - - - org.springframework.boot - spring-boot-starter-parent - 3.4.5 - - - - 17 - 5.12.1 - - - - - com.amazonaws.serverless - aws-serverless-java-container-springboot3 - 2.1.5 - - - com.amazonaws.serverless - aws-serverless-java-container-core - 2.1.5 - tests - test-jar - test - - - org.apache.httpcomponents.client5 - httpclient5 - 5.4.3 - test - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - - org.junit.jupiter - junit-jupiter - test - - - - - - - org.junit - junit-bom - ${junit.version} - import - pom - - - - - - - shaded-jar - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - false - - - - package - - shade - - - - - org.apache.tomcat.embed:* - - - - - - - - - - - assembly-zip - - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - - default-jar - none - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.2 - - true - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.8.1 - - - copy-dependencies - package - - copy-dependencies - - - ${dollar}{project.build.directory}${dollar}{file.separator}lib - runtime - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.7.1 - - - zip-assembly - package - - single - - - ${dollar}{project.artifactId}-${dollar}{project.version} - - src${dollar}{file.separator}assembly${dollar}{file.separator}bin.xml - - false - - - - - - - - - diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/assembly/bin.xml b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/assembly/bin.xml deleted file mode 100644 index 1e085057d..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/assembly/bin.xml +++ /dev/null @@ -1,27 +0,0 @@ - - lambda-package - - zip - - false - - - - ${project.build.directory}${file.separator}lib - lib - - tomcat-embed* - - - - - ${project.build.directory}${file.separator}classes - - ** - - ${file.separator} - - - \ No newline at end of file diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/Application.java b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/Application.java deleted file mode 100644 index 1b74086f7..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/Application.java +++ /dev/null @@ -1,24 +0,0 @@ -#macro(loggingOff) - logging.level.root:OFF -#end -#set($logging = "#loggingOff()") -#set($logging = $logging.replaceAll("\n", "").trim()) -package ${groupId}; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Import; - -import ${groupId}.controller.PingController; - - -@SpringBootApplication -// We use direct @Import instead of @ComponentScan to speed up cold starts -// @ComponentScan(basePackages = "${groupId}.controller") -@Import({ PingController.class }) -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} \ No newline at end of file diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/StreamLambdaHandler.java b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/StreamLambdaHandler.java deleted file mode 100644 index e022540c1..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/StreamLambdaHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package ${groupId}; - - -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.RequestStreamHandler; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - - -public class StreamLambdaHandler implements RequestStreamHandler { - private static SpringBootLambdaContainerHandler handler; - static { - try { - handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class); - } catch (ContainerInitializationException e) { - // if we fail here. We re-throw the exception to force another cold start - e.printStackTrace(); - throw new RuntimeException("Could not initialize Spring Boot application", e); - } - } - - @Override - public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) - throws IOException { - handler.proxyStream(inputStream, outputStream, context); - } -} \ No newline at end of file diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/controller/PingController.java b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/controller/PingController.java deleted file mode 100644 index 94f517f07..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/java/controller/PingController.java +++ /dev/null @@ -1,20 +0,0 @@ -package ${groupId}.controller; - - -import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -import java.util.HashMap; -import java.util.Map; - - -@RestController -@EnableWebMvc -public class PingController { - @RequestMapping(path = "/ping", method = RequestMethod.GET) - public Map ping() { - Map pong = new HashMap<>(); - pong.put("pong", "Hello, World!"); - return pong; - } -} diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/resources/application.properties b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/resources/application.properties deleted file mode 100644 index 070e632fe..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -# Reduce logging level to make sure the application works with SAM local -# https://github.com/aws/serverless-java-container/issues/134 -logging.level.root=WARN \ No newline at end of file diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/test/java/StreamLambdaHandlerTest.java b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/test/java/StreamLambdaHandlerTest.java deleted file mode 100644 index 26d5360bf..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/src/test/java/StreamLambdaHandlerTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package ${groupId}; - - -import com.amazonaws.serverless.proxy.internal.LambdaContainerHandler; -import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder; -import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext; -import com.amazonaws.serverless.proxy.model.AwsProxyResponse; -import com.amazonaws.services.lambda.runtime.Context; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import jakarta.ws.rs.HttpMethod; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import static org.junit.jupiter.api.Assertions.*; - -public class StreamLambdaHandlerTest { - - private static StreamLambdaHandler handler; - private static Context lambdaContext; - - @BeforeAll - public static void setUp() { - handler = new StreamLambdaHandler(); - lambdaContext = new MockLambdaContext(); - } - - @Test - public void ping_streamRequest_respondsWithHello() { - InputStream requestStream = new AwsProxyRequestBuilder("/ping", HttpMethod.GET) - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON) - .buildStream(); - ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); - - handle(requestStream, responseStream); - - AwsProxyResponse response = readResponse(responseStream); - assertNotNull(response); - assertEquals(Response.Status.OK.getStatusCode(), response.getStatusCode()); - - assertFalse(response.isBase64Encoded()); - - assertTrue(response.getBody().contains("pong")); - assertTrue(response.getBody().contains("Hello, World!")); - - assertTrue(response.getMultiValueHeaders().containsKey(HttpHeaders.CONTENT_TYPE)); - assertTrue(response.getMultiValueHeaders().getFirst(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.APPLICATION_JSON)); - } - - @Test - public void invalidResource_streamRequest_responds404() { - InputStream requestStream = new AwsProxyRequestBuilder("/pong", HttpMethod.GET) - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON) - .buildStream(); - ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); - - handle(requestStream, responseStream); - - AwsProxyResponse response = readResponse(responseStream); - assertNotNull(response); - assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatusCode()); - } - - private void handle(InputStream is, ByteArrayOutputStream os) { - try { - handler.handleRequest(is, os, lambdaContext); - } catch (IOException e) { - e.printStackTrace(); - fail(e.getMessage()); - } - } - - private AwsProxyResponse readResponse(ByteArrayOutputStream responseStream) { - try { - return LambdaContainerHandler.getObjectMapper().readValue(responseStream.toByteArray(), AwsProxyResponse.class); - } catch (IOException e) { - e.printStackTrace(); - fail("Error while parsing response: " + e.getMessage()); - } - return null; - } -} diff --git a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/template.yml b/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/template.yml deleted file mode 100644 index fe96b1fa2..000000000 --- a/aws-serverless-springboot3-archetype/src/main/resources/archetype-resources/template.yml +++ /dev/null @@ -1,52 +0,0 @@ -#set($resourceName = $artifactId) -#macro(replaceChar $originalName, $char) - #if($originalName.contains($char)) - #set($tokens = $originalName.split($char)) - #set($newResourceName = "") - #foreach($token in $tokens) - #set($newResourceName = $newResourceName + $token.substring(0,1).toUpperCase() + $token.substring(1).toLowerCase()) - #end - ${newResourceName} - #else - #set($newResourceName = $originalName.substring(0,1).toUpperCase() + $originalName.substring(1)) - ${newResourceName} - #end -#end -#set($resourceName = "#replaceChar($resourceName, '-')") -#set($resourceName = "#replaceChar($resourceName, '.')") -#set($resourceName = $resourceName.replaceAll("\n", "").trim()) -#macro(regionVar) - AWS::Region -#end -#set($awsRegion = "#regionVar()") -#set($awsRegion = $awsRegion.replaceAll("\n", "").trim()) -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: AWS Serverless Spring Boot 2 API - ${groupId}::${artifactId} -Globals: - Api: - EndpointConfiguration: REGIONAL - -Resources: - ${resourceName}Function: - Type: AWS::Serverless::Function - Properties: - Handler: ${groupId}.StreamLambdaHandler::handleRequest - Runtime: java21 - CodeUri: . - MemorySize: 512 - Policies: AWSLambdaBasicExecutionRole - Timeout: 30 - Events: - ProxyResource: - Type: Api - Properties: - Path: /{proxy+} - Method: any - -Outputs: - ${resourceName}Api: - Description: URL for application - Value: !Sub 'https://${ServerlessRestApi}.execute-api.${${awsRegion}}.amazonaws.com/Prod/ping' - Export: - Name: ${resourceName}Api diff --git a/aws-serverless-springboot3-archetype/src/test/resources/projects/base/archetype.properties b/aws-serverless-springboot3-archetype/src/test/resources/projects/base/archetype.properties deleted file mode 100644 index 7df3bf6e1..000000000 --- a/aws-serverless-springboot3-archetype/src/test/resources/projects/base/archetype.properties +++ /dev/null @@ -1,3 +0,0 @@ -groupId=test.service -artifactId=springboot-archetype-test -version=1.0-SNAPSHOT diff --git a/aws-serverless-springboot3-archetype/src/test/resources/projects/base/goal.txt b/aws-serverless-springboot3-archetype/src/test/resources/projects/base/goal.txt deleted file mode 100644 index 597acc768..000000000 --- a/aws-serverless-springboot3-archetype/src/test/resources/projects/base/goal.txt +++ /dev/null @@ -1 +0,0 @@ -package \ No newline at end of file diff --git a/samples/springboot3/alt-pet-store/README.md b/samples/springboot3/alt-pet-store/README.md deleted file mode 100644 index b91cd42f6..000000000 --- a/samples/springboot3/alt-pet-store/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Serverless Spring Boot 3 example -A basic pet store written with the [Spring Boot 3 framework](https://projects.spring.io/spring-boot/). Unlike older examples, this example is relying on the new -`SpringDelegatingLambdaContainerHandler`, which you simply need to identify as a _handler_ of the Lambda function. The main configuration class identified as `MAIN_CLASS` -environment variable or `Start-Class` or `Main-Class` entry in Manifest file. See provided `template.yml` file for reference. - - -The application can be deployed in an AWS account using the [Serverless Application Model](https://github.com/awslabs/serverless-application-model). The `template.yml` file in the root folder contains the application definition. - -## Pre-requisites -* [AWS CLI](https://aws.amazon.com/cli/) -* [SAM CLI](https://github.com/awslabs/aws-sam-cli) -* [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/) - -## Deployment -In a shell, navigate to the sample's folder and use the SAM CLI to build a deployable package -``` -$ sam build -``` - -This command compiles the application and prepares a deployment package in the `.aws-sam` sub-directory. - -To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen - -``` -$ sam deploy --guided -``` - -Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new application URL. You can use `curl` or a web browser to make a call to the URL - -``` -... ---------------------------------------------------------------------------------------------------------- -OutputKey-Description OutputValue ---------------------------------------------------------------------------------------------------------- -PetStoreApi - URL for application https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets ---------------------------------------------------------------------------------------------------------- - -$ curl https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets -``` - -You can also try a complex request passing both path and request parameters to complex endpoint such as this: - - -``` -@RequestMapping(path = "/foo/{gender}/bar/{age}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) -public String complexRequest(@RequestBody String body, - @PathVariable("gender") String gender, - @PathVariable("age") String age, - @RequestParam("name") String name -) -``` -For example. - -``` -curl -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST https://zuhd709386.execute-api.us-east-2.amazonaws.com/foo/male/bar/25?name=Ricky -``` diff --git a/samples/springboot3/alt-pet-store/build.gradle b/samples/springboot3/alt-pet-store/build.gradle deleted file mode 100644 index d2c99b907..000000000 --- a/samples/springboot3/alt-pet-store/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'java' - -repositories { - mavenLocal() - mavenCentral() - maven {url "https://repo.spring.io/milestone"} - maven {url "https://repo.spring.io/snapshot"} -} - -dependencies { - implementation ( - implementation('org.springframework.boot:spring-boot-starter-web:3.5.7') { - exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' - }, - 'com.amazonaws.serverless:aws-serverless-java-container-springboot3:[2.0-SNAPSHOT,)', - ) -} - -task buildZip(type: Zip) { - from compileJava - from processResources - into('lib') { - from(configurations.compileClasspath) { - exclude 'tomcat-embed-*' - } - } -} - -build.dependsOn buildZip diff --git a/samples/springboot3/alt-pet-store/pom.xml b/samples/springboot3/alt-pet-store/pom.xml deleted file mode 100644 index 64cbb083c..000000000 --- a/samples/springboot3/alt-pet-store/pom.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - 4.0.0 - - com.amazonaws.serverless.sample - petstore-springboot3-example - 2.0-SNAPSHOT - Spring Boot example for the aws-serverless-java-container library - Simple pet store written with the Spring framework and Spring Boot - https://aws.amazon.com/lambda/ - - - org.springframework.boot - spring-boot-starter-parent - 3.5.0 - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - 17 - - - - - org.springframework.boot - spring-boot-starter - - - - com.amazonaws.serverless - aws-serverless-java-container-springboot3 - [2.2.0-SNAPSHOT,),[2.1.1,) - - - - - - shaded-jar - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - false - - - - package - - shade - - - - - org.apache.tomcat.embed:* - - - - - - - - - - - assembly-zip - - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - - default-jar - none - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.4 - - true - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.8.1 - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/lib - runtime - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.7.1 - - - zip-assembly - package - - single - - - ${project.artifactId}-${project.version} - - src${file.separator}assembly${file.separator}bin.xml - - false - - - - - - - - - - - diff --git a/samples/springboot3/alt-pet-store/src/assembly/bin.xml b/samples/springboot3/alt-pet-store/src/assembly/bin.xml deleted file mode 100644 index 1e085057d..000000000 --- a/samples/springboot3/alt-pet-store/src/assembly/bin.xml +++ /dev/null @@ -1,27 +0,0 @@ - - lambda-package - - zip - - false - - - - ${project.build.directory}${file.separator}lib - lib - - tomcat-embed* - - - - - ${project.build.directory}${file.separator}classes - - ** - - ${file.separator} - - - \ No newline at end of file diff --git a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java b/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java deleted file mode 100644 index 428d67267..000000000 --- a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.web.servlet.HandlerAdapter; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -import com.amazonaws.serverless.sample.springboot3.controller.PetsController; -import com.amazonaws.serverless.sample.springboot3.filter.CognitoIdentityFilter; - -import jakarta.servlet.Filter; - - -@SpringBootApplication -@Import({ PetsController.class }) -public class Application { - - // silence console logging - @Value("${logging.level.root:OFF}") - String message = ""; - - /* - * Create required HandlerMapping, to avoid several default HandlerMapping instances being created - */ - @Bean - public HandlerMapping handlerMapping() { - return new RequestMappingHandlerMapping(); - } - - /* - * Create required HandlerAdapter, to avoid several default HandlerAdapter instances being created - */ - @Bean - public HandlerAdapter handlerAdapter() { - return new RequestMappingHandlerAdapter(); - } - - @Bean("CognitoIdentityFilter") - public Filter cognitoFilter() { - return new CognitoIdentityFilter(); - } - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} \ No newline at end of file diff --git a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java b/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java deleted file mode 100644 index 769db35f3..000000000 --- a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.sample.springboot3.controller; - - - -import com.amazonaws.serverless.sample.springboot3.model.Pet; -import com.amazonaws.serverless.sample.springboot3.model.PetData; - -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -import java.security.Principal; -import java.util.Optional; -import java.util.UUID; - - -@RestController -@EnableWebMvc -public class PetsController { - - @RequestMapping(path = "/pets", method = RequestMethod.POST) - public Pet createPet(@RequestBody Pet newPet) { - if (newPet.getName() == null || newPet.getBreed() == null) { - return null; - } - - Pet dbPet = newPet; - dbPet.setId(UUID.randomUUID().toString()); - return dbPet; - } - - @RequestMapping(path = "/pets", method = RequestMethod.GET) - public Pet[] listPets(@RequestParam("limit") Optional limit, Principal principal) { - int queryLimit = 10; - if (limit.isPresent()) { - queryLimit = limit.get(); - } - - Pet[] outputPets = new Pet[queryLimit]; - - for (int i = 0; i < queryLimit; i++) { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setName(PetData.getRandomName()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - outputPets[i] = newPet; - } - - return outputPets; - } - - @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET) - public Pet listPets() { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - newPet.setName(PetData.getRandomName()); - return newPet; - } - - @RequestMapping(path = "/foo/{gender}/bar/{age}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public String complexRequest(@RequestBody String body, - @PathVariable("gender") String gender, - @PathVariable("age") String age, - @RequestParam("name") String name - ) { - System.out.println("Body: " + body + " - " + gender + "/" + age + "/" + name); - return gender + "/" + age + "/" + name; - } - -} diff --git a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java b/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java deleted file mode 100644 index d6ccae765..000000000 --- a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3.filter; - - -import com.amazonaws.serverless.proxy.RequestReader; -import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; - -import java.io.IOException; - - -/** - * Simple Filter implementation that looks for a Cognito identity id in the API Gateway request context - * and stores the value in a request attribute. The filter is registered with aws-serverless-java-container - * in the onStartup method from the {@link com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler} class. - */ -public class CognitoIdentityFilter implements Filter { - public static final String COGNITO_IDENTITY_ATTRIBUTE = "com.amazonaws.serverless.cognitoId"; - - private static Logger log = LoggerFactory.getLogger(CognitoIdentityFilter.class); - - @Override - public void init(FilterConfig filterConfig) - throws ServletException { - // nothing to do in init - } - - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - Object apiGwContext = servletRequest.getAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY); - if (apiGwContext == null) { - log.warn("API Gateway context is null"); - filterChain.doFilter(servletRequest, servletResponse); - return; - } - if (!AwsProxyRequestContext.class.isAssignableFrom(apiGwContext.getClass())) { - log.warn("API Gateway context object is not of valid type"); - filterChain.doFilter(servletRequest, servletResponse); - } - - AwsProxyRequestContext ctx = (AwsProxyRequestContext)apiGwContext; - if (ctx.getIdentity() == null) { - log.warn("Identity context is null"); - filterChain.doFilter(servletRequest, servletResponse); - } - String cognitoIdentityId = ctx.getIdentity().getCognitoIdentityId(); - if (cognitoIdentityId == null || "".equals(cognitoIdentityId.trim())) { - log.warn("Cognito identity id in request is null"); - } - servletRequest.setAttribute(COGNITO_IDENTITY_ATTRIBUTE, cognitoIdentityId); - filterChain.doFilter(servletRequest, servletResponse); - } - - - @Override - public void destroy() { - // nothing to do in destroy - } -} diff --git a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java b/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java deleted file mode 100644 index 320f21582..000000000 --- a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.sample.springboot3.model; - -public class Error { - private String message; - - public Error(String errorMessage) { - message = errorMessage; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java b/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java deleted file mode 100644 index 4f0c4ba8e..000000000 --- a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.sample.springboot3.model; - -import java.util.Date; - - -public class Pet { - private String id; - private String breed; - private String name; - private Date dateOfBirth; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getBreed() { - return breed; - } - - public void setBreed(String breed) { - this.breed = breed; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } -} diff --git a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java b/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java deleted file mode 100644 index 68ea3c18b..000000000 --- a/samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.sample.springboot3.model; - - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - - -public class PetData { - private static List breeds = new ArrayList<>(); - static { - breeds.add("Afghan Hound"); - breeds.add("Beagle"); - breeds.add("Bernese Mountain Dog"); - breeds.add("Bloodhound"); - breeds.add("Dalmatian"); - breeds.add("Jack Russell Terrier"); - breeds.add("Norwegian Elkhound"); - } - - private static List names = new ArrayList<>(); - static { - names.add("Bailey"); - names.add("Bella"); - names.add("Max"); - names.add("Lucy"); - names.add("Charlie"); - names.add("Molly"); - names.add("Buddy"); - names.add("Daisy"); - names.add("Rocky"); - names.add("Maggie"); - names.add("Jake"); - names.add("Sophie"); - names.add("Jack"); - names.add("Sadie"); - names.add("Toby"); - names.add("Chloe"); - names.add("Cody"); - names.add("Bailey"); - names.add("Buster"); - names.add("Lola"); - names.add("Duke"); - names.add("Zoe"); - names.add("Cooper"); - names.add("Abby"); - names.add("Riley"); - names.add("Ginger"); - names.add("Harley"); - names.add("Roxy"); - names.add("Bear"); - names.add("Gracie"); - names.add("Tucker"); - names.add("Coco"); - names.add("Murphy"); - names.add("Sasha"); - names.add("Lucky"); - names.add("Lily"); - names.add("Oliver"); - names.add("Angel"); - names.add("Sam"); - names.add("Princess"); - names.add("Oscar"); - names.add("Emma"); - names.add("Teddy"); - names.add("Annie"); - names.add("Winston"); - names.add("Rosie"); - } - - public static List getBreeds() { - return breeds; - } - - public static List getNames() { - return names; - } - - public static String getRandomBreed() { - return breeds.get(ThreadLocalRandom.current().nextInt(0, breeds.size() - 1)); - } - - public static String getRandomName() { - return names.get(ThreadLocalRandom.current().nextInt(0, names.size() - 1)); - } - - public static Date getRandomDoB() { - GregorianCalendar gc = new GregorianCalendar(); - - int year = ThreadLocalRandom.current().nextInt( - Calendar.getInstance().get(Calendar.YEAR) - 15, - Calendar.getInstance().get(Calendar.YEAR) - ); - - gc.set(Calendar.YEAR, year); - - int dayOfYear = ThreadLocalRandom.current().nextInt(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR)); - - gc.set(Calendar.DAY_OF_YEAR, dayOfYear); - return gc.getTime(); - } -} diff --git a/samples/springboot3/alt-pet-store/src/main/resources/logback.xml b/samples/springboot3/alt-pet-store/src/main/resources/logback.xml deleted file mode 100644 index 81d891777..000000000 --- a/samples/springboot3/alt-pet-store/src/main/resources/logback.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/samples/springboot3/alt-pet-store/template.yml b/samples/springboot3/alt-pet-store/template.yml deleted file mode 100644 index c883f0850..000000000 --- a/samples/springboot3/alt-pet-store/template.yml +++ /dev/null @@ -1,41 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: Example Pet Store API written with spring-cloud-function web-proxy support - -Globals: - Api: - # API Gateway regional endpoints - EndpointConfiguration: REGIONAL - -Resources: - PetStoreFunction: - Type: AWS::Serverless::Function - Properties: -# AutoPublishAlias: bcn - FunctionName: pet-store-boot-3 - Handler: com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler::handleRequest - Runtime: java21 - SnapStart: - ApplyOn: PublishedVersions - CodeUri: . - MemorySize: 1024 - Policies: AWSLambdaBasicExecutionRole - Timeout: 30 - Environment: - Variables: - MAIN_CLASS: com.amazonaws.serverless.sample.springboot3.Application - Events: - HttpApiEvent: - Type: HttpApi - Properties: - TimeoutInMillis: 20000 - PayloadFormatVersion: '1.0' - -Outputs: - SpringPetStoreApi: - Description: URL for application - Value: !Sub 'https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/pets' - Export: - Name: SpringPetStoreApi - - diff --git a/samples/springboot3/graphql-pet-store/README.md b/samples/springboot3/graphql-pet-store/README.md deleted file mode 100644 index e5bfad120..000000000 --- a/samples/springboot3/graphql-pet-store/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Serverless Spring Boot 3 with GraphQL example -A basic pet store written with the [Spring Boot 3 framework](https://projects.spring.io/spring-boot/). Unlike older examples, this example uses the [Spring for GraphQl](https://docs.spring.io/spring-graphql/reference/) library. - - -The application can be deployed in an AWS account using the [Serverless Application Model](https://github.com/awslabs/serverless-application-model). The `template.yml` file in the root folder contains the application definition. - -## Pre-requisites -* [AWS CLI](https://aws.amazon.com/cli/) -* [SAM CLI](https://github.com/awslabs/aws-sam-cli) -* [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/) - -## Deployment -In a shell, navigate to the sample's folder and use the SAM CLI to build a deployable package -``` -$ sam build -``` - -This command compiles the application and prepares a deployment package in the `.aws-sam` sub-directory. - -To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen - -``` -$ sam deploy --guided -``` - -Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new application URL. You can use `curl` to make a call to the URL - -``` -... ---------------------------------------------------------------------------------------------------------- -OutputKey-Description OutputValue ---------------------------------------------------------------------------------------------------------- -PetStoreApi - URL for application https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/graphQl ---------------------------------------------------------------------------------------------------------- - -$ curl -X POST https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/graphQl -d '{"query":"query petDetails {\n petById(id: \"pet-1\") {\n id\n name\n breed\n owner {\n id\n firstName\n lastName\n }\n }\n}","operationName":"petDetails"}' -H "Content-Type: application/json" - -``` \ No newline at end of file diff --git a/samples/springboot3/graphql-pet-store/pom.xml b/samples/springboot3/graphql-pet-store/pom.xml deleted file mode 100644 index 23ac0bae6..000000000 --- a/samples/springboot3/graphql-pet-store/pom.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - 4.0.0 - - com.amazonaws.serverless.sample - serverless-springboot3-example - 2.0-SNAPSHOT - Spring Boot example for the aws-serverless-java-container library - Simple pet store written with the Spring framework and Spring Boot - https://aws.amazon.com/lambda/ - - - org.springframework.boot - spring-boot-starter-parent - 3.5.0 - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - 17 - - - - - org.springframework.boot - spring-boot-starter-graphql - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - org.springframework.graphql - spring-graphql-test - test - - - com.amazonaws.serverless - aws-serverless-java-container-springboot3 - [2.0.0-SNAPSHOT,),[2.0.0-M1,) - - - - - - shaded-jar - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - false - - - - package - - shade - - - - - org.apache.tomcat.embed:* - - - - - - - - - - - assembly-zip - - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - - default-jar - none - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.4 - - true - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.8.1 - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/lib - runtime - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.7.1 - - - zip-assembly - package - - single - - - ${project.artifactId}-${project.version} - - src${file.separator}assembly${file.separator}bin.xml - - false - - - - - - - - - - - diff --git a/samples/springboot3/graphql-pet-store/src/assembly/bin.xml b/samples/springboot3/graphql-pet-store/src/assembly/bin.xml deleted file mode 100644 index efc312c25..000000000 --- a/samples/springboot3/graphql-pet-store/src/assembly/bin.xml +++ /dev/null @@ -1,27 +0,0 @@ - - lambda-package - - zip - - false - - - - ${project.build.directory}${file.separator}lib - lib - - tomcat-embed* - - - - - ${project.build.directory}${file.separator}classes - - ** - - ${file.separator} - - - diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java deleted file mode 100644 index 9cf0ea610..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3; - -import com.amazonaws.serverless.sample.springboot3.controller.PetsController; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.web.servlet.HandlerAdapter; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - - -@SpringBootApplication -@Import({ PetsController.class }) -public class Application { - - // silence console logging - @Value("${logging.level.root:OFF}") - String message = ""; - - /* - * Create required HandlerMapping, to avoid several default HandlerMapping instances being created - */ - @Bean - public HandlerMapping handlerMapping() { - return new RequestMappingHandlerMapping(); - } - - /* - * Create required HandlerAdapter, to avoid several default HandlerAdapter instances being created - */ - @Bean - public HandlerAdapter handlerAdapter() { - return new RequestMappingHandlerAdapter(); - } - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java deleted file mode 100644 index a65c6f1ec..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3; - - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -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.SpringBootLambdaContainerHandler; -import com.amazonaws.serverless.sample.springboot3.filter.CognitoIdentityFilter; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; - -import jakarta.servlet.DispatcherType; -import jakarta.servlet.FilterRegistration; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.EnumSet; - - -public class StreamLambdaHandler implements RequestStreamHandler { - private static SpringBootLambdaContainerHandler handler; - static { - try { - handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class); - - // we use the onStartup method of the handler to register our custom filter - handler.onStartup(servletContext -> { - FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class); - registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*"); - }); - } catch (ContainerInitializationException e) { - // if we fail here. We re-throw the exception to force another cold start - e.printStackTrace(); - throw new RuntimeException("Could not initialize Spring Boot application", e); - } - } - - public StreamLambdaHandler() { - // we enable the timer for debugging. This SHOULD NOT be enabled in production. - Timer.enable(); - } - - @Override - public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) - throws IOException { - handler.proxyStream(inputStream, outputStream, context); - } -} diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java deleted file mode 100644 index 93eb999bd..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3.controller; - -import org.springframework.graphql.data.method.annotation.Argument; -import org.springframework.graphql.data.method.annotation.QueryMapping; -import org.springframework.graphql.data.method.annotation.SchemaMapping; -import org.springframework.stereotype.Controller; -import com.amazonaws.serverless.sample.springboot3.model.Owner; -import com.amazonaws.serverless.sample.springboot3.model.Pet; - -@Controller -public class PetsController { - @QueryMapping - public Pet petById(@Argument String id) { - return Pet.getById(id); - } - - @SchemaMapping - public Owner owner(Pet pet) { - return Owner.getById(pet.ownerId()); - } -} diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java deleted file mode 100644 index d6ccae765..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3.filter; - - -import com.amazonaws.serverless.proxy.RequestReader; -import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; - -import java.io.IOException; - - -/** - * Simple Filter implementation that looks for a Cognito identity id in the API Gateway request context - * and stores the value in a request attribute. The filter is registered with aws-serverless-java-container - * in the onStartup method from the {@link com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler} class. - */ -public class CognitoIdentityFilter implements Filter { - public static final String COGNITO_IDENTITY_ATTRIBUTE = "com.amazonaws.serverless.cognitoId"; - - private static Logger log = LoggerFactory.getLogger(CognitoIdentityFilter.class); - - @Override - public void init(FilterConfig filterConfig) - throws ServletException { - // nothing to do in init - } - - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - Object apiGwContext = servletRequest.getAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY); - if (apiGwContext == null) { - log.warn("API Gateway context is null"); - filterChain.doFilter(servletRequest, servletResponse); - return; - } - if (!AwsProxyRequestContext.class.isAssignableFrom(apiGwContext.getClass())) { - log.warn("API Gateway context object is not of valid type"); - filterChain.doFilter(servletRequest, servletResponse); - } - - AwsProxyRequestContext ctx = (AwsProxyRequestContext)apiGwContext; - if (ctx.getIdentity() == null) { - log.warn("Identity context is null"); - filterChain.doFilter(servletRequest, servletResponse); - } - String cognitoIdentityId = ctx.getIdentity().getCognitoIdentityId(); - if (cognitoIdentityId == null || "".equals(cognitoIdentityId.trim())) { - log.warn("Cognito identity id in request is null"); - } - servletRequest.setAttribute(COGNITO_IDENTITY_ATTRIBUTE, cognitoIdentityId); - filterChain.doFilter(servletRequest, servletResponse); - } - - - @Override - public void destroy() { - // nothing to do in destroy - } -} diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Owner.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Owner.java deleted file mode 100644 index f048e6906..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Owner.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3.model; - -import java.util.Arrays; -import java.util.List; - -public record Owner (String id, String firstName, String lastName) { - - private static List owners = Arrays.asList( - new Owner("owner-1", "Joshua", "Bloch"), - new Owner("owner-2", "Douglas", "Adams"), - new Owner("owner-3", "Bill", "Bryson") - ); - - public static Owner getById(String id) { - return owners.stream() - .filter(owner -> owner.id().equals(id)) - .findFirst() - .orElse(null); - } -} diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java deleted file mode 100644 index f97b973d0..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3.model; - -import java.util.Arrays; -import java.util.List; - -public record Pet (String id, String name, String breed, String ownerId) { - - private static List pets = Arrays.asList( - new Pet("pet-1", "Alpha", "Bulldog", "owner-1"), - new Pet("pet-2", "Max", "German Shepherd", "owner-2"), - new Pet("pet-3", "Rockie", "Golden Retriever", "owner-3") - ); - - public static Pet getById(String id) { - return pets.stream() - .filter(pet -> pet.id().equals(id)) - .findFirst() - .orElse(null); - } -} diff --git a/samples/springboot3/graphql-pet-store/src/main/resources/graphql/schema.graphqls b/samples/springboot3/graphql-pet-store/src/main/resources/graphql/schema.graphqls deleted file mode 100644 index 293cdcc40..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/resources/graphql/schema.graphqls +++ /dev/null @@ -1,16 +0,0 @@ -type Query { - petById(id: ID): Pet -} - -type Pet { - id: ID - name: String - breed: String - owner: Owner -} - -type Owner { - id: ID - firstName: String - lastName: String -} diff --git a/samples/springboot3/graphql-pet-store/src/main/resources/logback.xml b/samples/springboot3/graphql-pet-store/src/main/resources/logback.xml deleted file mode 100644 index 8ff988992..000000000 --- a/samples/springboot3/graphql-pet-store/src/main/resources/logback.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/samples/springboot3/graphql-pet-store/template.yml b/samples/springboot3/graphql-pet-store/template.yml deleted file mode 100644 index ce5dcc6b1..000000000 --- a/samples/springboot3/graphql-pet-store/template.yml +++ /dev/null @@ -1,32 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: Example Pet Store API written with SpringBoot3, Spring for GraphQl and the aws-serverless-java-container library - -Globals: - Api: - # API Gateway regional endpoints - EndpointConfiguration: REGIONAL - -Resources: - PetStoreFunction: - Type: AWS::Serverless::Function - Properties: - Handler: com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler::handleRequest - Runtime: java21 - CodeUri: . - MemorySize: 1024 - Policies: AWSLambdaBasicExecutionRole - Timeout: 60 - Events: - HttpApiEvent: - Type: HttpApi - Properties: - TimeoutInMillis: 20000 - PayloadFormatVersion: '1.0' - -Outputs: - SpringBootPetStoreApi: - Description: URL for application - Value: !Sub 'https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/graphql' - Export: - Name: SpringBootPetStoreApi diff --git a/samples/springboot3/pet-store-native/.gitignore b/samples/springboot3/pet-store-native/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/samples/springboot3/pet-store-native/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/samples/springboot3/pet-store-native/.mvn/wrapper/maven-wrapper.jar b/samples/springboot3/pet-store-native/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index cb28b0e37..000000000 Binary files a/samples/springboot3/pet-store-native/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/samples/springboot3/pet-store-native/.mvn/wrapper/maven-wrapper.properties b/samples/springboot3/pet-store-native/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 7d02699af..000000000 --- a/samples/springboot3/pet-store-native/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License 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. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/samples/springboot3/pet-store-native/Dockerfile b/samples/springboot3/pet-store-native/Dockerfile deleted file mode 100644 index 7d5833bfe..000000000 --- a/samples/springboot3/pet-store-native/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM public.ecr.aws/amazonlinux/amazonlinux:2023 - -RUN yum -y update \ - && yum install -y unzip tar gzip bzip2-devel ed gcc gcc-c++ gcc-gfortran \ - less libcurl-devel openssl openssl-devel readline-devel xz-devel \ - zlib-devel glibc-static zlib-static \ - && rm -rf /var/cache/yum - -# Graal VM -ENV GRAAL_VERSION 21.0.2 -ENV ARCHITECTURE aarch64 -ENV GRAAL_FILENAME graalvm-community-jdk-${GRAAL_VERSION}_linux-${ARCHITECTURE}_bin.tar.gz -RUN curl -4 -L https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${GRAAL_VERSION}/${GRAAL_FILENAME} | tar -xvz -RUN mv graalvm-community-openjdk-${GRAAL_VERSION}* /usr/lib/graalvm -ENV JAVA_HOME /usr/lib/graalvm - -# Maven -ENV MVN_VERSION 3.9.9 -ENV MVN_FOLDERNAME apache-maven-${MVN_VERSION} -ENV MVN_FILENAME apache-maven-${MVN_VERSION}-bin.tar.gz -RUN curl -4 -L https://archive.apache.org/dist/maven/maven-3/${MVN_VERSION}/binaries/${MVN_FILENAME} | tar -xvz -RUN mv $MVN_FOLDERNAME /usr/lib/maven -RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn - -# Gradle -ENV GRADLE_VERSION 7.4.1 -ENV GRADLE_FOLDERNAME gradle-${GRADLE_VERSION} -ENV GRADLE_FILENAME gradle-${GRADLE_VERSION}-bin.zip -RUN curl -LO https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -RUN unzip gradle-${GRADLE_VERSION}-bin.zip -RUN mv $GRADLE_FOLDERNAME /usr/lib/gradle -RUN ln -s /usr/lib/gradle/bin/gradle /usr/bin/gradle - -VOLUME /project -WORKDIR /project - -WORKDIR /pet-store-native diff --git a/samples/springboot3/pet-store-native/README.md b/samples/springboot3/pet-store-native/README.md deleted file mode 100644 index 571d56198..000000000 --- a/samples/springboot3/pet-store-native/README.md +++ /dev/null @@ -1,38 +0,0 @@ -In this sample, you'll build a native GraalVM image for running web workloads in AWS Lambda. - - -## To build the sample - -You first need to build the function, then you will deploy it to AWS Lambda. - -Please note that the sample is for `x86` architectures. In case you want to build and run it on ARM, e.g. Apple Mac M1, M2, ... -you must change the according line in the `Dockerfile` to `ENV ARCHITECTURE aarch64`. -In addition, uncomment the `arm64` Architectures section in `template.yml`. - -### Step 1 - Build the native image - -Before starting the build, you must clone or download the code in **pet-store-native**. - -1. Change into the project directory: `samples/springboot3/pet-store-native` -2. Run the following to build a Docker container image which will include all the necessary dependencies to build the application - ``` - docker build -t al2023-graalvm21:native-web . - ``` -3. Build the application within the previously created build image - ``` - docker run -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 al2023-graalvm21:native-web ./mvnw clean -Pnative package -DskipTests - ``` -4. After the build finishes, you need to deploy the function: - ``` - sam deploy --guided - ``` - -This will deploy your application and will attach an AWS API Gateway -Once the deployment is finished you should see the following: -``` -Key ServerlessWebNativeApi -Description URL for application -Value https://xxxxxxxx.execute-api.us-east-2.amazonaws.com/pets -``` - -You can now simply execute GET on this URL and see the listing fo all pets. diff --git a/samples/springboot3/pet-store-native/mvnw b/samples/springboot3/pet-store-native/mvnw deleted file mode 100755 index 8d937f4c1..000000000 --- a/samples/springboot3/pet-store-native/mvnw +++ /dev/null @@ -1,308 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.2.0 -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "$(uname)" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME - else - JAVA_HOME="/Library/Java/Home"; export JAVA_HOME - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=$(java-config --jre-home) - fi -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --unix "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --unix "$CLASSPATH") -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && - JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="$(which javac)" - if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=$(which readlink) - if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then - if $darwin ; then - javaHome="$(dirname "\"$javaExecutable\"")" - javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" - else - javaExecutable="$(readlink -f "\"$javaExecutable\"")" - fi - javaHome="$(dirname "\"$javaExecutable\"")" - javaHome=$(expr "$javaHome" : '\(.*\)/bin') - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=$(cd "$wdir/.." || exit 1; pwd) - fi - # end of workaround - done - printf '%s' "$(cd "$basedir" || exit 1; pwd)" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - # Remove \r in case we run on Windows within Git Bash - # and check out the repository with auto CRLF management - # enabled. Otherwise, we may read lines that are delimited with - # \r\n and produce $'-Xarg\r' rather than -Xarg due to word - # splitting rules. - tr -s '\r\n' ' ' < "$1" - fi -} - -log() { - if [ "$MVNW_VERBOSE" = true ]; then - printf '%s\n' "$1" - fi -} - -BASE_DIR=$(find_maven_basedir "$(dirname "$0")") -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR -log "$MAVEN_PROJECTBASEDIR" - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" -if [ -r "$wrapperJarPath" ]; then - log "Found $wrapperJarPath" -else - log "Couldn't find $wrapperJarPath, downloading it ..." - - if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - fi - while IFS="=" read -r key value; do - # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) - safeValue=$(echo "$value" | tr -d '\r') - case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; - esac - done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" - log "Downloading from: $wrapperUrl" - - if $cygwin; then - wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") - fi - - if command -v wget > /dev/null; then - log "Found wget ... using wget" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - log "Found curl ... using curl" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - fi - else - log "Falling back to using Java to download" - javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaSource=$(cygpath --path --windows "$javaSource") - javaClass=$(cygpath --path --windows "$javaClass") - fi - if [ -e "$javaSource" ]; then - if [ ! -e "$javaClass" ]; then - log " - Compiling MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/javac" "$javaSource") - fi - if [ -e "$javaClass" ]; then - log " - Running MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -# If specified, validate the SHA-256 sum of the Maven wrapper jar file -wrapperSha256Sum="" -while IFS="=" read -r key value; do - case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; - esac -done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" -if [ -n "$wrapperSha256Sum" ]; then - wrapperSha256Result=false - if command -v sha256sum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then - wrapperSha256Result=true - fi - elif command -v shasum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then - wrapperSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." - echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." - exit 1 - fi - if [ $wrapperSha256Result = false ]; then - echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 - echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 - echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 - exit 1 - fi -fi - -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --windows "$CLASSPATH") - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -# shellcheck disable=SC2086 # safe args -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/samples/springboot3/pet-store-native/mvnw.cmd b/samples/springboot3/pet-store-native/mvnw.cmd deleted file mode 100644 index f80fbad3e..000000000 --- a/samples/springboot3/pet-store-native/mvnw.cmd +++ /dev/null @@ -1,205 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/samples/springboot3/pet-store-native/pom.xml b/samples/springboot3/pet-store-native/pom.xml deleted file mode 100644 index 960442014..000000000 --- a/samples/springboot3/pet-store-native/pom.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.4.5 - - - com.amazonaws.serverless.sample - pet-store-native - 0.0.1-SNAPSHOT - pet-store-native - Sample of AWS with Spring Native - - 17 - - - - org.springframework.boot - spring-boot-starter - - - com.amazonaws.serverless - aws-serverless-java-container-springboot3 - [2.0.0-SNAPSHOT,),[2.0.0-M1,) - - - - org.crac - crac - runtime - - - com.amazonaws - aws-lambda-java-events - 3.15.0 - - - com.amazonaws - aws-lambda-java-core - 1.2.3 - provided - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - native - - - - org.springframework.boot - spring-boot-maven-plugin - - -agentlib:native-image-agent=config-merge-dir=src/main/resources/META-INF/native-image/ --enable-preview - - - - - org.graalvm.buildtools - native-maven-plugin - - - --enable-url-protocols=http - -march=compatibility - - - - - - build - - package - - - test - - test - - test - - - - - maven-assembly-plugin - - - native-zip - package - - single - - false - - - - - src/assembly/native.xml - - - - - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - \ No newline at end of file diff --git a/samples/springboot3/pet-store-native/src/assembly/java.xml b/samples/springboot3/pet-store-native/src/assembly/java.xml deleted file mode 100644 index bd4961b58..000000000 --- a/samples/springboot3/pet-store-native/src/assembly/java.xml +++ /dev/null @@ -1,31 +0,0 @@ - - java-zip - - zip - - - - - target/classes - / - - - src/shell/java - / - true - 0775 - - bootstrap - - - - - - /lib - false - runtime - - - \ No newline at end of file diff --git a/samples/springboot3/pet-store-native/src/assembly/native.xml b/samples/springboot3/pet-store-native/src/assembly/native.xml deleted file mode 100644 index 9bd97a5b7..000000000 --- a/samples/springboot3/pet-store-native/src/assembly/native.xml +++ /dev/null @@ -1,29 +0,0 @@ - - native-zip - - zip - - - - - src/shell/native - / - true - 0775 - - bootstrap - - - - target - / - true - 0775 - - pet-store-native - - - - \ No newline at end of file diff --git a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/DemoApplication.java b/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/DemoApplication.java deleted file mode 100644 index bf53a01f8..000000000 --- a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/DemoApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DemoApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(DemoApplication.class, args); - } -} diff --git a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/HelloController.java b/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/HelloController.java deleted file mode 100644 index 2c3fcfb01..000000000 --- a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/HelloController.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class HelloController { - - public HelloController() { - System.out.println("Creating controller"); - } - - @GetMapping("/hello") - public String something(){ - return "Hello World"; - } -} diff --git a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java b/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java deleted file mode 100644 index 849286fec..000000000 --- a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.sample.springboot3.controller; - - - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -import com.amazonaws.serverless.sample.springboot3.model.Pet; -import com.amazonaws.serverless.sample.springboot3.model.PetData; - -import java.security.Principal; -import java.util.Optional; -import java.util.UUID; - - -@RestController -@EnableWebMvc -public class PetsController { - @PostMapping(path = "/pets") - public Pet createPet(@RequestBody Pet newPet) { - System.out.println("==> Creating Pet: " + newPet); - if (newPet.getName() == null || newPet.getBreed() == null) { - return null; - } - - Pet dbPet = newPet; - dbPet.setId(UUID.randomUUID().toString()); - return dbPet; - } - - @GetMapping(path = "/pets") - public Pet[] listPets(@RequestParam("limit") Optional limit, Principal principal) { - System.out.println("==> Listing Pets"); - int queryLimit = 10; - if (limit.isPresent()) { - queryLimit = limit.get(); - } - - Pet[] outputPets = new Pet[queryLimit]; - - for (int i = 0; i < queryLimit; i++) { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setName(PetData.getRandomName()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - outputPets[i] = newPet; - } - - return outputPets; - } - - @GetMapping(path = "/pets/{petId}") - public Pet listPets() { - System.out.println("==> Listing Pets"); - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - newPet.setName(PetData.getRandomName()); - return newPet; - } - -} diff --git a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java b/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java deleted file mode 100644 index d6ccae765..000000000 --- a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3.filter; - - -import com.amazonaws.serverless.proxy.RequestReader; -import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; - -import java.io.IOException; - - -/** - * Simple Filter implementation that looks for a Cognito identity id in the API Gateway request context - * and stores the value in a request attribute. The filter is registered with aws-serverless-java-container - * in the onStartup method from the {@link com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler} class. - */ -public class CognitoIdentityFilter implements Filter { - public static final String COGNITO_IDENTITY_ATTRIBUTE = "com.amazonaws.serverless.cognitoId"; - - private static Logger log = LoggerFactory.getLogger(CognitoIdentityFilter.class); - - @Override - public void init(FilterConfig filterConfig) - throws ServletException { - // nothing to do in init - } - - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - Object apiGwContext = servletRequest.getAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY); - if (apiGwContext == null) { - log.warn("API Gateway context is null"); - filterChain.doFilter(servletRequest, servletResponse); - return; - } - if (!AwsProxyRequestContext.class.isAssignableFrom(apiGwContext.getClass())) { - log.warn("API Gateway context object is not of valid type"); - filterChain.doFilter(servletRequest, servletResponse); - } - - AwsProxyRequestContext ctx = (AwsProxyRequestContext)apiGwContext; - if (ctx.getIdentity() == null) { - log.warn("Identity context is null"); - filterChain.doFilter(servletRequest, servletResponse); - } - String cognitoIdentityId = ctx.getIdentity().getCognitoIdentityId(); - if (cognitoIdentityId == null || "".equals(cognitoIdentityId.trim())) { - log.warn("Cognito identity id in request is null"); - } - servletRequest.setAttribute(COGNITO_IDENTITY_ATTRIBUTE, cognitoIdentityId); - filterChain.doFilter(servletRequest, servletResponse); - } - - - @Override - public void destroy() { - // nothing to do in destroy - } -} diff --git a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java b/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java deleted file mode 100644 index 320f21582..000000000 --- a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.sample.springboot3.model; - -public class Error { - private String message; - - public Error(String errorMessage) { - message = errorMessage; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java b/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java deleted file mode 100644 index 4f0c4ba8e..000000000 --- a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.sample.springboot3.model; - -import java.util.Date; - - -public class Pet { - private String id; - private String breed; - private String name; - private Date dateOfBirth; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getBreed() { - return breed; - } - - public void setBreed(String breed) { - this.breed = breed; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } -} diff --git a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java b/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java deleted file mode 100644 index 68ea3c18b..000000000 --- a/samples/springboot3/pet-store-native/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.sample.springboot3.model; - - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - - -public class PetData { - private static List breeds = new ArrayList<>(); - static { - breeds.add("Afghan Hound"); - breeds.add("Beagle"); - breeds.add("Bernese Mountain Dog"); - breeds.add("Bloodhound"); - breeds.add("Dalmatian"); - breeds.add("Jack Russell Terrier"); - breeds.add("Norwegian Elkhound"); - } - - private static List names = new ArrayList<>(); - static { - names.add("Bailey"); - names.add("Bella"); - names.add("Max"); - names.add("Lucy"); - names.add("Charlie"); - names.add("Molly"); - names.add("Buddy"); - names.add("Daisy"); - names.add("Rocky"); - names.add("Maggie"); - names.add("Jake"); - names.add("Sophie"); - names.add("Jack"); - names.add("Sadie"); - names.add("Toby"); - names.add("Chloe"); - names.add("Cody"); - names.add("Bailey"); - names.add("Buster"); - names.add("Lola"); - names.add("Duke"); - names.add("Zoe"); - names.add("Cooper"); - names.add("Abby"); - names.add("Riley"); - names.add("Ginger"); - names.add("Harley"); - names.add("Roxy"); - names.add("Bear"); - names.add("Gracie"); - names.add("Tucker"); - names.add("Coco"); - names.add("Murphy"); - names.add("Sasha"); - names.add("Lucky"); - names.add("Lily"); - names.add("Oliver"); - names.add("Angel"); - names.add("Sam"); - names.add("Princess"); - names.add("Oscar"); - names.add("Emma"); - names.add("Teddy"); - names.add("Annie"); - names.add("Winston"); - names.add("Rosie"); - } - - public static List getBreeds() { - return breeds; - } - - public static List getNames() { - return names; - } - - public static String getRandomBreed() { - return breeds.get(ThreadLocalRandom.current().nextInt(0, breeds.size() - 1)); - } - - public static String getRandomName() { - return names.get(ThreadLocalRandom.current().nextInt(0, names.size() - 1)); - } - - public static Date getRandomDoB() { - GregorianCalendar gc = new GregorianCalendar(); - - int year = ThreadLocalRandom.current().nextInt( - Calendar.getInstance().get(Calendar.YEAR) - 15, - Calendar.getInstance().get(Calendar.YEAR) - ); - - gc.set(Calendar.YEAR, year); - - int dayOfYear = ThreadLocalRandom.current().nextInt(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR)); - - gc.set(Calendar.DAY_OF_YEAR, dayOfYear); - return gc.getTime(); - } -} diff --git a/samples/springboot3/pet-store-native/src/main/resources/META-INF/.gitignore b/samples/springboot3/pet-store-native/src/main/resources/META-INF/.gitignore deleted file mode 100644 index 0726bbaa2..000000000 --- a/samples/springboot3/pet-store-native/src/main/resources/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/native-image/ diff --git a/samples/springboot3/pet-store-native/src/main/resources/application.properties b/samples/springboot3/pet-store-native/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/samples/springboot3/pet-store-native/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/samples/springboot3/pet-store-native/src/shell/java/bootstrap b/samples/springboot3/pet-store-native/src/shell/java/bootstrap deleted file mode 100644 index 4586728a7..000000000 --- a/samples/springboot3/pet-store-native/src/shell/java/bootstrap +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -cd ${LAMBDA_TASK_ROOT:-.} - -java -Dspring.main.web-application-type=none -Dlogging.level.org.springframework=DEBUG \ - -noverify -XX:TieredStopAtLevel=1 -Xss256K -XX:MaxMetaspaceSize=128M \ - -cp .:`echo lib/*.jar | tr ' ' :` com.amazonaws.serverless.sample.springboot3.DemoApplication \ No newline at end of file diff --git a/samples/springboot3/pet-store-native/src/shell/native/bootstrap b/samples/springboot3/pet-store-native/src/shell/native/bootstrap deleted file mode 100644 index 0156b090b..000000000 --- a/samples/springboot3/pet-store-native/src/shell/native/bootstrap +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -cd ${LAMBDA_TASK_ROOT:-.} - -./pet-store-native -Dlogging.level.org.springframework=DEBUG -Dlogging.level.com.amazonaws.serverless.proxy.spring=DEBUG diff --git a/samples/springboot3/pet-store-native/template.yaml b/samples/springboot3/pet-store-native/template.yaml deleted file mode 100644 index dc05e1be7..000000000 --- a/samples/springboot3/pet-store-native/template.yaml +++ /dev/null @@ -1,34 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: Serverless Java Container GraalVM -Resources: - ServerlessWebNativeFunction: - Type: AWS::Serverless::Function - Properties: - MemorySize: 512 - FunctionName: pet-store-native - Timeout: 15 - CodeUri: ./target/pet-store-native-0.0.1-SNAPSHOT-native-zip.zip - Handler: NOP - Runtime: provided.al2023 -# If you want to build for ARM64 uncomment the following lines -# Architectures: -# - arm64 - Events: - HttpApiEvent: - Type: HttpApi - Properties: - TimeoutInMillis: 20000 - PayloadFormatVersion: '1.0' - -Globals: - Api: - # API Gateway regional endpoints - EndpointConfiguration: REGIONAL -Outputs: - ServerlessWebNativeApi: - Description: URL for application - Value: !Sub 'https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/pets' - Export: - Name: ServerlessWebNativeApi - \ No newline at end of file diff --git a/samples/springboot3/pet-store/README.md b/samples/springboot3/pet-store/README.md deleted file mode 100644 index fb3fab3b0..000000000 --- a/samples/springboot3/pet-store/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Serverless Spring Boot 3 example -A basic pet store written with the [Spring Boot 3 framework](https://projects.spring.io/spring-boot/). The `StreamLambdaHandler` object is the main entry point for Lambda. - -The application can be deployed in an AWS account using the [Serverless Application Model](https://github.com/awslabs/serverless-application-model). The `template.yml` file in the root folder contains the application definition. - -## Pre-requisites -* [AWS CLI](https://aws.amazon.com/cli/) -* [SAM CLI](https://github.com/awslabs/aws-sam-cli) -* [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/) - -## Deployment -In a shell, navigate to the sample's folder and use the SAM CLI to build a deployable package -``` -$ sam build -``` - -This command compiles the application and prepares a deployment package in the `.aws-sam` sub-directory. - -To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen - -``` -$ sam deploy --guided -``` - -Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new application URL. You can use `curl` or a web browser to make a call to the URL - -``` -... ---------------------------------------------------------------------------------------------------------- -OutputKey-Description OutputValue ---------------------------------------------------------------------------------------------------------- -PetStoreApi - URL for application https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets ---------------------------------------------------------------------------------------------------------- - -$ curl https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets -``` \ No newline at end of file diff --git a/samples/springboot3/pet-store/build.gradle b/samples/springboot3/pet-store/build.gradle deleted file mode 100644 index 653135db0..000000000 --- a/samples/springboot3/pet-store/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'java' - -repositories { - mavenLocal() - mavenCentral() - maven {url "https://repo.spring.io/milestone"} - maven {url "https://repo.spring.io/snapshot"} -} - -dependencies { - implementation ( - implementation('org.springframework.boot:spring-boot-starter-web:3.4.5') { - exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' - }, - 'com.amazonaws.serverless:aws-serverless-java-container-springboot3:[2.0-SNAPSHOT,)', - ) -} - -task buildZip(type: Zip) { - from compileJava - from processResources - into('lib') { - from(configurations.compileClasspath) { - exclude 'tomcat-embed-*' - } - } -} - -build.dependsOn buildZip diff --git a/samples/springboot3/pet-store/pom.xml b/samples/springboot3/pet-store/pom.xml deleted file mode 100644 index 4126ead75..000000000 --- a/samples/springboot3/pet-store/pom.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - 4.0.0 - - com.amazonaws.serverless.sample - serverless-springboot3-example - 2.0-SNAPSHOT - Spring Boot example for the aws-serverless-java-container library - Simple pet store written with the Spring framework and Spring Boot - https://aws.amazon.com/lambda/ - - - org.springframework.boot - spring-boot-starter-parent - 3.5.0 - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - 17 - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - - com.amazonaws.serverless - aws-serverless-java-container-springboot3 - [2.0.0-SNAPSHOT,),[2.0.0-M1,) - - - - - - shaded-jar - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - false - - - - package - - shade - - - - - org.apache.tomcat.embed:* - - - - - - - - - - - assembly-zip - - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - - default-jar - none - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.4 - - true - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.8.1 - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/lib - runtime - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.7.1 - - - zip-assembly - package - - single - - - ${project.artifactId}-${project.version} - - src${file.separator}assembly${file.separator}bin.xml - - false - - - - - - - - - - - diff --git a/samples/springboot3/pet-store/src/assembly/bin.xml b/samples/springboot3/pet-store/src/assembly/bin.xml deleted file mode 100644 index 1e085057d..000000000 --- a/samples/springboot3/pet-store/src/assembly/bin.xml +++ /dev/null @@ -1,27 +0,0 @@ - - lambda-package - - zip - - false - - - - ${project.build.directory}${file.separator}lib - lib - - tomcat-embed* - - - - - ${project.build.directory}${file.separator}classes - - ** - - ${file.separator} - - - \ No newline at end of file diff --git a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java b/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java deleted file mode 100644 index c576521f1..000000000 --- a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3; - -import com.amazonaws.serverless.sample.springboot3.controller.PetsController; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.web.servlet.HandlerAdapter; -import org.springframework.web.servlet.HandlerExceptionResolver; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - - -@SpringBootApplication -@Import({ PetsController.class }) -public class Application { - - // silence console logging - @Value("${logging.level.root:OFF}") - String message = ""; - - /* - * Create required HandlerMapping, to avoid several default HandlerMapping instances being created - */ - @Bean - public HandlerMapping handlerMapping() { - return new RequestMappingHandlerMapping(); - } - - /* - * Create required HandlerAdapter, to avoid several default HandlerAdapter instances being created - */ - @Bean - public HandlerAdapter handlerAdapter() { - return new RequestMappingHandlerAdapter(); - } - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} \ No newline at end of file diff --git a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java b/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java deleted file mode 100644 index a65c6f1ec..000000000 --- a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3; - - -import com.amazonaws.serverless.exceptions.ContainerInitializationException; -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.SpringBootLambdaContainerHandler; -import com.amazonaws.serverless.sample.springboot3.filter.CognitoIdentityFilter; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; - -import jakarta.servlet.DispatcherType; -import jakarta.servlet.FilterRegistration; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.EnumSet; - - -public class StreamLambdaHandler implements RequestStreamHandler { - private static SpringBootLambdaContainerHandler handler; - static { - try { - handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class); - - // we use the onStartup method of the handler to register our custom filter - handler.onStartup(servletContext -> { - FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class); - registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*"); - }); - } catch (ContainerInitializationException e) { - // if we fail here. We re-throw the exception to force another cold start - e.printStackTrace(); - throw new RuntimeException("Could not initialize Spring Boot application", e); - } - } - - public StreamLambdaHandler() { - // we enable the timer for debugging. This SHOULD NOT be enabled in production. - Timer.enable(); - } - - @Override - public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) - throws IOException { - handler.proxyStream(inputStream, outputStream, context); - } -} diff --git a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java b/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java deleted file mode 100644 index 680e629d3..000000000 --- a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.sample.springboot3.controller; - - - -import com.amazonaws.serverless.sample.springboot3.model.Pet; -import com.amazonaws.serverless.sample.springboot3.model.PetData; - -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -import java.security.Principal; -import java.util.Optional; -import java.util.UUID; - - -@RestController -@EnableWebMvc -public class PetsController { - @RequestMapping(path = "/pets", method = RequestMethod.POST) - public Pet createPet(@RequestBody Pet newPet) { - if (newPet.getName() == null || newPet.getBreed() == null) { - return null; - } - - Pet dbPet = newPet; - dbPet.setId(UUID.randomUUID().toString()); - return dbPet; - } - - @RequestMapping(path = "/pets", method = RequestMethod.GET) - public Pet[] listPets(@RequestParam("limit") Optional limit, Principal principal) { - int queryLimit = 10; - if (limit.isPresent()) { - queryLimit = limit.get(); - } - - Pet[] outputPets = new Pet[queryLimit]; - - for (int i = 0; i < queryLimit; i++) { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setName(PetData.getRandomName()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - outputPets[i] = newPet; - } - - return outputPets; - } - - @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET) - public Pet listPets() { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - newPet.setName(PetData.getRandomName()); - return newPet; - } - -} diff --git a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java b/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java deleted file mode 100644 index d6ccae765..000000000 --- a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.amazonaws.serverless.sample.springboot3.filter; - - -import com.amazonaws.serverless.proxy.RequestReader; -import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; - -import java.io.IOException; - - -/** - * Simple Filter implementation that looks for a Cognito identity id in the API Gateway request context - * and stores the value in a request attribute. The filter is registered with aws-serverless-java-container - * in the onStartup method from the {@link com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler} class. - */ -public class CognitoIdentityFilter implements Filter { - public static final String COGNITO_IDENTITY_ATTRIBUTE = "com.amazonaws.serverless.cognitoId"; - - private static Logger log = LoggerFactory.getLogger(CognitoIdentityFilter.class); - - @Override - public void init(FilterConfig filterConfig) - throws ServletException { - // nothing to do in init - } - - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - Object apiGwContext = servletRequest.getAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY); - if (apiGwContext == null) { - log.warn("API Gateway context is null"); - filterChain.doFilter(servletRequest, servletResponse); - return; - } - if (!AwsProxyRequestContext.class.isAssignableFrom(apiGwContext.getClass())) { - log.warn("API Gateway context object is not of valid type"); - filterChain.doFilter(servletRequest, servletResponse); - } - - AwsProxyRequestContext ctx = (AwsProxyRequestContext)apiGwContext; - if (ctx.getIdentity() == null) { - log.warn("Identity context is null"); - filterChain.doFilter(servletRequest, servletResponse); - } - String cognitoIdentityId = ctx.getIdentity().getCognitoIdentityId(); - if (cognitoIdentityId == null || "".equals(cognitoIdentityId.trim())) { - log.warn("Cognito identity id in request is null"); - } - servletRequest.setAttribute(COGNITO_IDENTITY_ATTRIBUTE, cognitoIdentityId); - filterChain.doFilter(servletRequest, servletResponse); - } - - - @Override - public void destroy() { - // nothing to do in destroy - } -} diff --git a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java b/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java deleted file mode 100644 index 320f21582..000000000 --- a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Error.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.sample.springboot3.model; - -public class Error { - private String message; - - public Error(String errorMessage) { - message = errorMessage; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java b/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java deleted file mode 100644 index 4f0c4ba8e..000000000 --- a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.sample.springboot3.model; - -import java.util.Date; - - -public class Pet { - private String id; - private String breed; - private String name; - private Date dateOfBirth; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getBreed() { - return breed; - } - - public void setBreed(String breed) { - this.breed = breed; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } -} diff --git a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java b/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java deleted file mode 100644 index 68ea3c18b..000000000 --- a/samples/springboot3/pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/PetData.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.sample.springboot3.model; - - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - - -public class PetData { - private static List breeds = new ArrayList<>(); - static { - breeds.add("Afghan Hound"); - breeds.add("Beagle"); - breeds.add("Bernese Mountain Dog"); - breeds.add("Bloodhound"); - breeds.add("Dalmatian"); - breeds.add("Jack Russell Terrier"); - breeds.add("Norwegian Elkhound"); - } - - private static List names = new ArrayList<>(); - static { - names.add("Bailey"); - names.add("Bella"); - names.add("Max"); - names.add("Lucy"); - names.add("Charlie"); - names.add("Molly"); - names.add("Buddy"); - names.add("Daisy"); - names.add("Rocky"); - names.add("Maggie"); - names.add("Jake"); - names.add("Sophie"); - names.add("Jack"); - names.add("Sadie"); - names.add("Toby"); - names.add("Chloe"); - names.add("Cody"); - names.add("Bailey"); - names.add("Buster"); - names.add("Lola"); - names.add("Duke"); - names.add("Zoe"); - names.add("Cooper"); - names.add("Abby"); - names.add("Riley"); - names.add("Ginger"); - names.add("Harley"); - names.add("Roxy"); - names.add("Bear"); - names.add("Gracie"); - names.add("Tucker"); - names.add("Coco"); - names.add("Murphy"); - names.add("Sasha"); - names.add("Lucky"); - names.add("Lily"); - names.add("Oliver"); - names.add("Angel"); - names.add("Sam"); - names.add("Princess"); - names.add("Oscar"); - names.add("Emma"); - names.add("Teddy"); - names.add("Annie"); - names.add("Winston"); - names.add("Rosie"); - } - - public static List getBreeds() { - return breeds; - } - - public static List getNames() { - return names; - } - - public static String getRandomBreed() { - return breeds.get(ThreadLocalRandom.current().nextInt(0, breeds.size() - 1)); - } - - public static String getRandomName() { - return names.get(ThreadLocalRandom.current().nextInt(0, names.size() - 1)); - } - - public static Date getRandomDoB() { - GregorianCalendar gc = new GregorianCalendar(); - - int year = ThreadLocalRandom.current().nextInt( - Calendar.getInstance().get(Calendar.YEAR) - 15, - Calendar.getInstance().get(Calendar.YEAR) - ); - - gc.set(Calendar.YEAR, year); - - int dayOfYear = ThreadLocalRandom.current().nextInt(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR)); - - gc.set(Calendar.DAY_OF_YEAR, dayOfYear); - return gc.getTime(); - } -} diff --git a/samples/springboot3/pet-store/src/main/resources/logback.xml b/samples/springboot3/pet-store/src/main/resources/logback.xml deleted file mode 100644 index 14a3a84fa..000000000 --- a/samples/springboot3/pet-store/src/main/resources/logback.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/samples/springboot3/pet-store/template.yml b/samples/springboot3/pet-store/template.yml deleted file mode 100644 index a8474349b..000000000 --- a/samples/springboot3/pet-store/template.yml +++ /dev/null @@ -1,32 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: Example Pet Store API written with SpringBoot with the aws-serverless-java-container library - -Globals: - Api: - # API Gateway regional endpoints - EndpointConfiguration: REGIONAL - -Resources: - PetStoreFunction: - Type: AWS::Serverless::Function - Properties: - Handler: com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler::handleRequest - Runtime: java21 - CodeUri: . - MemorySize: 1512 - Policies: AWSLambdaBasicExecutionRole - Timeout: 60 - Events: - HttpApiEvent: - Type: HttpApi - Properties: - TimeoutInMillis: 20000 - PayloadFormatVersion: '1.0' - -Outputs: - SpringBootPetStoreApi: - Description: URL for application - Value: !Sub 'https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/pets' - Export: - Name: SpringBootPetStoreApi