├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── baseline-arm └── CustomerService │ ├── .gitignore │ ├── Dockerfile │ ├── Dockerfile-local │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── amazon │ │ │ └── customerService │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── config │ │ │ └── AppConfig.java │ │ │ ├── controller │ │ │ └── CustomerController.java │ │ │ ├── exception │ │ │ └── CustomerNotFoundException.java │ │ │ ├── model │ │ │ ├── Customer.java │ │ │ └── metrics │ │ │ │ ├── ContainerMetric.java │ │ │ │ ├── MetricWrapper.java │ │ │ │ └── TaskMetric.java │ │ │ ├── repository │ │ │ └── CustomerRepository.java │ │ │ └── service │ │ │ ├── CustomerService.java │ │ │ └── EcsMetaDataService.java │ └── resources │ │ ├── application-local.properties │ │ └── application-prod.properties │ └── test │ ├── java │ └── com │ │ └── amazon │ │ └── customerService │ │ └── repository │ │ └── CustomerRepositoryTest.java │ └── resources │ ├── container_response.json │ └── task_response.json ├── baseline └── CustomerService │ ├── .gitignore │ ├── Dockerfile │ ├── Dockerfile-local │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── amazon │ │ │ └── customerService │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── config │ │ │ └── AppConfig.java │ │ │ ├── controller │ │ │ └── CustomerController.java │ │ │ ├── exception │ │ │ └── CustomerNotFoundException.java │ │ │ ├── model │ │ │ ├── Customer.java │ │ │ └── metrics │ │ │ │ ├── ContainerMetric.java │ │ │ │ ├── MetricWrapper.java │ │ │ │ └── TaskMetric.java │ │ │ ├── repository │ │ │ └── CustomerRepository.java │ │ │ └── service │ │ │ ├── CustomerService.java │ │ │ └── EcsMetaDataService.java │ └── resources │ │ ├── application-local.properties │ │ └── application-prod.properties │ └── test │ ├── java │ └── com │ │ └── amazon │ │ └── customerService │ │ └── repository │ │ └── CustomerRepositoryTest.java │ └── resources │ ├── container_response.json │ └── task_response.json ├── cdkapp ├── .gitignore ├── .npmignore ├── README.md ├── bin │ ├── cdkapp.d.ts │ ├── cdkapp.js │ └── cdkapp.ts ├── cdk.json ├── jest.config.js ├── lib │ ├── cdkapp-stack.d.ts │ ├── cdkapp-stack.js │ └── cdkapp-stack.ts ├── package-lock.json ├── package.json ├── test │ ├── cdkapp.test.d.ts │ ├── cdkapp.test.js │ └── cdkapp.test.ts └── tsconfig.json ├── custom-jre-java-optimizations-arm └── CustomerService │ ├── .gitignore │ ├── Dockerfile │ ├── Dockerfile-local │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── amazon │ │ │ └── customerService │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── config │ │ │ └── AppConfig.java │ │ │ ├── controller │ │ │ └── CustomerController.java │ │ │ ├── exception │ │ │ └── CustomerNotFoundException.java │ │ │ ├── model │ │ │ ├── Customer.java │ │ │ └── metrics │ │ │ │ ├── ContainerMetric.java │ │ │ │ ├── MetricWrapper.java │ │ │ │ └── TaskMetric.java │ │ │ ├── repository │ │ │ └── CustomerRepository.java │ │ │ └── service │ │ │ ├── CustomerService.java │ │ │ └── EcsMetaDataService.java │ └── resources │ │ ├── application-local.properties │ │ └── application-prod.properties │ └── test │ ├── java │ └── com │ │ └── amazon │ │ └── customerService │ │ └── repository │ │ └── CustomerRepositoryTest.java │ └── resources │ ├── container_response.json │ └── task_response.json ├── custom-jre-java-optimizations └── CustomerService │ ├── .gitignore │ ├── Dockerfile │ ├── Dockerfile-local │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── amazon │ │ │ └── customerService │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── config │ │ │ └── AppConfig.java │ │ │ ├── controller │ │ │ └── CustomerController.java │ │ │ ├── exception │ │ │ └── CustomerNotFoundException.java │ │ │ ├── model │ │ │ ├── Customer.java │ │ │ └── metrics │ │ │ │ ├── ContainerMetric.java │ │ │ │ ├── MetricWrapper.java │ │ │ │ └── TaskMetric.java │ │ │ ├── repository │ │ │ └── CustomerRepository.java │ │ │ └── service │ │ │ ├── CustomerService.java │ │ │ └── EcsMetaDataService.java │ └── resources │ │ ├── application-local.properties │ │ └── application-prod.properties │ └── test │ ├── java │ └── com │ │ └── amazon │ │ └── customerService │ │ └── repository │ │ └── CustomerRepositoryTest.java │ └── resources │ ├── container_response.json │ └── task_response.json ├── images ├── SpringBoot_example_architecture.png └── cloud9.png ├── spring-native-arm └── CustomerService │ ├── .gitignore │ ├── Dockerfile │ ├── Dockerfile-local │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── amazon │ │ │ └── customerService │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── config │ │ │ └── AppConfig.java │ │ │ ├── controller │ │ │ └── CustomerController.java │ │ │ ├── exception │ │ │ └── CustomerNotFoundException.java │ │ │ ├── model │ │ │ ├── Customer.java │ │ │ └── metrics │ │ │ │ ├── ContainerMetric.java │ │ │ │ ├── MetricWrapper.java │ │ │ │ └── TaskMetric.java │ │ │ ├── repository │ │ │ └── CustomerRepository.java │ │ │ └── service │ │ │ ├── CustomerService.java │ │ │ └── EcsMetaDataService.java │ └── resources │ │ ├── META-INF │ │ └── native-image │ │ │ ├── jni-config.json │ │ │ ├── predefined-classes-config.json │ │ │ ├── proxy-config.json │ │ │ ├── reflect-config.json │ │ │ ├── resource-config.json │ │ │ └── serialization-config.json │ │ ├── application-local.properties │ │ └── application-prod.properties │ └── test │ └── java │ └── com │ └── amazon │ └── customerService │ └── repository │ └── CustomerRepositoryTest.java ├── spring-native-distroless └── CustomerService │ ├── .gitignore │ ├── Dockerfile │ ├── Dockerfile-local │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── amazon │ │ │ └── customerService │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── config │ │ │ └── AppConfig.java │ │ │ ├── controller │ │ │ └── CustomerController.java │ │ │ ├── exception │ │ │ └── CustomerNotFoundException.java │ │ │ ├── model │ │ │ ├── Customer.java │ │ │ └── metrics │ │ │ │ ├── ContainerMetric.java │ │ │ │ ├── MetricWrapper.java │ │ │ │ └── TaskMetric.java │ │ │ ├── repository │ │ │ └── CustomerRepository.java │ │ │ └── service │ │ │ ├── CustomerService.java │ │ │ └── EcsMetaDataService.java │ └── resources │ │ ├── META-INF │ │ └── native-image │ │ │ ├── jni-config.json │ │ │ ├── predefined-classes-config.json │ │ │ ├── proxy-config.json │ │ │ ├── reflect-config.json │ │ │ ├── resource-config.json │ │ │ └── serialization-config.json │ │ ├── application-local.properties │ │ └── application-prod.properties │ └── test │ └── java │ └── com │ └── amazon │ └── customerService │ ├── repository │ └── CustomerRepositoryTest.java │ └── service │ └── EcsMetaDataServiceTest.java └── spring-native └── CustomerService ├── .gitignore ├── Dockerfile ├── Dockerfile-local ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── amazon │ │ └── customerService │ │ ├── CustomerServiceApplication.java │ │ ├── config │ │ └── AppConfig.java │ │ ├── controller │ │ └── CustomerController.java │ │ ├── exception │ │ └── CustomerNotFoundException.java │ │ ├── model │ │ ├── Customer.java │ │ └── metrics │ │ │ ├── ContainerMetric.java │ │ │ ├── MetricWrapper.java │ │ │ └── TaskMetric.java │ │ ├── repository │ │ └── CustomerRepository.java │ │ └── service │ │ ├── CustomerService.java │ │ └── EcsMetaDataService.java └── resources │ ├── META-INF │ └── native-image │ │ ├── jni-config.json │ │ ├── predefined-classes-config.json │ │ ├── proxy-config.json │ │ ├── reflect-config.json │ │ ├── resource-config.json │ │ └── serialization-config.json │ ├── application-local.properties │ └── application-prod.properties └── test └── java └── com └── amazon └── customerService └── repository └── CustomerRepositoryTest.java /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '30 23 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java', 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .project 3 | .classpath 4 | .settings/ 5 | 6 | # IntelliJ 7 | .idea 8 | *.ipr 9 | *.iml 10 | *.iws 11 | 12 | # NetBeans 13 | nb-configuration.xml 14 | 15 | # Visual Studio Code 16 | .vscode 17 | 18 | # OSX 19 | .DS_Store 20 | 21 | # Vim 22 | *.swp 23 | *.swo 24 | 25 | # patch 26 | *.orig 27 | *.rej 28 | 29 | # Maven 30 | target/ 31 | pom.xml.tag 32 | pom.xml.releaseBackup 33 | pom.xml.versionsBackup 34 | release.properties 35 | .mvn 36 | 37 | # CDK 38 | cdk.context.json 39 | node_modules 40 | cdk.out 41 | 42 | samconfig.toml 43 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/CustomerServiceApplication.java 44 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/config/AppConfig.java 45 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/controller/CustomerController.java 46 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java 47 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/inspector/XRayInspector.java 48 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/model/Customer.java 49 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/repository/CustomerRepository.java 50 | 04-spring-native/CustomerService/_src/main/java/com/amazon/customerService/service/CustomerService.java 51 | 04-spring-native/CustomerService/_src/main/resources/application-local.properties 52 | 04-spring-native/CustomerService/_src/main/resources/application-prod.properties 53 | 04-spring-native/CustomerService/_src/main/resources/META-INF/native-image/reflect-config.json 54 | 04-spring-native/CustomerService/_src/test/java/com/amazon/customerService/repository/CustomerRepositoryTest.java 55 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lts/ubuntu:22.04 AS builder 2 | LABEL maintainer="Sascha Möllering " 3 | 4 | RUN apt-get update --fix-missing && apt-get install zip curl -y 5 | 6 | RUN \ 7 | curl -s "https://get.sdkman.io" | bash; \ 8 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 9 | sdk install java 17.0.5-amzn; \ 10 | sdk install maven;" 11 | 12 | COPY ./pom.xml ./pom.xml 13 | COPY src ./src/ 14 | 15 | ENV MAVEN_OPTS='-Xmx6g' 16 | 17 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && mvn -Dmaven.test.skip=true clean package" 18 | 19 | FROM public.ecr.aws/lts/ubuntu:22.04 20 | 21 | RUN apt-get update --fix-missing && apt-get install zip curl -y 22 | 23 | RUN addgroup --system spring && adduser --system spring --ingroup spring 24 | USER spring:spring 25 | 26 | RUN \ 27 | curl -s "https://get.sdkman.io" | bash; \ 28 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 29 | sdk install java 17.0.5-amzn" 30 | 31 | COPY --from=builder target/CustomerService-0.0.1.jar CustomerService-0.0.1.jar 32 | EXPOSE 8080 33 | CMD ["/home/spring/.sdkman/candidates/java/current/bin/java","-jar","-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] 34 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/Dockerfile-local: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-alpine 2 | RUN addgroup -S spring && adduser -S spring -G spring 3 | USER spring:spring 4 | ARG JAR_FILE=target/*.jar 5 | COPY ${JAR_FILE} CustomerService-0.0.1.jar 6 | ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService; 17 | 18 | import com.amazon.customerService.config.AppConfig; 19 | import com.amazon.customerService.model.metrics.MetricWrapper; 20 | import com.amazon.customerService.service.EcsMetaDataService; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.boot.SpringApplication; 26 | import org.springframework.boot.autoconfigure.SpringBootApplication; 27 | import org.springframework.boot.context.event.ApplicationReadyEvent; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.lang.management.ManagementFactory; 31 | import java.lang.management.RuntimeMXBean; 32 | import java.time.Duration; 33 | import java.time.Instant; 34 | 35 | @Slf4j 36 | @SpringBootApplication 37 | public class CustomerServiceApplication { 38 | 39 | private static Instant startTime; 40 | private static Instant endTime; 41 | 42 | public static void main(String[] args) { 43 | RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); 44 | startTime = Instant.ofEpochMilli(bean.getStartTime()); 45 | SpringApplication.run(CustomerServiceApplication.class, args); 46 | Duration springBootStartTime = Duration.between(startTime, endTime); 47 | 48 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 49 | MetricWrapper metricWrapper = ecsMetaDataService.getMetaData(); 50 | 51 | if (metricWrapper != null) { 52 | metricWrapper.setVersion(AppConfig.APPLICATION_VERSION); 53 | metricWrapper.setSpringBootStartDuration(springBootStartTime); 54 | metricWrapper.setSpringBootReadyTime(endTime); 55 | ObjectMapper mapper = new ObjectMapper() 56 | .registerModule(new JavaTimeModule()); 57 | 58 | try { 59 | String metricsJson = mapper.writeValueAsString(metricWrapper); 60 | log.info("Metrics: " + metricsJson); 61 | } catch (JsonProcessingException e) { 62 | log.error(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | @EventListener(ApplicationReadyEvent.class) 68 | public void startApp() { 69 | endTime = Instant.now(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.config; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 | import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; 23 | import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; 24 | import software.amazon.awssdk.regions.Region; 25 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 26 | 27 | import java.net.URI; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | public final static Integer APPLICATION_VERSION = 2; 33 | 34 | @Value("${amazon.dynamodb.endpoint}") 35 | private String amazonDynamoDBEndpoint; 36 | 37 | @Bean 38 | public DynamoDbClient getDynamoDbClient() { 39 | AwsCredentialsProvider credentialsProvider = 40 | DefaultCredentialsProvider.builder() 41 | .profileName("default") 42 | .build(); 43 | 44 | return DynamoDbClient.builder() 45 | .region(Region.EU_WEST_1) 46 | .credentialsProvider(credentialsProvider) 47 | .endpointOverride(URI.create(amazonDynamoDBEndpoint)) 48 | .build(); 49 | } 50 | 51 | @Bean 52 | public DynamoDbEnhancedClient getDynamoDbEnhancedClient() { 53 | return DynamoDbEnhancedClient.builder() 54 | .dynamoDbClient(getDynamoDbClient()) 55 | .build(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.controller; 17 | 18 | import com.amazon.customerService.exception.CustomerNotFoundException; 19 | import com.amazon.customerService.model.Customer; 20 | import com.amazon.customerService.service.CustomerService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import java.util.List; 26 | 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/api") 30 | public class CustomerController { 31 | 32 | @Autowired 33 | CustomerService customerService; 34 | 35 | @GetMapping("/customers") 36 | List getCustomers() { 37 | return customerService.findAll(); 38 | } 39 | 40 | @GetMapping("/customers/load") 41 | List loadCustomers() { 42 | customerService.loadCustomerData(100); 43 | return customerService.findAll(); 44 | } 45 | 46 | @PostMapping("/customers") 47 | Customer createCustomer(@RequestBody Customer customer) { 48 | return customerService.create(customer); 49 | } 50 | 51 | @GetMapping("/customers/{id}") 52 | Customer getCustomerbyId(@PathVariable String id) { 53 | return customerService.findById(id); 54 | } 55 | 56 | @PutMapping("/customers/{id}") 57 | Customer replaceCustomer(@RequestBody Customer newCustomer, @PathVariable String id) { 58 | Customer customer = customerService.findById(id); 59 | 60 | if (null == customer) { 61 | throw new CustomerNotFoundException(newCustomer.getId()); 62 | } 63 | 64 | customer.setId(newCustomer.getId()); 65 | customer.setRegDate(newCustomer.getRegDate()); 66 | customer.setEmail(newCustomer.getEmail()); 67 | customer.setAccountNumber(newCustomer.getAccountNumber()); 68 | customer.setName(newCustomer.getName()); 69 | 70 | customerService.update(customer); 71 | 72 | return customer; 73 | } 74 | 75 | @DeleteMapping("/customers/{id}") 76 | void deleteCustomerById(@PathVariable String id) { 77 | customerService.deleteById(id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.exception; 17 | 18 | public class CustomerNotFoundException extends RuntimeException { 19 | 20 | public CustomerNotFoundException(String id) { 21 | super("Could not find customer " + id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/ContainerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class ContainerMetric { 23 | private Instant createdAt; 24 | private Instant startedAt; 25 | 26 | public ContainerMetric() { 27 | } 28 | 29 | public ContainerMetric(Instant createdAt, Instant startedAt) { 30 | this.createdAt = createdAt; 31 | this.startedAt = startedAt; 32 | } 33 | 34 | public Duration calculateDuration() { 35 | if (startedAt == null || createdAt == null) 36 | return null; 37 | 38 | Duration duration = Duration.between(createdAt, startedAt); 39 | 40 | return duration; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "ContainerMetric{" + 46 | "createdAt=" + createdAt + 47 | ", startedAt=" + startedAt + 48 | '}'; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object o) { 53 | if (this == o) return true; 54 | if (o == null || getClass() != o.getClass()) return false; 55 | ContainerMetric that = (ContainerMetric) o; 56 | return createdAt.equals(that.createdAt) && startedAt.equals(that.startedAt); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(createdAt, startedAt); 62 | } 63 | 64 | public Instant getCreatedAt() { 65 | return createdAt; 66 | } 67 | 68 | public void setCreatedAt(Instant createdAt) { 69 | this.createdAt = createdAt; 70 | } 71 | 72 | public Instant getStartedAt() { 73 | return startedAt; 74 | } 75 | 76 | public void setStartedAt(Instant startedAt) { 77 | this.startedAt = startedAt; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/MetricWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | 21 | public class MetricWrapper { 22 | 23 | private ContainerMetric containerMetric; 24 | private TaskMetric taskMetric; 25 | private Duration springBootStartDuration; 26 | private Instant springBootReadyTime; 27 | private Integer version; 28 | 29 | public MetricWrapper() { 30 | } 31 | 32 | public MetricWrapper(ContainerMetric containerMetric, TaskMetric taskMetric, Duration springBootStartTime, Instant springBootReadyTime, Integer version) { 33 | this.containerMetric = containerMetric; 34 | this.taskMetric = taskMetric; 35 | this.springBootStartDuration = springBootStartTime; 36 | this.springBootReadyTime = springBootReadyTime; 37 | this.version = version; 38 | } 39 | 40 | public Integer getVersion() { 41 | return version; 42 | } 43 | 44 | public void setVersion(Integer version) { 45 | this.version = version; 46 | } 47 | 48 | public ContainerMetric getContainerMetric() { 49 | return containerMetric; 50 | } 51 | 52 | public void setContainerMetric(ContainerMetric containerMetric) { 53 | this.containerMetric = containerMetric; 54 | } 55 | 56 | public TaskMetric getTaskMetric() { 57 | return taskMetric; 58 | } 59 | 60 | public void setTaskMetric(TaskMetric taskMetric) { 61 | this.taskMetric = taskMetric; 62 | } 63 | 64 | public Instant getSpringBootReadyTime() { 65 | return springBootReadyTime; 66 | } 67 | 68 | public void setSpringBootReadyTime(Instant springBootReadyTime) { 69 | this.springBootReadyTime = springBootReadyTime; 70 | } 71 | 72 | public Duration getSpringBootStartDuration() { 73 | return springBootStartDuration; 74 | } 75 | 76 | public void setSpringBootStartDuration(Duration springBootStartDuration) { 77 | this.springBootStartDuration = springBootStartDuration; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/TaskMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class TaskMetric { 23 | private Instant pullStartedAt; 24 | private Instant pullStoppedAt; 25 | private String taskArn; 26 | 27 | public TaskMetric() { 28 | } 29 | 30 | public TaskMetric(Instant pullStartedAt, Instant pullStoppedAt, String taskArn) { 31 | this.pullStartedAt = pullStartedAt; 32 | this.pullStoppedAt = pullStoppedAt; 33 | this.taskArn = taskArn; 34 | } 35 | 36 | public Instant getPullStartedAt() { 37 | return pullStartedAt; 38 | } 39 | 40 | public void setPullStartedAt(Instant pullStartedAt) { 41 | this.pullStartedAt = pullStartedAt; 42 | } 43 | 44 | public Instant getPullStoppedAt() { 45 | return pullStoppedAt; 46 | } 47 | 48 | public void setPullStoppedAt(Instant pullStoppedAt) { 49 | this.pullStoppedAt = pullStoppedAt; 50 | } 51 | 52 | public Duration calculateDuration() { 53 | if (pullStartedAt == null || pullStoppedAt == null) 54 | return null; 55 | 56 | Duration duration = Duration.between(pullStartedAt, pullStoppedAt); 57 | 58 | return duration; 59 | } 60 | 61 | public String getTaskArn() { 62 | return taskArn; 63 | } 64 | 65 | public void setTaskArn(String taskArn) { 66 | this.taskArn = taskArn; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object o) { 71 | if (this == o) return true; 72 | if (o == null || getClass() != o.getClass()) return false; 73 | TaskMetric that = (TaskMetric) o; 74 | return taskArn.equals(that.taskArn); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | return Objects.hash(taskArn); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "TaskMetric{" + 85 | "pullStartedAt=" + pullStartedAt + 86 | ", pullStoppedAt=" + pullStoppedAt + 87 | ", taskArn='" + taskArn + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/java/com/amazon/customerService/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.Customer; 19 | import com.amazon.customerService.repository.CustomerRepository; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.sql.Date; 25 | import java.time.Instant; 26 | import java.util.List; 27 | import java.util.Random; 28 | import java.util.UUID; 29 | 30 | @Service 31 | public class CustomerService { 32 | 33 | @Autowired 34 | CustomerRepository customerRepository; 35 | 36 | public List findAll() { 37 | return customerRepository.findAll(); 38 | } 39 | 40 | public Customer findById(String id) { 41 | return customerRepository.findById(id); 42 | } 43 | 44 | public Customer create(Customer customer) { 45 | return customerRepository.save(customer); 46 | } 47 | 48 | public Customer update(Customer customer) { 49 | return customerRepository.save(customer); 50 | } 51 | 52 | public void deleteById(String id) { 53 | customerRepository.deleteById(id); 54 | } 55 | 56 | public void loadCustomerData(int count) { 57 | 58 | for (int i = 0; i < count; i++) { 59 | String generatedString = RandomStringUtils.randomAlphabetic(10); 60 | 61 | Customer cust = new Customer(); 62 | cust.setName(generatedString); 63 | cust.setId(UUID.randomUUID().toString()); 64 | cust.setRegDate(Date.from(Instant.now())); 65 | cust.setEmail(generatedString + "@test.com"); 66 | 67 | Random rnd = new Random(); 68 | int number = rnd.nextInt(999999); 69 | 70 | cust.setAccountNumber(String.format("%06d", number)); 71 | 72 | customerRepository.save(cust); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=http://localhost:8000/ 2 | logging.level.root=DEBUG -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=https://dynamodb.eu-west-1.amazonaws.com 2 | logging.level.root=INFO -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/test/resources/container_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "DockerId": "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66", 3 | "Name": "curl", 4 | "DockerName": "ecs-curltest-24-curl-cca48e8dcadd97805600", 5 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 6 | "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", 7 | "Labels": { 8 | "com.amazonaws.ecs.cluster": "default", 9 | "com.amazonaws.ecs.container-name": "curl", 10 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/8f03e41243824aea923aca126495f665", 11 | "com.amazonaws.ecs.task-definition-family": "curltest", 12 | "com.amazonaws.ecs.task-definition-version": "24" 13 | }, 14 | "DesiredStatus": "RUNNING", 15 | "KnownStatus": "RUNNING", 16 | "Limits": { 17 | "CPU": 10, 18 | "Memory": 128 19 | }, 20 | "CreatedAt": "2020-10-02T00:15:07.620912337Z", 21 | "StartedAt": "2020-10-02T00:15:08.062559351Z", 22 | "Type": "NORMAL", 23 | "LogDriver": "awslogs", 24 | "LogOptions": { 25 | "awslogs-create-group": "true", 26 | "awslogs-group": "/ecs/metadata", 27 | "awslogs-region": "us-west-2", 28 | "awslogs-stream": "ecs/curl/8f03e41243824aea923aca126495f665" 29 | }, 30 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9", 31 | "Networks": [ 32 | { 33 | "NetworkMode": "awsvpc", 34 | "IPv4Addresses": [ 35 | "10.0.2.100" 36 | ], 37 | "AttachmentIndex": 0, 38 | "MACAddress": "0e:9e:32:c7:48:85", 39 | "IPv4SubnetCIDRBlock": "10.0.2.0/24", 40 | "PrivateDNSName": "ip-10-0-2-100.us-west-2.compute.internal", 41 | "SubnetGatewayIpv4Address": "10.0.2.1/24" 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /baseline-arm/CustomerService/src/test/resources/task_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "Cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 3 | "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 4 | "Family": "curltest", 5 | "Revision": "3", 6 | "DesiredStatus": "RUNNING", 7 | "KnownStatus": "RUNNING", 8 | "Limits": { 9 | "CPU": 0.25, 10 | "Memory": 512 11 | }, 12 | "PullStartedAt": "2020-10-08T20:47:16.053330955Z", 13 | "PullStoppedAt": "2020-10-08T20:47:19.592684631Z", 14 | "AvailabilityZone": "us-west-2a", 15 | "Containers": [ 16 | { 17 | "DockerId": "e9028f8d5d8e4f258373e7b93ce9a3c3-2495160603", 18 | "Name": "curl", 19 | "DockerName": "curl", 20 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 21 | "ImageID": "sha256:25f3695bedfb454a50f12d127839a68ad3caf91e451c1da073db34c542c4d2cb", 22 | "Labels": { 23 | "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 24 | "com.amazonaws.ecs.container-name": "curl", 25 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 26 | "com.amazonaws.ecs.task-definition-family": "curltest", 27 | "com.amazonaws.ecs.task-definition-version": "3" 28 | }, 29 | "DesiredStatus": "RUNNING", 30 | "KnownStatus": "RUNNING", 31 | "Limits": { 32 | "CPU": 10, 33 | "Memory": 128 34 | }, 35 | "CreatedAt": "2020-10-08T20:47:20.567813946Z", 36 | "StartedAt": "2020-10-08T20:47:20.567813946Z", 37 | "Type": "NORMAL", 38 | "Networks": [ 39 | { 40 | "NetworkMode": "awsvpc", 41 | "IPv4Addresses": [ 42 | "192.0.2.3" 43 | ], 44 | "IPv6Addresses": [ 45 | "2001:dB8:10b:1a00:32bf:a372:d80f:e958" 46 | ], 47 | "AttachmentIndex": 0, 48 | "MACAddress": "02:b7:20:19:72:39", 49 | "IPv4SubnetCIDRBlock": "192.0.2.0/24", 50 | "IPv6SubnetCIDRBlock": "2600:1f13:10b:1a00::/64", 51 | "DomainNameServers": [ 52 | "192.0.2.2" 53 | ], 54 | "DomainNameSearchList": [ 55 | "us-west-2.compute.internal" 56 | ], 57 | "PrivateDNSName": "ip-172-31-30-173.us-west-2.compute.internal", 58 | "SubnetGatewayIpv4Address": "192.0.2.0/24" 59 | } 60 | ], 61 | "ClockDrift": { 62 | "ClockErrorBound": 0.5458234999999999, 63 | "ReferenceTimestamp": "2021-09-07T16:57:44Z", 64 | "ClockSynchronizationStatus": "SYNCHRONIZED" 65 | }, 66 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/1bdcca8b-f905-4ee6-885c-4064cb70f6e6", 67 | "LogOptions": { 68 | "awslogs-create-group": "true", 69 | "awslogs-group": "/ecs/containerlogs", 70 | "awslogs-region": "us-west-2", 71 | "awslogs-stream": "ecs/curl/e9028f8d5d8e4f258373e7b93ce9a3c3" 72 | }, 73 | "LogDriver": "awslogs" 74 | } 75 | ], 76 | "LaunchType": "FARGATE" 77 | } -------------------------------------------------------------------------------- /baseline/CustomerService/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /baseline/CustomerService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lts/ubuntu:22.04 AS builder 2 | LABEL maintainer="Sascha Möllering " 3 | 4 | RUN apt-get update --fix-missing && apt-get install zip curl -y 5 | 6 | RUN \ 7 | curl -s "https://get.sdkman.io" | bash; \ 8 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 9 | sdk install java 17.0.5-amzn; \ 10 | sdk install maven;" 11 | 12 | COPY ./pom.xml ./pom.xml 13 | COPY src ./src/ 14 | 15 | ENV MAVEN_OPTS='-Xmx6g' 16 | 17 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && mvn -Dmaven.test.skip=true clean package" 18 | 19 | FROM public.ecr.aws/lts/ubuntu:22.04 20 | 21 | RUN apt-get update --fix-missing && apt-get install zip curl -y 22 | 23 | RUN addgroup --system spring && adduser --system spring --ingroup spring 24 | USER spring:spring 25 | 26 | RUN \ 27 | curl -s "https://get.sdkman.io" | bash; \ 28 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 29 | sdk install java 17.0.5-amzn" 30 | 31 | COPY --from=builder target/CustomerService-0.0.1.jar CustomerService-0.0.1.jar 32 | EXPOSE 8080 33 | CMD ["/home/spring/.sdkman/candidates/java/current/bin/java","-jar","-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] 34 | -------------------------------------------------------------------------------- /baseline/CustomerService/Dockerfile-local: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-alpine 2 | RUN addgroup -S spring && adduser -S spring -G spring 3 | USER spring:spring 4 | ARG JAR_FILE=target/*.jar 5 | COPY ${JAR_FILE} CustomerService-0.0.1.jar 6 | ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService; 17 | 18 | import com.amazon.customerService.config.AppConfig; 19 | import com.amazon.customerService.model.metrics.MetricWrapper; 20 | import com.amazon.customerService.service.EcsMetaDataService; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.boot.SpringApplication; 26 | import org.springframework.boot.autoconfigure.SpringBootApplication; 27 | import org.springframework.boot.context.event.ApplicationReadyEvent; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.lang.management.ManagementFactory; 31 | import java.lang.management.RuntimeMXBean; 32 | import java.time.Duration; 33 | import java.time.Instant; 34 | 35 | @Slf4j 36 | @SpringBootApplication 37 | public class CustomerServiceApplication { 38 | 39 | private static Instant startTime; 40 | private static Instant endTime; 41 | 42 | public static void main(String[] args) { 43 | RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); 44 | startTime = Instant.ofEpochMilli(bean.getStartTime()); 45 | SpringApplication.run(CustomerServiceApplication.class, args); 46 | Duration springBootStartTime = Duration.between(startTime, endTime); 47 | 48 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 49 | MetricWrapper metricWrapper = ecsMetaDataService.getMetaData(); 50 | 51 | if (metricWrapper != null) { 52 | metricWrapper.setVersion(AppConfig.APPLICATION_VERSION); 53 | metricWrapper.setSpringBootStartDuration(springBootStartTime); 54 | metricWrapper.setSpringBootReadyTime(endTime); 55 | ObjectMapper mapper = new ObjectMapper() 56 | .registerModule(new JavaTimeModule()); 57 | 58 | try { 59 | String metricsJson = mapper.writeValueAsString(metricWrapper); 60 | log.info("Metrics: " + metricsJson); 61 | } catch (JsonProcessingException e) { 62 | log.error(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | @EventListener(ApplicationReadyEvent.class) 68 | public void startApp() { 69 | endTime = Instant.now(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.config; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 | import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; 23 | import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; 24 | import software.amazon.awssdk.regions.Region; 25 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 26 | 27 | import java.net.URI; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | public final static Integer APPLICATION_VERSION = 1; 33 | 34 | @Value("${amazon.dynamodb.endpoint}") 35 | private String amazonDynamoDBEndpoint; 36 | 37 | @Bean 38 | public DynamoDbClient getDynamoDbClient() { 39 | AwsCredentialsProvider credentialsProvider = 40 | DefaultCredentialsProvider.builder() 41 | .profileName("default") 42 | .build(); 43 | 44 | return DynamoDbClient.builder() 45 | .region(Region.EU_WEST_1) 46 | .credentialsProvider(credentialsProvider) 47 | .endpointOverride(URI.create(amazonDynamoDBEndpoint)) 48 | .build(); 49 | } 50 | 51 | @Bean 52 | public DynamoDbEnhancedClient getDynamoDbEnhancedClient() { 53 | return DynamoDbEnhancedClient.builder() 54 | .dynamoDbClient(getDynamoDbClient()) 55 | .build(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.controller; 17 | 18 | import com.amazon.customerService.exception.CustomerNotFoundException; 19 | import com.amazon.customerService.model.Customer; 20 | import com.amazon.customerService.service.CustomerService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import java.util.List; 26 | 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/api") 30 | public class CustomerController { 31 | 32 | @Autowired 33 | CustomerService customerService; 34 | 35 | @GetMapping("/customers") 36 | List getCustomers() { 37 | return customerService.findAll(); 38 | } 39 | 40 | @GetMapping("/customers/load") 41 | List loadCustomers() { 42 | customerService.loadCustomerData(100); 43 | return customerService.findAll(); 44 | } 45 | 46 | @PostMapping("/customers") 47 | Customer createCustomer(@RequestBody Customer customer) { 48 | return customerService.create(customer); 49 | } 50 | 51 | @GetMapping("/customers/{id}") 52 | Customer getCustomerbyId(@PathVariable String id) { 53 | return customerService.findById(id); 54 | } 55 | 56 | @PutMapping("/customers/{id}") 57 | Customer replaceCustomer(@RequestBody Customer newCustomer, @PathVariable String id) { 58 | Customer customer = customerService.findById(id); 59 | 60 | if (null == customer) { 61 | throw new CustomerNotFoundException(newCustomer.getId()); 62 | } 63 | 64 | customer.setId(newCustomer.getId()); 65 | customer.setRegDate(newCustomer.getRegDate()); 66 | customer.setEmail(newCustomer.getEmail()); 67 | customer.setAccountNumber(newCustomer.getAccountNumber()); 68 | customer.setName(newCustomer.getName()); 69 | 70 | customerService.update(customer); 71 | 72 | return customer; 73 | } 74 | 75 | @DeleteMapping("/customers/{id}") 76 | void deleteCustomerById(@PathVariable String id) { 77 | customerService.deleteById(id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.exception; 17 | 18 | public class CustomerNotFoundException extends RuntimeException { 19 | 20 | public CustomerNotFoundException(String id) { 21 | super("Could not find customer " + id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/model/Customer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute; 20 | import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; 21 | import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; 22 | 23 | import java.util.Date; 24 | import java.util.Objects; 25 | 26 | @DynamoDbBean 27 | @JsonInclude(JsonInclude.Include.NON_NULL) 28 | 29 | public class Customer { 30 | 31 | private String id, name, email, accountNumber; 32 | private Date regDate; 33 | 34 | @DynamoDbPartitionKey 35 | @DynamoDbAttribute(value = "Id") 36 | public String getId() { 37 | return id; 38 | } 39 | 40 | public void setId(String id) { 41 | this.id = id; 42 | } 43 | 44 | @DynamoDbAttribute(value = "Name") 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public void setName(String name) { 50 | this.name = name; 51 | } 52 | 53 | @DynamoDbAttribute(value = "Email") 54 | public String getEmail() { 55 | return email; 56 | } 57 | 58 | public void setEmail(String email) { 59 | this.email = email; 60 | } 61 | 62 | @DynamoDbAttribute(value = "AccountNumber") 63 | public String getAccountNumber() { 64 | return accountNumber; 65 | } 66 | 67 | public void setAccountNumber(String accountNumber) { 68 | this.accountNumber = accountNumber; 69 | } 70 | 71 | @DynamoDbAttribute(value = "RegistrationDate") 72 | public Date getRegDate() { 73 | return regDate; 74 | } 75 | 76 | public void setRegDate(Date regDate) { 77 | this.regDate = regDate; 78 | } 79 | 80 | @Override 81 | public boolean equals(Object o) { 82 | if (this == o) return true; 83 | if (o == null || getClass() != o.getClass()) return false; 84 | Customer customer = (Customer) o; 85 | return id.equals(customer.id); 86 | } 87 | 88 | @Override 89 | public int hashCode() { 90 | return Objects.hash(id); 91 | } 92 | 93 | @Override 94 | public String toString() { 95 | return "Customer{" + 96 | "id='" + id + '\'' + 97 | ", name='" + name + '\'' + 98 | ", email='" + email + '\'' + 99 | ", accountNumber='" + accountNumber + '\'' + 100 | ", regDate=" + regDate + 101 | '}'; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/model/metrics/ContainerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class ContainerMetric { 23 | private Instant createdAt; 24 | private Instant startedAt; 25 | 26 | public ContainerMetric() { 27 | } 28 | 29 | public ContainerMetric(Instant createdAt, Instant startedAt) { 30 | this.createdAt = createdAt; 31 | this.startedAt = startedAt; 32 | } 33 | 34 | public Duration calculateDuration() { 35 | if (startedAt == null || createdAt == null) 36 | return null; 37 | 38 | Duration duration = Duration.between(createdAt, startedAt); 39 | 40 | return duration; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "ContainerMetric{" + 46 | "createdAt=" + createdAt + 47 | ", startedAt=" + startedAt + 48 | '}'; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object o) { 53 | if (this == o) return true; 54 | if (o == null || getClass() != o.getClass()) return false; 55 | ContainerMetric that = (ContainerMetric) o; 56 | return createdAt.equals(that.createdAt) && startedAt.equals(that.startedAt); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(createdAt, startedAt); 62 | } 63 | 64 | public Instant getCreatedAt() { 65 | return createdAt; 66 | } 67 | 68 | public void setCreatedAt(Instant createdAt) { 69 | this.createdAt = createdAt; 70 | } 71 | 72 | public Instant getStartedAt() { 73 | return startedAt; 74 | } 75 | 76 | public void setStartedAt(Instant startedAt) { 77 | this.startedAt = startedAt; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/model/metrics/MetricWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | 21 | public class MetricWrapper { 22 | 23 | private ContainerMetric containerMetric; 24 | private TaskMetric taskMetric; 25 | private Duration springBootStartDuration; 26 | private Instant springBootReadyTime; 27 | private Integer version; 28 | 29 | public MetricWrapper() { 30 | } 31 | 32 | public MetricWrapper(ContainerMetric containerMetric, TaskMetric taskMetric, Duration springBootStartTime, Instant springBootReadyTime, Integer version) { 33 | this.containerMetric = containerMetric; 34 | this.taskMetric = taskMetric; 35 | this.springBootStartDuration = springBootStartTime; 36 | this.springBootReadyTime = springBootReadyTime; 37 | this.version = version; 38 | } 39 | 40 | public Integer getVersion() { 41 | return version; 42 | } 43 | 44 | public void setVersion(Integer version) { 45 | this.version = version; 46 | } 47 | 48 | public ContainerMetric getContainerMetric() { 49 | return containerMetric; 50 | } 51 | 52 | public void setContainerMetric(ContainerMetric containerMetric) { 53 | this.containerMetric = containerMetric; 54 | } 55 | 56 | public TaskMetric getTaskMetric() { 57 | return taskMetric; 58 | } 59 | 60 | public void setTaskMetric(TaskMetric taskMetric) { 61 | this.taskMetric = taskMetric; 62 | } 63 | 64 | public Instant getSpringBootReadyTime() { 65 | return springBootReadyTime; 66 | } 67 | 68 | public void setSpringBootReadyTime(Instant springBootReadyTime) { 69 | this.springBootReadyTime = springBootReadyTime; 70 | } 71 | 72 | public Duration getSpringBootStartDuration() { 73 | return springBootStartDuration; 74 | } 75 | 76 | public void setSpringBootStartDuration(Duration springBootStartDuration) { 77 | this.springBootStartDuration = springBootStartDuration; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/model/metrics/TaskMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class TaskMetric { 23 | private Instant pullStartedAt; 24 | private Instant pullStoppedAt; 25 | private String taskArn; 26 | 27 | public TaskMetric() { 28 | } 29 | 30 | public TaskMetric(Instant pullStartedAt, Instant pullStoppedAt, String taskArn) { 31 | this.pullStartedAt = pullStartedAt; 32 | this.pullStoppedAt = pullStoppedAt; 33 | this.taskArn = taskArn; 34 | } 35 | 36 | public Instant getPullStartedAt() { 37 | return pullStartedAt; 38 | } 39 | 40 | public void setPullStartedAt(Instant pullStartedAt) { 41 | this.pullStartedAt = pullStartedAt; 42 | } 43 | 44 | public Instant getPullStoppedAt() { 45 | return pullStoppedAt; 46 | } 47 | 48 | public void setPullStoppedAt(Instant pullStoppedAt) { 49 | this.pullStoppedAt = pullStoppedAt; 50 | } 51 | 52 | public Duration calculateDuration() { 53 | if (pullStartedAt == null || pullStoppedAt == null) 54 | return null; 55 | 56 | Duration duration = Duration.between(pullStartedAt, pullStoppedAt); 57 | 58 | return duration; 59 | } 60 | 61 | public String getTaskArn() { 62 | return taskArn; 63 | } 64 | 65 | public void setTaskArn(String taskArn) { 66 | this.taskArn = taskArn; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object o) { 71 | if (this == o) return true; 72 | if (o == null || getClass() != o.getClass()) return false; 73 | TaskMetric that = (TaskMetric) o; 74 | return taskArn.equals(that.taskArn); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | return Objects.hash(taskArn); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "TaskMetric{" + 85 | "pullStartedAt=" + pullStartedAt + 86 | ", pullStoppedAt=" + pullStoppedAt + 87 | ", taskArn='" + taskArn + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/java/com/amazon/customerService/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.Customer; 19 | import com.amazon.customerService.repository.CustomerRepository; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.sql.Date; 25 | import java.time.Instant; 26 | import java.util.List; 27 | import java.util.Random; 28 | import java.util.UUID; 29 | 30 | @Service 31 | public class CustomerService { 32 | 33 | @Autowired 34 | CustomerRepository customerRepository; 35 | 36 | public List findAll() { 37 | return customerRepository.findAll(); 38 | } 39 | 40 | public Customer findById(String id) { 41 | return customerRepository.findById(id); 42 | } 43 | 44 | public Customer create(Customer customer) { 45 | return customerRepository.save(customer); 46 | } 47 | 48 | public Customer update(Customer customer) { 49 | return customerRepository.save(customer); 50 | } 51 | 52 | public void deleteById(String id) { 53 | customerRepository.deleteById(id); 54 | } 55 | 56 | public void loadCustomerData(int count) { 57 | 58 | for (int i = 0; i < count; i++) { 59 | String generatedString = RandomStringUtils.randomAlphabetic(10); 60 | 61 | Customer cust = new Customer(); 62 | cust.setName(generatedString); 63 | cust.setId(UUID.randomUUID().toString()); 64 | cust.setRegDate(Date.from(Instant.now())); 65 | cust.setEmail(generatedString + "@test.com"); 66 | 67 | Random rnd = new Random(); 68 | int number = rnd.nextInt(999999); 69 | 70 | cust.setAccountNumber(String.format("%06d", number)); 71 | 72 | customerRepository.save(cust); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=http://localhost:8000/ 2 | logging.level.root=DEBUG -------------------------------------------------------------------------------- /baseline/CustomerService/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=https://dynamodb.eu-west-1.amazonaws.com 2 | logging.level.root=INFO -------------------------------------------------------------------------------- /baseline/CustomerService/src/test/resources/container_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "DockerId": "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66", 3 | "Name": "curl", 4 | "DockerName": "ecs-curltest-24-curl-cca48e8dcadd97805600", 5 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 6 | "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", 7 | "Labels": { 8 | "com.amazonaws.ecs.cluster": "default", 9 | "com.amazonaws.ecs.container-name": "curl", 10 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/8f03e41243824aea923aca126495f665", 11 | "com.amazonaws.ecs.task-definition-family": "curltest", 12 | "com.amazonaws.ecs.task-definition-version": "24" 13 | }, 14 | "DesiredStatus": "RUNNING", 15 | "KnownStatus": "RUNNING", 16 | "Limits": { 17 | "CPU": 10, 18 | "Memory": 128 19 | }, 20 | "CreatedAt": "2020-10-02T00:15:07.620912337Z", 21 | "StartedAt": "2020-10-02T00:15:08.062559351Z", 22 | "Type": "NORMAL", 23 | "LogDriver": "awslogs", 24 | "LogOptions": { 25 | "awslogs-create-group": "true", 26 | "awslogs-group": "/ecs/metadata", 27 | "awslogs-region": "us-west-2", 28 | "awslogs-stream": "ecs/curl/8f03e41243824aea923aca126495f665" 29 | }, 30 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9", 31 | "Networks": [ 32 | { 33 | "NetworkMode": "awsvpc", 34 | "IPv4Addresses": [ 35 | "10.0.2.100" 36 | ], 37 | "AttachmentIndex": 0, 38 | "MACAddress": "0e:9e:32:c7:48:85", 39 | "IPv4SubnetCIDRBlock": "10.0.2.0/24", 40 | "PrivateDNSName": "ip-10-0-2-100.us-west-2.compute.internal", 41 | "SubnetGatewayIpv4Address": "10.0.2.1/24" 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /baseline/CustomerService/src/test/resources/task_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "Cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 3 | "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 4 | "Family": "curltest", 5 | "Revision": "3", 6 | "DesiredStatus": "RUNNING", 7 | "KnownStatus": "RUNNING", 8 | "Limits": { 9 | "CPU": 0.25, 10 | "Memory": 512 11 | }, 12 | "PullStartedAt": "2020-10-08T20:47:16.053330955Z", 13 | "PullStoppedAt": "2020-10-08T20:47:19.592684631Z", 14 | "AvailabilityZone": "us-west-2a", 15 | "Containers": [ 16 | { 17 | "DockerId": "e9028f8d5d8e4f258373e7b93ce9a3c3-2495160603", 18 | "Name": "curl", 19 | "DockerName": "curl", 20 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 21 | "ImageID": "sha256:25f3695bedfb454a50f12d127839a68ad3caf91e451c1da073db34c542c4d2cb", 22 | "Labels": { 23 | "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 24 | "com.amazonaws.ecs.container-name": "curl", 25 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 26 | "com.amazonaws.ecs.task-definition-family": "curltest", 27 | "com.amazonaws.ecs.task-definition-version": "3" 28 | }, 29 | "DesiredStatus": "RUNNING", 30 | "KnownStatus": "RUNNING", 31 | "Limits": { 32 | "CPU": 10, 33 | "Memory": 128 34 | }, 35 | "CreatedAt": "2020-10-08T20:47:20.567813946Z", 36 | "StartedAt": "2020-10-08T20:47:20.567813946Z", 37 | "Type": "NORMAL", 38 | "Networks": [ 39 | { 40 | "NetworkMode": "awsvpc", 41 | "IPv4Addresses": [ 42 | "192.0.2.3" 43 | ], 44 | "IPv6Addresses": [ 45 | "2001:dB8:10b:1a00:32bf:a372:d80f:e958" 46 | ], 47 | "AttachmentIndex": 0, 48 | "MACAddress": "02:b7:20:19:72:39", 49 | "IPv4SubnetCIDRBlock": "192.0.2.0/24", 50 | "IPv6SubnetCIDRBlock": "2600:1f13:10b:1a00::/64", 51 | "DomainNameServers": [ 52 | "192.0.2.2" 53 | ], 54 | "DomainNameSearchList": [ 55 | "us-west-2.compute.internal" 56 | ], 57 | "PrivateDNSName": "ip-172-31-30-173.us-west-2.compute.internal", 58 | "SubnetGatewayIpv4Address": "192.0.2.0/24" 59 | } 60 | ], 61 | "ClockDrift": { 62 | "ClockErrorBound": 0.5458234999999999, 63 | "ReferenceTimestamp": "2021-09-07T16:57:44Z", 64 | "ClockSynchronizationStatus": "SYNCHRONIZED" 65 | }, 66 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/1bdcca8b-f905-4ee6-885c-4064cb70f6e6", 67 | "LogOptions": { 68 | "awslogs-create-group": "true", 69 | "awslogs-group": "/ecs/containerlogs", 70 | "awslogs-region": "us-west-2", 71 | "awslogs-stream": "ecs/curl/e9028f8d5d8e4f258373e7b93ce9a3c3" 72 | }, 73 | "LogDriver": "awslogs" 74 | } 75 | ], 76 | "LaunchType": "FARGATE" 77 | } -------------------------------------------------------------------------------- /cdkapp/.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .project 3 | .classpath 4 | .settings/ 5 | bin/ 6 | 7 | # IntelliJ 8 | .idea 9 | *.ipr 10 | *.iml 11 | *.iws 12 | 13 | # NetBeans 14 | nb-configuration.xml 15 | 16 | # Visual Studio Code 17 | .vscode 18 | 19 | # OSX 20 | .DS_Store 21 | 22 | # Vim 23 | *.swp 24 | *.swo 25 | 26 | # patch 27 | *.orig 28 | *.rej 29 | 30 | # Maven 31 | target/ 32 | pom.xml.tag 33 | pom.xml.releaseBackup 34 | pom.xml.versionsBackup 35 | release.properties 36 | .mvn 37 | 38 | # CDK 39 | cdk.context.json 40 | node_modules 41 | bin 42 | cdk.out 43 | 44 | samconfig.toml -------------------------------------------------------------------------------- /cdkapp/.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | !*.d.ts 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /cdkapp/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to your CDK TypeScript project! 2 | 3 | This is a blank project for TypeScript development with CDK. 4 | 5 | The `cdk.json` file tells the CDK Toolkit how to execute your app. 6 | 7 | ## Useful commands 8 | 9 | * `npm run build` compile typescript to js 10 | * `npm run watch` watch for changes and compile 11 | * `npm run test` perform the jest unit tests 12 | * `cdk deploy` deploy this stack to your default AWS account/region 13 | * `cdk diff` compare deployed stack with current state 14 | * `cdk synth` emits the synthesized CloudFormation template 15 | -------------------------------------------------------------------------------- /cdkapp/bin/cdkapp.d.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import 'source-map-support/register'; 3 | -------------------------------------------------------------------------------- /cdkapp/bin/cdkapp.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | require("source-map-support/register"); 5 | const cdk = require("aws-cdk-lib"); 6 | const cdkapp_stack_1 = require("../lib/cdkapp-stack"); 7 | const app = new cdk.App(); 8 | new cdkapp_stack_1.CdkappStack(app, 'CdkappStack', { 9 | /* If you don't specify 'env', this stack will be environment-agnostic. 10 | * Account/Region-dependent features and context lookups will not work, 11 | * but a single synthesized template can be deployed anywhere. */ 12 | /* Uncomment the next line to specialize this stack for the AWS Account 13 | * and Region that are implied by the current CLI configuration. */ 14 | // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, 15 | /* Uncomment the next line if you know exactly what Account and Region you 16 | * want to deploy the stack to. */ 17 | // env: { account: '123456789012', region: 'us-east-1' }, 18 | /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */ 19 | }); 20 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2RrYXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHVDQUFxQztBQUNyQyxtQ0FBbUM7QUFDbkMsc0RBQWtEO0FBRWxELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQzFCLElBQUksMEJBQVcsQ0FBQyxHQUFHLEVBQUUsYUFBYSxFQUFFO0FBQ2xDOztpRUFFaUU7QUFFakU7bUVBQ21FO0FBQ25FLDZGQUE2RjtBQUU3RjtrQ0FDa0M7QUFDbEMseURBQXlEO0FBRXpELDhGQUE4RjtDQUMvRixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIjIS91c3IvYmluL2VudiBub2RlXG5pbXBvcnQgJ3NvdXJjZS1tYXAtc3VwcG9ydC9yZWdpc3Rlcic7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ2RrYXBwU3RhY2sgfSBmcm9tICcuLi9saWIvY2RrYXBwLXN0YWNrJztcblxuY29uc3QgYXBwID0gbmV3IGNkay5BcHAoKTtcbm5ldyBDZGthcHBTdGFjayhhcHAsICdDZGthcHBTdGFjaycsIHtcbiAgLyogSWYgeW91IGRvbid0IHNwZWNpZnkgJ2VudicsIHRoaXMgc3RhY2sgd2lsbCBiZSBlbnZpcm9ubWVudC1hZ25vc3RpYy5cbiAgICogQWNjb3VudC9SZWdpb24tZGVwZW5kZW50IGZlYXR1cmVzIGFuZCBjb250ZXh0IGxvb2t1cHMgd2lsbCBub3Qgd29yayxcbiAgICogYnV0IGEgc2luZ2xlIHN5bnRoZXNpemVkIHRlbXBsYXRlIGNhbiBiZSBkZXBsb3llZCBhbnl3aGVyZS4gKi9cblxuICAvKiBVbmNvbW1lbnQgdGhlIG5leHQgbGluZSB0byBzcGVjaWFsaXplIHRoaXMgc3RhY2sgZm9yIHRoZSBBV1MgQWNjb3VudFxuICAgKiBhbmQgUmVnaW9uIHRoYXQgYXJlIGltcGxpZWQgYnkgdGhlIGN1cnJlbnQgQ0xJIGNvbmZpZ3VyYXRpb24uICovXG4gIC8vIGVudjogeyBhY2NvdW50OiBwcm9jZXNzLmVudi5DREtfREVGQVVMVF9BQ0NPVU5ULCByZWdpb246IHByb2Nlc3MuZW52LkNES19ERUZBVUxUX1JFR0lPTiB9LFxuXG4gIC8qIFVuY29tbWVudCB0aGUgbmV4dCBsaW5lIGlmIHlvdSBrbm93IGV4YWN0bHkgd2hhdCBBY2NvdW50IGFuZCBSZWdpb24geW91XG4gICAqIHdhbnQgdG8gZGVwbG95IHRoZSBzdGFjayB0by4gKi9cbiAgLy8gZW52OiB7IGFjY291bnQ6ICcxMjM0NTY3ODkwMTInLCByZWdpb246ICd1cy1lYXN0LTEnIH0sXG5cbiAgLyogRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL2xhdGVzdC9ndWlkZS9lbnZpcm9ubWVudHMuaHRtbCAqL1xufSk7Il19 -------------------------------------------------------------------------------- /cdkapp/bin/cdkapp.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import 'source-map-support/register'; 3 | import * as cdk from 'aws-cdk-lib'; 4 | import { CdkappStack } from '../lib/cdkapp-stack'; 5 | 6 | const app = new cdk.App(); 7 | new CdkappStack(app, 'CdkappStack', { 8 | /* If you don't specify 'env', this stack will be environment-agnostic. 9 | * Account/Region-dependent features and context lookups will not work, 10 | * but a single synthesized template can be deployed anywhere. */ 11 | 12 | /* Uncomment the next line to specialize this stack for the AWS Account 13 | * and Region that are implied by the current CLI configuration. */ 14 | // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, 15 | 16 | /* Uncomment the next line if you know exactly what Account and Region you 17 | * want to deploy the stack to. */ 18 | // env: { account: '123456789012', region: 'us-east-1' }, 19 | 20 | /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */ 21 | }); -------------------------------------------------------------------------------- /cdkapp/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node --prefer-ts-exts bin/cdkapp.ts", 3 | "watch": { 4 | "include": [ 5 | "**" 6 | ], 7 | "exclude": [ 8 | "README.md", 9 | "cdk*.json", 10 | "**/*.d.ts", 11 | "**/*.js", 12 | "tsconfig.json", 13 | "package*.json", 14 | "yarn.lock", 15 | "node_modules", 16 | "test" 17 | ] 18 | }, 19 | "context": { 20 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, 21 | "@aws-cdk/core:stackRelativeExports": true, 22 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, 23 | "@aws-cdk/aws-lambda:recognizeVersionProps": true, 24 | "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true, 25 | "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, 26 | "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, 27 | "@aws-cdk/core:target-partitions": [ 28 | "aws", 29 | "aws-cn" 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cdkapp/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | roots: ['/test'], 4 | testMatch: ['**/*.test.ts'], 5 | transform: { 6 | '^.+\\.tsx?$': 'ts-jest' 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /cdkapp/lib/cdkapp-stack.d.ts: -------------------------------------------------------------------------------- 1 | import { Stack, StackProps } from 'aws-cdk-lib'; 2 | import { Construct } from 'constructs'; 3 | export declare class CdkappStack extends Stack { 4 | constructor(scope: Construct, id: string, props?: StackProps); 5 | } 6 | -------------------------------------------------------------------------------- /cdkapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cdk", 3 | "version": "0.1.0", 4 | "bin": { 5 | "cdk": "bin/cdk.js" 6 | }, 7 | "scripts": { 8 | "build": "tsc", 9 | "watch": "tsc -w", 10 | "test": "jest", 11 | "cdk": "cdk" 12 | }, 13 | "devDependencies": { 14 | "@types/jest": "^29.5.12", 15 | "@types/node": "22.1.0", 16 | "@types/prettier": "2.7.3", 17 | "jest": "^29.7.0", 18 | "ts-jest": "^29.2.4", 19 | "aws-cdk": "2.151.0", 20 | "ts-node": "^10.9.2", 21 | "typescript": "~5.5.4" 22 | }, 23 | "dependencies": { 24 | "aws-cdk-lib": "2.151.0", 25 | "constructs": "^10.3.0", 26 | "source-map-support": "^0.5.21" 27 | } 28 | } -------------------------------------------------------------------------------- /cdkapp/test/cdkapp.test.d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-spring-boot-optimization/d952ae738cc5826e4bfbcc4167b4b31d3330f1dd/cdkapp/test/cdkapp.test.d.ts -------------------------------------------------------------------------------- /cdkapp/test/cdkapp.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // import * as cdk from 'aws-cdk-lib'; 3 | // import { Template } from 'aws-cdk-lib/assertions'; 4 | // import * as Cdkapp from '../lib/cdkapp-stack'; 5 | // example test. To run these tests, uncomment this file along with the 6 | // example resource in lib/cdkapp-stack.ts 7 | test('SQS Queue Created', () => { 8 | // const app = new cdk.App(); 9 | // // WHEN 10 | // const stack = new Cdkapp.CdkappStack(app, 'MyTestStack'); 11 | // // THEN 12 | // const template = Template.fromStack(stack); 13 | // template.hasResourceProperties('AWS::SQS::Queue', { 14 | // VisibilityTimeout: 300 15 | // }); 16 | }); 17 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrYXBwLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjZGthcHAudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsc0NBQXNDO0FBQ3RDLHFEQUFxRDtBQUNyRCxpREFBaUQ7QUFFakQsdUVBQXVFO0FBQ3ZFLDBDQUEwQztBQUMxQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxFQUFFO0lBQy9CLCtCQUErQjtJQUMvQixjQUFjO0lBQ2QsOERBQThEO0lBQzlELGNBQWM7SUFDZCxnREFBZ0Q7SUFFaEQsd0RBQXdEO0lBQ3hELDZCQUE2QjtJQUM3QixRQUFRO0FBQ1IsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBpbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuLy8gaW1wb3J0IHsgVGVtcGxhdGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hc3NlcnRpb25zJztcbi8vIGltcG9ydCAqIGFzIENka2FwcCBmcm9tICcuLi9saWIvY2RrYXBwLXN0YWNrJztcblxuLy8gZXhhbXBsZSB0ZXN0LiBUbyBydW4gdGhlc2UgdGVzdHMsIHVuY29tbWVudCB0aGlzIGZpbGUgYWxvbmcgd2l0aCB0aGVcbi8vIGV4YW1wbGUgcmVzb3VyY2UgaW4gbGliL2Nka2FwcC1zdGFjay50c1xudGVzdCgnU1FTIFF1ZXVlIENyZWF0ZWQnLCAoKSA9PiB7XG4vLyAgIGNvbnN0IGFwcCA9IG5ldyBjZGsuQXBwKCk7XG4vLyAgICAgLy8gV0hFTlxuLy8gICBjb25zdCBzdGFjayA9IG5ldyBDZGthcHAuQ2RrYXBwU3RhY2soYXBwLCAnTXlUZXN0U3RhY2snKTtcbi8vICAgICAvLyBUSEVOXG4vLyAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuLy8gICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6U1FTOjpRdWV1ZScsIHtcbi8vICAgICBWaXNpYmlsaXR5VGltZW91dDogMzAwXG4vLyAgIH0pO1xufSk7XG4iXX0= -------------------------------------------------------------------------------- /cdkapp/test/cdkapp.test.ts: -------------------------------------------------------------------------------- 1 | // import * as cdk from 'aws-cdk-lib'; 2 | // import { Template } from 'aws-cdk-lib/assertions'; 3 | // import * as Cdkapp from '../lib/cdkapp-stack'; 4 | 5 | // example test. To run these tests, uncomment this file along with the 6 | // example resource in lib/cdkapp-stack.ts 7 | test('SQS Queue Created', () => { 8 | // const app = new cdk.App(); 9 | // // WHEN 10 | // const stack = new Cdkapp.CdkappStack(app, 'MyTestStack'); 11 | // // THEN 12 | // const template = Template.fromStack(stack); 13 | 14 | // template.hasResourceProperties('AWS::SQS::Queue', { 15 | // VisibilityTimeout: 300 16 | // }); 17 | }); 18 | -------------------------------------------------------------------------------- /cdkapp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": [ 6 | "es2018" 7 | ], 8 | "declaration": true, 9 | "strict": true, 10 | "noImplicitAny": true, 11 | "strictNullChecks": true, 12 | "noImplicitThis": true, 13 | "alwaysStrict": true, 14 | "noUnusedLocals": false, 15 | "noUnusedParameters": false, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": false, 18 | "inlineSourceMap": true, 19 | "inlineSources": true, 20 | "experimentalDecorators": true, 21 | "strictPropertyInitialization": false, 22 | "typeRoots": [ 23 | "./node_modules/@types" 24 | ] 25 | }, 26 | "exclude": [ 27 | "node_modules", 28 | "cdk.out" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | custom-jre/ -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lts/ubuntu:22.04 AS builder 2 | LABEL maintainer="Sascha Möllering " 3 | 4 | RUN apt-get update --fix-missing && apt-get install zip curl -y 5 | 6 | RUN \ 7 | curl -s "https://get.sdkman.io" | bash; \ 8 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 9 | sdk install java 17.0.5-amzn; \ 10 | sdk install maven;" 11 | 12 | COPY ./pom.xml ./pom.xml 13 | COPY src ./src/ 14 | 15 | ENV MAVEN_OPTS='-Xmx6g' 16 | 17 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && mvn -Dmaven.test.skip=true clean package && cd target && unzip CustomerService-0.0.1.jar" 18 | 19 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && jdeps --ignore-missing-deps \ 20 | --multi-release 17 --print-module-deps \ 21 | --class-path target/BOOT-INF/lib/* \ 22 | target/CustomerService-0.0.1.jar > jre-deps.info" 23 | 24 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && export JAVA_TOOL_OPTIONS=\"-Djdk.lang.Process.launchMechanism=vfork\" && \ 25 | jlink --verbose --compress 2 --strip-java-debug-attributes \ 26 | --no-header-files --no-man-pages --output custom-jre \ 27 | --add-modules $(cat jre-deps.info)" 28 | 29 | FROM public.ecr.aws/lts/ubuntu:22.04 30 | RUN addgroup --system spring && adduser --system spring --ingroup spring 31 | USER spring:spring 32 | COPY --from=builder target/CustomerService-0.0.1.jar CustomerService-0.0.1.jar 33 | COPY --from=builder custom-jre custom-jre 34 | 35 | EXPOSE 8080 36 | CMD ["./custom-jre/bin/java","-jar","-XX:TieredStopAtLevel=1", "-noverify", "-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] 37 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/Dockerfile-local: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-alpine 2 | RUN addgroup -S spring && adduser -S spring -G spring 3 | USER spring:spring 4 | ARG JAR_FILE=target/*.jar 5 | COPY ${JAR_FILE} CustomerService-0.0.1.jar 6 | ENTRYPOINT ["java","-jar", "-XX:TieredStopAtLevel=1", "-noverify", "-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService; 17 | 18 | import com.amazon.customerService.config.AppConfig; 19 | import com.amazon.customerService.model.metrics.MetricWrapper; 20 | import com.amazon.customerService.service.EcsMetaDataService; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.boot.SpringApplication; 26 | import org.springframework.boot.autoconfigure.SpringBootApplication; 27 | import org.springframework.boot.context.event.ApplicationReadyEvent; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.lang.management.ManagementFactory; 31 | import java.lang.management.RuntimeMXBean; 32 | import java.time.Duration; 33 | import java.time.Instant; 34 | 35 | @Slf4j 36 | @SpringBootApplication 37 | public class CustomerServiceApplication { 38 | 39 | private static Instant startTime; 40 | private static Instant endTime; 41 | 42 | public static void main(String[] args) { 43 | RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); 44 | startTime = Instant.ofEpochMilli(bean.getStartTime()); 45 | SpringApplication.run(CustomerServiceApplication.class, args); 46 | Duration springBootStartTime = Duration.between(startTime, endTime); 47 | 48 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 49 | MetricWrapper metricWrapper = ecsMetaDataService.getMetaData(); 50 | 51 | if (metricWrapper != null) { 52 | metricWrapper.setVersion(AppConfig.APPLICATION_VERSION); 53 | metricWrapper.setSpringBootStartDuration(springBootStartTime); 54 | metricWrapper.setSpringBootReadyTime(endTime); 55 | ObjectMapper mapper = new ObjectMapper() 56 | .registerModule(new JavaTimeModule()); 57 | 58 | try { 59 | String metricsJson = mapper.writeValueAsString(metricWrapper); 60 | log.info("Metrics: " + metricsJson); 61 | } catch (JsonProcessingException e) { 62 | log.error(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | @EventListener(ApplicationReadyEvent.class) 68 | public void startApp() { 69 | endTime = Instant.now(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.config; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 | import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; 23 | import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; 24 | import software.amazon.awssdk.regions.Region; 25 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 26 | 27 | import java.net.URI; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | public final static Integer APPLICATION_VERSION = 4; 33 | 34 | @Value("${amazon.dynamodb.endpoint}") 35 | private String amazonDynamoDBEndpoint; 36 | 37 | @Bean 38 | public DynamoDbClient getDynamoDbClient() { 39 | AwsCredentialsProvider credentialsProvider = 40 | DefaultCredentialsProvider.builder() 41 | .profileName("default") 42 | .build(); 43 | 44 | return DynamoDbClient.builder() 45 | .region(Region.EU_WEST_1) 46 | .credentialsProvider(credentialsProvider) 47 | .endpointOverride(URI.create(amazonDynamoDBEndpoint)) 48 | .build(); 49 | } 50 | 51 | @Bean 52 | public DynamoDbEnhancedClient getDynamoDbEnhancedClient() { 53 | return DynamoDbEnhancedClient.builder() 54 | .dynamoDbClient(getDynamoDbClient()) 55 | .build(); 56 | } 57 | } -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.controller; 17 | 18 | import com.amazon.customerService.exception.CustomerNotFoundException; 19 | import com.amazon.customerService.model.Customer; 20 | import com.amazon.customerService.service.CustomerService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import java.util.List; 26 | 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/api") 30 | public class CustomerController { 31 | 32 | @Autowired 33 | CustomerService customerService; 34 | 35 | @GetMapping("/customers") 36 | List getCustomers() { 37 | return customerService.findAll(); 38 | } 39 | 40 | @GetMapping("/customers/load") 41 | List loadCustomers() { 42 | customerService.loadCustomerData(100); 43 | return customerService.findAll(); 44 | } 45 | 46 | @PostMapping("/customers") 47 | Customer createCustomer(@RequestBody Customer customer) { 48 | return customerService.create(customer); 49 | } 50 | 51 | @GetMapping("/customers/{id}") 52 | Customer getCustomerbyId(@PathVariable String id) { 53 | return customerService.findById(id); 54 | } 55 | 56 | @PutMapping("/customers/{id}") 57 | Customer replaceCustomer(@RequestBody Customer newCustomer, @PathVariable String id) { 58 | Customer customer = customerService.findById(id); 59 | 60 | if (null == customer) { 61 | throw new CustomerNotFoundException(newCustomer.getId()); 62 | } 63 | 64 | customer.setId(newCustomer.getId()); 65 | customer.setRegDate(newCustomer.getRegDate()); 66 | customer.setEmail(newCustomer.getEmail()); 67 | customer.setAccountNumber(newCustomer.getAccountNumber()); 68 | customer.setName(newCustomer.getName()); 69 | 70 | customerService.update(customer); 71 | 72 | return customer; 73 | } 74 | 75 | @DeleteMapping("/customers/{id}") 76 | void deleteCustomerById(@PathVariable String id) { 77 | customerService.deleteById(id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.exception; 17 | 18 | public class CustomerNotFoundException extends RuntimeException { 19 | 20 | public CustomerNotFoundException(String id) { 21 | super("Could not find customer " + id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/ContainerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class ContainerMetric { 23 | private Instant createdAt; 24 | private Instant startedAt; 25 | 26 | public ContainerMetric() { 27 | } 28 | 29 | public ContainerMetric(Instant createdAt, Instant startedAt) { 30 | this.createdAt = createdAt; 31 | this.startedAt = startedAt; 32 | } 33 | 34 | public Duration calculateDuration() { 35 | if (startedAt == null || createdAt == null) 36 | return null; 37 | 38 | Duration duration = Duration.between(createdAt, startedAt); 39 | 40 | return duration; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "ContainerMetric{" + 46 | "createdAt=" + createdAt + 47 | ", startedAt=" + startedAt + 48 | '}'; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object o) { 53 | if (this == o) return true; 54 | if (o == null || getClass() != o.getClass()) return false; 55 | ContainerMetric that = (ContainerMetric) o; 56 | return createdAt.equals(that.createdAt) && startedAt.equals(that.startedAt); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(createdAt, startedAt); 62 | } 63 | 64 | public Instant getCreatedAt() { 65 | return createdAt; 66 | } 67 | 68 | public void setCreatedAt(Instant createdAt) { 69 | this.createdAt = createdAt; 70 | } 71 | 72 | public Instant getStartedAt() { 73 | return startedAt; 74 | } 75 | 76 | public void setStartedAt(Instant startedAt) { 77 | this.startedAt = startedAt; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/MetricWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | 21 | public class MetricWrapper { 22 | 23 | private ContainerMetric containerMetric; 24 | private TaskMetric taskMetric; 25 | private Duration springBootStartDuration; 26 | private Instant springBootReadyTime; 27 | private Integer version; 28 | 29 | public MetricWrapper() { 30 | } 31 | 32 | public MetricWrapper(ContainerMetric containerMetric, TaskMetric taskMetric, Duration springBootStartTime, Instant springBootReadyTime, Integer version) { 33 | this.containerMetric = containerMetric; 34 | this.taskMetric = taskMetric; 35 | this.springBootStartDuration = springBootStartTime; 36 | this.springBootReadyTime = springBootReadyTime; 37 | this.version = version; 38 | } 39 | 40 | public Integer getVersion() { 41 | return version; 42 | } 43 | 44 | public void setVersion(Integer version) { 45 | this.version = version; 46 | } 47 | 48 | public ContainerMetric getContainerMetric() { 49 | return containerMetric; 50 | } 51 | 52 | public void setContainerMetric(ContainerMetric containerMetric) { 53 | this.containerMetric = containerMetric; 54 | } 55 | 56 | public TaskMetric getTaskMetric() { 57 | return taskMetric; 58 | } 59 | 60 | public void setTaskMetric(TaskMetric taskMetric) { 61 | this.taskMetric = taskMetric; 62 | } 63 | 64 | public Instant getSpringBootReadyTime() { 65 | return springBootReadyTime; 66 | } 67 | 68 | public void setSpringBootReadyTime(Instant springBootReadyTime) { 69 | this.springBootReadyTime = springBootReadyTime; 70 | } 71 | 72 | public Duration getSpringBootStartDuration() { 73 | return springBootStartDuration; 74 | } 75 | 76 | public void setSpringBootStartDuration(Duration springBootStartDuration) { 77 | this.springBootStartDuration = springBootStartDuration; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/TaskMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class TaskMetric { 23 | private Instant pullStartedAt; 24 | private Instant pullStoppedAt; 25 | private String taskArn; 26 | 27 | public TaskMetric() { 28 | } 29 | 30 | public TaskMetric(Instant pullStartedAt, Instant pullStoppedAt, String taskArn) { 31 | this.pullStartedAt = pullStartedAt; 32 | this.pullStoppedAt = pullStoppedAt; 33 | this.taskArn = taskArn; 34 | } 35 | 36 | public Instant getPullStartedAt() { 37 | return pullStartedAt; 38 | } 39 | 40 | public void setPullStartedAt(Instant pullStartedAt) { 41 | this.pullStartedAt = pullStartedAt; 42 | } 43 | 44 | public Instant getPullStoppedAt() { 45 | return pullStoppedAt; 46 | } 47 | 48 | public void setPullStoppedAt(Instant pullStoppedAt) { 49 | this.pullStoppedAt = pullStoppedAt; 50 | } 51 | 52 | public Duration calculateDuration() { 53 | if (pullStartedAt == null || pullStoppedAt == null) 54 | return null; 55 | 56 | Duration duration = Duration.between(pullStartedAt, pullStoppedAt); 57 | 58 | return duration; 59 | } 60 | 61 | public String getTaskArn() { 62 | return taskArn; 63 | } 64 | 65 | public void setTaskArn(String taskArn) { 66 | this.taskArn = taskArn; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object o) { 71 | if (this == o) return true; 72 | if (o == null || getClass() != o.getClass()) return false; 73 | TaskMetric that = (TaskMetric) o; 74 | return taskArn.equals(that.taskArn); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | return Objects.hash(taskArn); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "TaskMetric{" + 85 | "pullStartedAt=" + pullStartedAt + 86 | ", pullStoppedAt=" + pullStoppedAt + 87 | ", taskArn='" + taskArn + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/java/com/amazon/customerService/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.Customer; 19 | import com.amazon.customerService.repository.CustomerRepository; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.sql.Date; 25 | import java.time.Instant; 26 | import java.util.List; 27 | import java.util.Random; 28 | import java.util.UUID; 29 | 30 | @Service 31 | public class CustomerService { 32 | 33 | @Autowired 34 | CustomerRepository customerRepository; 35 | 36 | public List findAll() { 37 | return customerRepository.findAll(); 38 | } 39 | 40 | public Customer findById(String id) { 41 | return customerRepository.findById(id); 42 | } 43 | 44 | public Customer create(Customer customer) { 45 | return customerRepository.save(customer); 46 | } 47 | 48 | public Customer update(Customer customer) { 49 | return customerRepository.save(customer); 50 | } 51 | 52 | public void deleteById(String id) { 53 | customerRepository.deleteById(id); 54 | } 55 | 56 | public void loadCustomerData(int count) { 57 | 58 | for (int i = 0; i < count; i++) { 59 | String generatedString = RandomStringUtils.randomAlphabetic(10); 60 | 61 | Customer cust = new Customer(); 62 | cust.setName(generatedString); 63 | cust.setId(UUID.randomUUID().toString()); 64 | cust.setRegDate(Date.from(Instant.now())); 65 | cust.setEmail(generatedString + "@test.com"); 66 | 67 | Random rnd = new Random(); 68 | int number = rnd.nextInt(999999); 69 | 70 | cust.setAccountNumber(String.format("%06d", number)); 71 | 72 | customerRepository.save(cust); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=http://localhost:8000/ 2 | logging.level.root=DEBUG 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=https://dynamodb.eu-west-1.amazonaws.com 2 | logging.level.root=INFO 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/test/resources/container_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "DockerId": "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66", 3 | "Name": "curl", 4 | "DockerName": "ecs-curltest-24-curl-cca48e8dcadd97805600", 5 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 6 | "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", 7 | "Labels": { 8 | "com.amazonaws.ecs.cluster": "default", 9 | "com.amazonaws.ecs.container-name": "curl", 10 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/8f03e41243824aea923aca126495f665", 11 | "com.amazonaws.ecs.task-definition-family": "curltest", 12 | "com.amazonaws.ecs.task-definition-version": "24" 13 | }, 14 | "DesiredStatus": "RUNNING", 15 | "KnownStatus": "RUNNING", 16 | "Limits": { 17 | "CPU": 10, 18 | "Memory": 128 19 | }, 20 | "CreatedAt": "2020-10-02T00:15:07.620912337Z", 21 | "StartedAt": "2020-10-02T00:15:08.062559351Z", 22 | "Type": "NORMAL", 23 | "LogDriver": "awslogs", 24 | "LogOptions": { 25 | "awslogs-create-group": "true", 26 | "awslogs-group": "/ecs/metadata", 27 | "awslogs-region": "us-west-2", 28 | "awslogs-stream": "ecs/curl/8f03e41243824aea923aca126495f665" 29 | }, 30 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9", 31 | "Networks": [ 32 | { 33 | "NetworkMode": "awsvpc", 34 | "IPv4Addresses": [ 35 | "10.0.2.100" 36 | ], 37 | "AttachmentIndex": 0, 38 | "MACAddress": "0e:9e:32:c7:48:85", 39 | "IPv4SubnetCIDRBlock": "10.0.2.0/24", 40 | "PrivateDNSName": "ip-10-0-2-100.us-west-2.compute.internal", 41 | "SubnetGatewayIpv4Address": "10.0.2.1/24" 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /custom-jre-java-optimizations-arm/CustomerService/src/test/resources/task_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "Cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 3 | "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 4 | "Family": "curltest", 5 | "Revision": "3", 6 | "DesiredStatus": "RUNNING", 7 | "KnownStatus": "RUNNING", 8 | "Limits": { 9 | "CPU": 0.25, 10 | "Memory": 512 11 | }, 12 | "PullStartedAt": "2020-10-08T20:47:16.053330955Z", 13 | "PullStoppedAt": "2020-10-08T20:47:19.592684631Z", 14 | "AvailabilityZone": "us-west-2a", 15 | "Containers": [ 16 | { 17 | "DockerId": "e9028f8d5d8e4f258373e7b93ce9a3c3-2495160603", 18 | "Name": "curl", 19 | "DockerName": "curl", 20 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 21 | "ImageID": "sha256:25f3695bedfb454a50f12d127839a68ad3caf91e451c1da073db34c542c4d2cb", 22 | "Labels": { 23 | "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 24 | "com.amazonaws.ecs.container-name": "curl", 25 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 26 | "com.amazonaws.ecs.task-definition-family": "curltest", 27 | "com.amazonaws.ecs.task-definition-version": "3" 28 | }, 29 | "DesiredStatus": "RUNNING", 30 | "KnownStatus": "RUNNING", 31 | "Limits": { 32 | "CPU": 10, 33 | "Memory": 128 34 | }, 35 | "CreatedAt": "2020-10-08T20:47:20.567813946Z", 36 | "StartedAt": "2020-10-08T20:47:20.567813946Z", 37 | "Type": "NORMAL", 38 | "Networks": [ 39 | { 40 | "NetworkMode": "awsvpc", 41 | "IPv4Addresses": [ 42 | "192.0.2.3" 43 | ], 44 | "IPv6Addresses": [ 45 | "2001:dB8:10b:1a00:32bf:a372:d80f:e958" 46 | ], 47 | "AttachmentIndex": 0, 48 | "MACAddress": "02:b7:20:19:72:39", 49 | "IPv4SubnetCIDRBlock": "192.0.2.0/24", 50 | "IPv6SubnetCIDRBlock": "2600:1f13:10b:1a00::/64", 51 | "DomainNameServers": [ 52 | "192.0.2.2" 53 | ], 54 | "DomainNameSearchList": [ 55 | "us-west-2.compute.internal" 56 | ], 57 | "PrivateDNSName": "ip-172-31-30-173.us-west-2.compute.internal", 58 | "SubnetGatewayIpv4Address": "192.0.2.0/24" 59 | } 60 | ], 61 | "ClockDrift": { 62 | "ClockErrorBound": 0.5458234999999999, 63 | "ReferenceTimestamp": "2021-09-07T16:57:44Z", 64 | "ClockSynchronizationStatus": "SYNCHRONIZED" 65 | }, 66 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/1bdcca8b-f905-4ee6-885c-4064cb70f6e6", 67 | "LogOptions": { 68 | "awslogs-create-group": "true", 69 | "awslogs-group": "/ecs/containerlogs", 70 | "awslogs-region": "us-west-2", 71 | "awslogs-stream": "ecs/curl/e9028f8d5d8e4f258373e7b93ce9a3c3" 72 | }, 73 | "LogDriver": "awslogs" 74 | } 75 | ], 76 | "LaunchType": "FARGATE" 77 | } -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | custom-jre/ -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lts/ubuntu:22.04 AS builder 2 | LABEL maintainer="Sascha Möllering " 3 | 4 | RUN apt-get update --fix-missing && apt-get install zip curl -y 5 | 6 | RUN \ 7 | curl -s "https://get.sdkman.io" | bash; \ 8 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 9 | sdk install java 17.0.5-amzn; \ 10 | sdk install maven;" 11 | 12 | COPY ./pom.xml ./pom.xml 13 | COPY src ./src/ 14 | 15 | ENV MAVEN_OPTS='-Xmx6g' 16 | 17 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && mvn -Dmaven.test.skip=true clean package && cd target && unzip CustomerService-0.0.1.jar" 18 | 19 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && jdeps --ignore-missing-deps \ 20 | --multi-release 17 --print-module-deps \ 21 | --class-path target/BOOT-INF/lib/* \ 22 | target/CustomerService-0.0.1.jar > jre-deps.info" 23 | 24 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && export JAVA_TOOL_OPTIONS=\"-Djdk.lang.Process.launchMechanism=vfork\" && \ 25 | jlink --verbose --compress 2 --strip-java-debug-attributes \ 26 | --no-header-files --no-man-pages --output custom-jre \ 27 | --add-modules $(cat jre-deps.info)" 28 | 29 | FROM public.ecr.aws/lts/ubuntu:22.04 30 | RUN addgroup --system spring && adduser --system spring --ingroup spring 31 | USER spring:spring 32 | COPY --from=builder target/CustomerService-0.0.1.jar CustomerService-0.0.1.jar 33 | COPY --from=builder custom-jre custom-jre 34 | 35 | EXPOSE 8080 36 | CMD ["./custom-jre/bin/java","-jar","-XX:TieredStopAtLevel=1", "-noverify", "-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] 37 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/Dockerfile-local: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-alpine 2 | RUN addgroup -S spring && adduser -S spring -G spring 3 | USER spring:spring 4 | ARG JAR_FILE=target/*.jar 5 | COPY ${JAR_FILE} CustomerService-0.0.1.jar 6 | ENTRYPOINT ["java","-jar", "-XX:TieredStopAtLevel=1", "-noverify", "-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService; 17 | 18 | import com.amazon.customerService.config.AppConfig; 19 | import com.amazon.customerService.model.metrics.MetricWrapper; 20 | import com.amazon.customerService.service.EcsMetaDataService; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.boot.SpringApplication; 26 | import org.springframework.boot.autoconfigure.SpringBootApplication; 27 | import org.springframework.boot.context.event.ApplicationReadyEvent; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.lang.management.ManagementFactory; 31 | import java.lang.management.RuntimeMXBean; 32 | import java.time.Duration; 33 | import java.time.Instant; 34 | 35 | @Slf4j 36 | @SpringBootApplication 37 | public class CustomerServiceApplication { 38 | 39 | private static Instant startTime; 40 | private static Instant endTime; 41 | 42 | public static void main(String[] args) { 43 | RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); 44 | startTime = Instant.ofEpochMilli(bean.getStartTime()); 45 | SpringApplication.run(CustomerServiceApplication.class, args); 46 | Duration springBootStartTime = Duration.between(startTime, endTime); 47 | 48 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 49 | MetricWrapper metricWrapper = ecsMetaDataService.getMetaData(); 50 | 51 | if (metricWrapper != null) { 52 | metricWrapper.setVersion(AppConfig.APPLICATION_VERSION); 53 | metricWrapper.setSpringBootStartDuration(springBootStartTime); 54 | metricWrapper.setSpringBootReadyTime(endTime); 55 | ObjectMapper mapper = new ObjectMapper() 56 | .registerModule(new JavaTimeModule()); 57 | 58 | try { 59 | String metricsJson = mapper.writeValueAsString(metricWrapper); 60 | log.info("Metrics: " + metricsJson); 61 | } catch (JsonProcessingException e) { 62 | log.error(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | @EventListener(ApplicationReadyEvent.class) 68 | public void startApp() { 69 | endTime = Instant.now(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.config; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 | import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; 23 | import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; 24 | import software.amazon.awssdk.regions.Region; 25 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 26 | 27 | import java.net.URI; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | public final static Integer APPLICATION_VERSION = 3; 33 | 34 | @Value("${amazon.dynamodb.endpoint}") 35 | private String amazonDynamoDBEndpoint; 36 | 37 | @Bean 38 | public DynamoDbClient getDynamoDbClient() { 39 | AwsCredentialsProvider credentialsProvider = 40 | DefaultCredentialsProvider.builder() 41 | .profileName("default") 42 | .build(); 43 | 44 | return DynamoDbClient.builder() 45 | .region(Region.EU_WEST_1) 46 | .credentialsProvider(credentialsProvider) 47 | .endpointOverride(URI.create(amazonDynamoDBEndpoint)) 48 | .build(); 49 | } 50 | 51 | @Bean 52 | public DynamoDbEnhancedClient getDynamoDbEnhancedClient() { 53 | return DynamoDbEnhancedClient.builder() 54 | .dynamoDbClient(getDynamoDbClient()) 55 | .build(); 56 | } 57 | } -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.controller; 17 | 18 | import com.amazon.customerService.exception.CustomerNotFoundException; 19 | import com.amazon.customerService.model.Customer; 20 | import com.amazon.customerService.service.CustomerService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import java.util.List; 26 | 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/api") 30 | public class CustomerController { 31 | 32 | @Autowired 33 | CustomerService customerService; 34 | 35 | @GetMapping("/customers") 36 | List getCustomers() { 37 | return customerService.findAll(); 38 | } 39 | 40 | @GetMapping("/customers/load") 41 | List loadCustomers() { 42 | customerService.loadCustomerData(100); 43 | return customerService.findAll(); 44 | } 45 | 46 | @PostMapping("/customers") 47 | Customer createCustomer(@RequestBody Customer customer) { 48 | return customerService.create(customer); 49 | } 50 | 51 | @GetMapping("/customers/{id}") 52 | Customer getCustomerbyId(@PathVariable String id) { 53 | return customerService.findById(id); 54 | } 55 | 56 | @PutMapping("/customers/{id}") 57 | Customer replaceCustomer(@RequestBody Customer newCustomer, @PathVariable String id) { 58 | Customer customer = customerService.findById(id); 59 | 60 | if (null == customer) { 61 | throw new CustomerNotFoundException(newCustomer.getId()); 62 | } 63 | 64 | customer.setId(newCustomer.getId()); 65 | customer.setRegDate(newCustomer.getRegDate()); 66 | customer.setEmail(newCustomer.getEmail()); 67 | customer.setAccountNumber(newCustomer.getAccountNumber()); 68 | customer.setName(newCustomer.getName()); 69 | 70 | customerService.update(customer); 71 | 72 | return customer; 73 | } 74 | 75 | @DeleteMapping("/customers/{id}") 76 | void deleteCustomerById(@PathVariable String id) { 77 | customerService.deleteById(id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.exception; 17 | 18 | public class CustomerNotFoundException extends RuntimeException { 19 | 20 | public CustomerNotFoundException(String id) { 21 | super("Could not find customer " + id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/model/metrics/ContainerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class ContainerMetric { 23 | private Instant createdAt; 24 | private Instant startedAt; 25 | 26 | public ContainerMetric() { 27 | } 28 | 29 | public ContainerMetric(Instant createdAt, Instant startedAt) { 30 | this.createdAt = createdAt; 31 | this.startedAt = startedAt; 32 | } 33 | 34 | public Duration calculateDuration() { 35 | if (startedAt == null || createdAt == null) 36 | return null; 37 | 38 | Duration duration = Duration.between(createdAt, startedAt); 39 | 40 | return duration; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "ContainerMetric{" + 46 | "createdAt=" + createdAt + 47 | ", startedAt=" + startedAt + 48 | '}'; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object o) { 53 | if (this == o) return true; 54 | if (o == null || getClass() != o.getClass()) return false; 55 | ContainerMetric that = (ContainerMetric) o; 56 | return createdAt.equals(that.createdAt) && startedAt.equals(that.startedAt); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(createdAt, startedAt); 62 | } 63 | 64 | public Instant getCreatedAt() { 65 | return createdAt; 66 | } 67 | 68 | public void setCreatedAt(Instant createdAt) { 69 | this.createdAt = createdAt; 70 | } 71 | 72 | public Instant getStartedAt() { 73 | return startedAt; 74 | } 75 | 76 | public void setStartedAt(Instant startedAt) { 77 | this.startedAt = startedAt; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/model/metrics/MetricWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | 21 | public class MetricWrapper { 22 | 23 | private ContainerMetric containerMetric; 24 | private TaskMetric taskMetric; 25 | private Duration springBootStartDuration; 26 | private Instant springBootReadyTime; 27 | private Integer version; 28 | 29 | public MetricWrapper() { 30 | } 31 | 32 | public MetricWrapper(ContainerMetric containerMetric, TaskMetric taskMetric, Duration springBootStartTime, Instant springBootReadyTime, Integer version) { 33 | this.containerMetric = containerMetric; 34 | this.taskMetric = taskMetric; 35 | this.springBootStartDuration = springBootStartTime; 36 | this.springBootReadyTime = springBootReadyTime; 37 | this.version = version; 38 | } 39 | 40 | public Integer getVersion() { 41 | return version; 42 | } 43 | 44 | public void setVersion(Integer version) { 45 | this.version = version; 46 | } 47 | 48 | public ContainerMetric getContainerMetric() { 49 | return containerMetric; 50 | } 51 | 52 | public void setContainerMetric(ContainerMetric containerMetric) { 53 | this.containerMetric = containerMetric; 54 | } 55 | 56 | public TaskMetric getTaskMetric() { 57 | return taskMetric; 58 | } 59 | 60 | public void setTaskMetric(TaskMetric taskMetric) { 61 | this.taskMetric = taskMetric; 62 | } 63 | 64 | public Instant getSpringBootReadyTime() { 65 | return springBootReadyTime; 66 | } 67 | 68 | public void setSpringBootReadyTime(Instant springBootReadyTime) { 69 | this.springBootReadyTime = springBootReadyTime; 70 | } 71 | 72 | public Duration getSpringBootStartDuration() { 73 | return springBootStartDuration; 74 | } 75 | 76 | public void setSpringBootStartDuration(Duration springBootStartDuration) { 77 | this.springBootStartDuration = springBootStartDuration; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/model/metrics/TaskMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class TaskMetric { 23 | private Instant pullStartedAt; 24 | private Instant pullStoppedAt; 25 | private String taskArn; 26 | 27 | public TaskMetric() { 28 | } 29 | 30 | public TaskMetric(Instant pullStartedAt, Instant pullStoppedAt, String taskArn) { 31 | this.pullStartedAt = pullStartedAt; 32 | this.pullStoppedAt = pullStoppedAt; 33 | this.taskArn = taskArn; 34 | } 35 | 36 | public Instant getPullStartedAt() { 37 | return pullStartedAt; 38 | } 39 | 40 | public void setPullStartedAt(Instant pullStartedAt) { 41 | this.pullStartedAt = pullStartedAt; 42 | } 43 | 44 | public Instant getPullStoppedAt() { 45 | return pullStoppedAt; 46 | } 47 | 48 | public void setPullStoppedAt(Instant pullStoppedAt) { 49 | this.pullStoppedAt = pullStoppedAt; 50 | } 51 | 52 | public Duration calculateDuration() { 53 | if (pullStartedAt == null || pullStoppedAt == null) 54 | return null; 55 | 56 | Duration duration = Duration.between(pullStartedAt, pullStoppedAt); 57 | 58 | return duration; 59 | } 60 | 61 | public String getTaskArn() { 62 | return taskArn; 63 | } 64 | 65 | public void setTaskArn(String taskArn) { 66 | this.taskArn = taskArn; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object o) { 71 | if (this == o) return true; 72 | if (o == null || getClass() != o.getClass()) return false; 73 | TaskMetric that = (TaskMetric) o; 74 | return taskArn.equals(that.taskArn); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | return Objects.hash(taskArn); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "TaskMetric{" + 85 | "pullStartedAt=" + pullStartedAt + 86 | ", pullStoppedAt=" + pullStoppedAt + 87 | ", taskArn='" + taskArn + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/java/com/amazon/customerService/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.Customer; 19 | import com.amazon.customerService.repository.CustomerRepository; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.sql.Date; 25 | import java.time.Instant; 26 | import java.util.List; 27 | import java.util.Random; 28 | import java.util.UUID; 29 | 30 | @Service 31 | public class CustomerService { 32 | 33 | @Autowired 34 | CustomerRepository customerRepository; 35 | 36 | public List findAll() { 37 | return customerRepository.findAll(); 38 | } 39 | 40 | public Customer findById(String id) { 41 | return customerRepository.findById(id); 42 | } 43 | 44 | public Customer create(Customer customer) { 45 | return customerRepository.save(customer); 46 | } 47 | 48 | public Customer update(Customer customer) { 49 | return customerRepository.save(customer); 50 | } 51 | 52 | public void deleteById(String id) { 53 | customerRepository.deleteById(id); 54 | } 55 | 56 | public void loadCustomerData(int count) { 57 | 58 | for (int i = 0; i < count; i++) { 59 | String generatedString = RandomStringUtils.randomAlphabetic(10); 60 | 61 | Customer cust = new Customer(); 62 | cust.setName(generatedString); 63 | cust.setId(UUID.randomUUID().toString()); 64 | cust.setRegDate(Date.from(Instant.now())); 65 | cust.setEmail(generatedString + "@test.com"); 66 | 67 | Random rnd = new Random(); 68 | int number = rnd.nextInt(999999); 69 | 70 | cust.setAccountNumber(String.format("%06d", number)); 71 | 72 | customerRepository.save(cust); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=http://localhost:8000/ 2 | logging.level.root=DEBUG 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=https://dynamodb.eu-west-1.amazonaws.com 2 | logging.level.root=INFO 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/test/resources/container_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "DockerId": "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66", 3 | "Name": "curl", 4 | "DockerName": "ecs-curltest-24-curl-cca48e8dcadd97805600", 5 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 6 | "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", 7 | "Labels": { 8 | "com.amazonaws.ecs.cluster": "default", 9 | "com.amazonaws.ecs.container-name": "curl", 10 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/8f03e41243824aea923aca126495f665", 11 | "com.amazonaws.ecs.task-definition-family": "curltest", 12 | "com.amazonaws.ecs.task-definition-version": "24" 13 | }, 14 | "DesiredStatus": "RUNNING", 15 | "KnownStatus": "RUNNING", 16 | "Limits": { 17 | "CPU": 10, 18 | "Memory": 128 19 | }, 20 | "CreatedAt": "2020-10-02T00:15:07.620912337Z", 21 | "StartedAt": "2020-10-02T00:15:08.062559351Z", 22 | "Type": "NORMAL", 23 | "LogDriver": "awslogs", 24 | "LogOptions": { 25 | "awslogs-create-group": "true", 26 | "awslogs-group": "/ecs/metadata", 27 | "awslogs-region": "us-west-2", 28 | "awslogs-stream": "ecs/curl/8f03e41243824aea923aca126495f665" 29 | }, 30 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9", 31 | "Networks": [ 32 | { 33 | "NetworkMode": "awsvpc", 34 | "IPv4Addresses": [ 35 | "10.0.2.100" 36 | ], 37 | "AttachmentIndex": 0, 38 | "MACAddress": "0e:9e:32:c7:48:85", 39 | "IPv4SubnetCIDRBlock": "10.0.2.0/24", 40 | "PrivateDNSName": "ip-10-0-2-100.us-west-2.compute.internal", 41 | "SubnetGatewayIpv4Address": "10.0.2.1/24" 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /custom-jre-java-optimizations/CustomerService/src/test/resources/task_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "Cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 3 | "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 4 | "Family": "curltest", 5 | "Revision": "3", 6 | "DesiredStatus": "RUNNING", 7 | "KnownStatus": "RUNNING", 8 | "Limits": { 9 | "CPU": 0.25, 10 | "Memory": 512 11 | }, 12 | "PullStartedAt": "2020-10-08T20:47:16.053330955Z", 13 | "PullStoppedAt": "2020-10-08T20:47:19.592684631Z", 14 | "AvailabilityZone": "us-west-2a", 15 | "Containers": [ 16 | { 17 | "DockerId": "e9028f8d5d8e4f258373e7b93ce9a3c3-2495160603", 18 | "Name": "curl", 19 | "DockerName": "curl", 20 | "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", 21 | "ImageID": "sha256:25f3695bedfb454a50f12d127839a68ad3caf91e451c1da073db34c542c4d2cb", 22 | "Labels": { 23 | "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", 24 | "com.amazonaws.ecs.container-name": "curl", 25 | "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", 26 | "com.amazonaws.ecs.task-definition-family": "curltest", 27 | "com.amazonaws.ecs.task-definition-version": "3" 28 | }, 29 | "DesiredStatus": "RUNNING", 30 | "KnownStatus": "RUNNING", 31 | "Limits": { 32 | "CPU": 10, 33 | "Memory": 128 34 | }, 35 | "CreatedAt": "2020-10-08T20:47:20.567813946Z", 36 | "StartedAt": "2020-10-08T20:47:20.567813946Z", 37 | "Type": "NORMAL", 38 | "Networks": [ 39 | { 40 | "NetworkMode": "awsvpc", 41 | "IPv4Addresses": [ 42 | "192.0.2.3" 43 | ], 44 | "IPv6Addresses": [ 45 | "2001:dB8:10b:1a00:32bf:a372:d80f:e958" 46 | ], 47 | "AttachmentIndex": 0, 48 | "MACAddress": "02:b7:20:19:72:39", 49 | "IPv4SubnetCIDRBlock": "192.0.2.0/24", 50 | "IPv6SubnetCIDRBlock": "2600:1f13:10b:1a00::/64", 51 | "DomainNameServers": [ 52 | "192.0.2.2" 53 | ], 54 | "DomainNameSearchList": [ 55 | "us-west-2.compute.internal" 56 | ], 57 | "PrivateDNSName": "ip-172-31-30-173.us-west-2.compute.internal", 58 | "SubnetGatewayIpv4Address": "192.0.2.0/24" 59 | } 60 | ], 61 | "ClockDrift": { 62 | "ClockErrorBound": 0.5458234999999999, 63 | "ReferenceTimestamp": "2021-09-07T16:57:44Z", 64 | "ClockSynchronizationStatus": "SYNCHRONIZED" 65 | }, 66 | "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/1bdcca8b-f905-4ee6-885c-4064cb70f6e6", 67 | "LogOptions": { 68 | "awslogs-create-group": "true", 69 | "awslogs-group": "/ecs/containerlogs", 70 | "awslogs-region": "us-west-2", 71 | "awslogs-stream": "ecs/curl/e9028f8d5d8e4f258373e7b93ce9a3c3" 72 | }, 73 | "LogDriver": "awslogs" 74 | } 75 | ], 76 | "LaunchType": "FARGATE" 77 | } -------------------------------------------------------------------------------- /images/SpringBoot_example_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-spring-boot-optimization/d952ae738cc5826e4bfbcc4167b4b31d3330f1dd/images/SpringBoot_example_architecture.png -------------------------------------------------------------------------------- /images/cloud9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-spring-boot-optimization/d952ae738cc5826e4bfbcc4167b4b31d3330f1dd/images/cloud9.png -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | custom-jre/ -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/graalvm/graalvm-ce:22.3.0 AS build-aot 2 | LABEL maintainer="Sascha Möllering " 3 | 4 | RUN microdnf install -y unzip zip 5 | 6 | RUN \ 7 | curl -s "https://get.sdkman.io" | bash; \ 8 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 9 | sdk install maven;" 10 | 11 | COPY ./pom.xml ./pom.xml 12 | COPY src ./src/ 13 | 14 | ENV MAVEN_OPTS='-Xmx8g' 15 | 16 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && mvn -Dmaven.test.skip=true clean package -Pnative" 17 | 18 | FROM public.ecr.aws/lts/ubuntu:22.04 19 | RUN addgroup --system spring && adduser --system spring --ingroup spring 20 | USER spring:spring 21 | COPY --from=build-aot /app/target/CustomerService / 22 | EXPOSE 8080 23 | 24 | CMD ["./CustomerService", "-Dspring.profiles.active=prod"] 25 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/Dockerfile-local: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-alpine 2 | RUN addgroup -S spring && adduser -S spring -G spring 3 | USER spring:spring 4 | ARG JAR_FILE=target/*.jar 5 | COPY ${JAR_FILE} CustomerService-0.0.1.jar 6 | ENTRYPOINT ["java","-jar", "-XX:TieredStopAtLevel=1", "-noverify", "-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService; 17 | 18 | import com.amazon.customerService.config.AppConfig; 19 | import com.amazon.customerService.model.metrics.MetricWrapper; 20 | import com.amazon.customerService.service.EcsMetaDataService; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.boot.SpringApplication; 26 | import org.springframework.boot.autoconfigure.SpringBootApplication; 27 | import org.springframework.boot.context.event.ApplicationReadyEvent; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.lang.management.ManagementFactory; 31 | import java.lang.management.RuntimeMXBean; 32 | import java.time.Duration; 33 | import java.time.Instant; 34 | 35 | @Slf4j 36 | @SpringBootApplication 37 | public class CustomerServiceApplication { 38 | 39 | private static Instant startTime; 40 | private static Instant endTime; 41 | 42 | public static void main(String[] args) { 43 | RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); 44 | startTime = Instant.ofEpochMilli(bean.getStartTime()); 45 | SpringApplication.run(CustomerServiceApplication.class, args); 46 | Duration springBootStartTime = Duration.between(startTime, endTime); 47 | 48 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 49 | MetricWrapper metricWrapper = ecsMetaDataService.getMetaData(); 50 | 51 | if (metricWrapper != null) { 52 | metricWrapper.setVersion(AppConfig.APPLICATION_VERSION); 53 | metricWrapper.setSpringBootStartDuration(springBootStartTime); 54 | metricWrapper.setSpringBootReadyTime(endTime); 55 | ObjectMapper mapper = new ObjectMapper() 56 | .registerModule(new JavaTimeModule()); 57 | 58 | try { 59 | String metricsJson = mapper.writeValueAsString(metricWrapper); 60 | log.info("Metrics: " + metricsJson); 61 | } catch (JsonProcessingException e) { 62 | log.error(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | @EventListener(ApplicationReadyEvent.class) 68 | public void startApp() { 69 | endTime = Instant.now(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.config; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 | import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; 23 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 24 | import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; 25 | 26 | import java.net.URI; 27 | 28 | @Configuration 29 | public class AppConfig { 30 | 31 | public final static Integer APPLICATION_VERSION = 6; 32 | 33 | @Value("${amazon.dynamodb.endpoint}") 34 | private String amazonDynamoDBEndpoint; 35 | 36 | @Bean 37 | public DynamoDbClient getDynamoDbClient() { 38 | AwsCredentialsProvider credentialsProvider = 39 | DefaultCredentialsProvider.builder() 40 | .profileName("default") 41 | .build(); 42 | 43 | DynamoDbClientBuilder clientBuilder = DynamoDbClient.builder(); 44 | clientBuilder 45 | .credentialsProvider(credentialsProvider); 46 | if (!amazonDynamoDBEndpoint.isEmpty()) { 47 | clientBuilder.endpointOverride(URI.create(amazonDynamoDBEndpoint)); 48 | } 49 | return clientBuilder.build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.controller; 17 | 18 | import com.amazon.customerService.exception.CustomerNotFoundException; 19 | import com.amazon.customerService.model.Customer; 20 | import com.amazon.customerService.service.CustomerService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import java.util.List; 26 | 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/api") 30 | public class CustomerController { 31 | 32 | @Autowired 33 | CustomerService customerService; 34 | 35 | @GetMapping("/customers") 36 | List getCustomers() { 37 | return customerService.findAll(); 38 | } 39 | 40 | @GetMapping("/customers/load") 41 | List loadCustomers() { 42 | customerService.loadCustomerData(100); 43 | return customerService.findAll(); 44 | } 45 | 46 | @PostMapping("/customers") 47 | Customer createCustomer(@RequestBody Customer customer) { 48 | return customerService.create(customer); 49 | } 50 | 51 | @GetMapping("/customers/{id}") 52 | Customer getCustomerbyId(@PathVariable String id) { 53 | return customerService.findById(id); 54 | } 55 | 56 | @PutMapping("/customers/{id}") 57 | Customer replaceCustomer(@RequestBody Customer newCustomer, @PathVariable String id) { 58 | Customer customer = customerService.findById(id); 59 | 60 | if (null == customer) { 61 | throw new CustomerNotFoundException(newCustomer.getId()); 62 | } 63 | 64 | customer.setId(newCustomer.getId()); 65 | customer.setRegDate(newCustomer.getRegDate()); 66 | customer.setEmail(newCustomer.getEmail()); 67 | customer.setAccountNumber(newCustomer.getAccountNumber()); 68 | customer.setName(newCustomer.getName()); 69 | 70 | customerService.update(customer); 71 | 72 | return customer; 73 | } 74 | 75 | @DeleteMapping("/customers/{id}") 76 | void deleteCustomerById(@PathVariable String id) { 77 | customerService.deleteById(id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.exception; 17 | 18 | public class CustomerNotFoundException extends RuntimeException { 19 | 20 | public CustomerNotFoundException(String id) { 21 | super("Could not find customer " + id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/ContainerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class ContainerMetric { 23 | private Instant createdAt; 24 | private Instant startedAt; 25 | 26 | public ContainerMetric() { 27 | } 28 | 29 | public ContainerMetric(Instant createdAt, Instant startedAt) { 30 | this.createdAt = createdAt; 31 | this.startedAt = startedAt; 32 | } 33 | 34 | public Duration calculateDuration() { 35 | if (startedAt == null || createdAt == null) 36 | return null; 37 | 38 | Duration duration = Duration.between(createdAt, startedAt); 39 | 40 | return duration; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "ContainerMetric{" + 46 | "createdAt=" + createdAt + 47 | ", startedAt=" + startedAt + 48 | '}'; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object o) { 53 | if (this == o) return true; 54 | if (o == null || getClass() != o.getClass()) return false; 55 | ContainerMetric that = (ContainerMetric) o; 56 | return createdAt.equals(that.createdAt) && startedAt.equals(that.startedAt); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(createdAt, startedAt); 62 | } 63 | 64 | public Instant getCreatedAt() { 65 | return createdAt; 66 | } 67 | 68 | public void setCreatedAt(Instant createdAt) { 69 | this.createdAt = createdAt; 70 | } 71 | 72 | public Instant getStartedAt() { 73 | return startedAt; 74 | } 75 | 76 | public void setStartedAt(Instant startedAt) { 77 | this.startedAt = startedAt; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/MetricWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | 21 | public class MetricWrapper { 22 | 23 | private ContainerMetric containerMetric; 24 | private TaskMetric taskMetric; 25 | private Duration springBootStartDuration; 26 | private Instant springBootReadyTime; 27 | private Integer version; 28 | 29 | public MetricWrapper() { 30 | } 31 | 32 | public MetricWrapper(ContainerMetric containerMetric, TaskMetric taskMetric, Duration springBootStartTime, Instant springBootReadyTime, Integer version) { 33 | this.containerMetric = containerMetric; 34 | this.taskMetric = taskMetric; 35 | this.springBootStartDuration = springBootStartTime; 36 | this.springBootReadyTime = springBootReadyTime; 37 | this.version = version; 38 | } 39 | 40 | public Integer getVersion() { 41 | return version; 42 | } 43 | 44 | public void setVersion(Integer version) { 45 | this.version = version; 46 | } 47 | 48 | public ContainerMetric getContainerMetric() { 49 | return containerMetric; 50 | } 51 | 52 | public void setContainerMetric(ContainerMetric containerMetric) { 53 | this.containerMetric = containerMetric; 54 | } 55 | 56 | public TaskMetric getTaskMetric() { 57 | return taskMetric; 58 | } 59 | 60 | public void setTaskMetric(TaskMetric taskMetric) { 61 | this.taskMetric = taskMetric; 62 | } 63 | 64 | public Instant getSpringBootReadyTime() { 65 | return springBootReadyTime; 66 | } 67 | 68 | public void setSpringBootReadyTime(Instant springBootReadyTime) { 69 | this.springBootReadyTime = springBootReadyTime; 70 | } 71 | 72 | public Duration getSpringBootStartDuration() { 73 | return springBootStartDuration; 74 | } 75 | 76 | public void setSpringBootStartDuration(Duration springBootStartDuration) { 77 | this.springBootStartDuration = springBootStartDuration; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/model/metrics/TaskMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class TaskMetric { 23 | private Instant pullStartedAt; 24 | private Instant pullStoppedAt; 25 | private String taskArn; 26 | 27 | public TaskMetric() { 28 | } 29 | 30 | public TaskMetric(Instant pullStartedAt, Instant pullStoppedAt, String taskArn) { 31 | this.pullStartedAt = pullStartedAt; 32 | this.pullStoppedAt = pullStoppedAt; 33 | this.taskArn = taskArn; 34 | } 35 | 36 | public Instant getPullStartedAt() { 37 | return pullStartedAt; 38 | } 39 | 40 | public void setPullStartedAt(Instant pullStartedAt) { 41 | this.pullStartedAt = pullStartedAt; 42 | } 43 | 44 | public Instant getPullStoppedAt() { 45 | return pullStoppedAt; 46 | } 47 | 48 | public void setPullStoppedAt(Instant pullStoppedAt) { 49 | this.pullStoppedAt = pullStoppedAt; 50 | } 51 | 52 | public Duration calculateDuration() { 53 | if (pullStartedAt == null || pullStoppedAt == null) 54 | return null; 55 | 56 | Duration duration = Duration.between(pullStartedAt, pullStoppedAt); 57 | 58 | return duration; 59 | } 60 | 61 | public String getTaskArn() { 62 | return taskArn; 63 | } 64 | 65 | public void setTaskArn(String taskArn) { 66 | this.taskArn = taskArn; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object o) { 71 | if (this == o) return true; 72 | if (o == null || getClass() != o.getClass()) return false; 73 | TaskMetric that = (TaskMetric) o; 74 | return taskArn.equals(that.taskArn); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | return Objects.hash(taskArn); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "TaskMetric{" + 85 | "pullStartedAt=" + pullStartedAt + 86 | ", pullStoppedAt=" + pullStoppedAt + 87 | ", taskArn='" + taskArn + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/java/com/amazon/customerService/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.Customer; 19 | import com.amazon.customerService.repository.CustomerRepository; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.sql.Date; 25 | import java.time.Instant; 26 | import java.util.List; 27 | import java.util.Random; 28 | import java.util.UUID; 29 | 30 | @Service 31 | public class CustomerService { 32 | 33 | @Autowired 34 | CustomerRepository customerRepository; 35 | 36 | public List findAll() { 37 | return customerRepository.findAll(); 38 | } 39 | 40 | public Customer findById(String id) { 41 | return customerRepository.findById(id); 42 | } 43 | 44 | public Customer create(Customer customer) { 45 | return customerRepository.save(customer); 46 | } 47 | 48 | public Customer update(Customer customer) { 49 | return customerRepository.save(customer); 50 | } 51 | 52 | public void deleteById(String id) { 53 | customerRepository.deleteById(id); 54 | } 55 | 56 | public void loadCustomerData(int count) { 57 | 58 | for (int i = 0; i < count; i++) { 59 | String generatedString = RandomStringUtils.randomAlphabetic(10); 60 | 61 | Customer cust = new Customer(); 62 | cust.setName(generatedString); 63 | cust.setId(UUID.randomUUID().toString()); 64 | cust.setRegDate(Date.from(Instant.now())); 65 | cust.setEmail(generatedString + "@test.com"); 66 | 67 | Random rnd = new Random(); 68 | int number = rnd.nextInt(999999); 69 | 70 | cust.setAccountNumber(String.format("%06d", number)); 71 | 72 | customerRepository.save(cust); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/resources/META-INF/native-image/predefined-classes-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "agent-extracted", 4 | "classes": [ 5 | ] 6 | } 7 | ] 8 | 9 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/resources/META-INF/native-image/proxy-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "interfaces": [ 4 | "java.lang.reflect.GenericArrayType", 5 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 6 | "java.io.Serializable" 7 | ] 8 | }, 9 | { 10 | "interfaces": [ 11 | "java.lang.reflect.ParameterizedType", 12 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 13 | "java.io.Serializable" 14 | ] 15 | }, 16 | { 17 | "interfaces": [ 18 | "java.lang.reflect.TypeVariable", 19 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 20 | "java.io.Serializable" 21 | ] 22 | }, 23 | { 24 | "interfaces": [ 25 | "java.lang.reflect.WildcardType", 26 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 27 | "java.io.Serializable" 28 | ] 29 | }, 30 | { 31 | "interfaces": [ 32 | "java.util.List", 33 | "org.springframework.aop.SpringProxy", 34 | "org.springframework.aop.framework.Advised", 35 | "org.springframework.core.DecoratingProxy" 36 | ] 37 | }, 38 | { 39 | "interfaces": [ 40 | "org.springframework.boot.actuate.endpoint.annotation.EndpointExtension", 41 | "org.springframework.core.annotation.SynthesizedAnnotation" 42 | ] 43 | }, 44 | { 45 | "interfaces": [ 46 | "org.springframework.boot.context.properties.ConfigurationProperties", 47 | "org.springframework.core.annotation.SynthesizedAnnotation" 48 | ] 49 | }, 50 | { 51 | "interfaces": [ 52 | "org.springframework.context.event.EventListener", 53 | "org.springframework.core.annotation.SynthesizedAnnotation" 54 | ] 55 | }, 56 | { 57 | "interfaces": [ 58 | "org.springframework.stereotype.Controller", 59 | "org.springframework.core.annotation.SynthesizedAnnotation" 60 | ] 61 | }, 62 | { 63 | "interfaces": [ 64 | "org.springframework.web.bind.annotation.ControllerAdvice", 65 | "org.springframework.core.annotation.SynthesizedAnnotation" 66 | ] 67 | }, 68 | { 69 | "interfaces": [ 70 | "org.springframework.web.bind.annotation.RequestMapping", 71 | "org.springframework.core.annotation.SynthesizedAnnotation" 72 | ] 73 | } 74 | ] 75 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/resources/META-INF/native-image/reflect-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "com.amazon.customerService.model.metrics.MetricWrapper", 4 | "allDeclaredFields": true, 5 | "allDeclaredMethods": true, 6 | "allDeclaredConstructors": true, 7 | "allPublicConstructors": true, 8 | "allPublicMethods": true, 9 | "allPublicFields": true 10 | }, 11 | { 12 | "name": "com.amazon.customerService.model.metrics.ContainerMetric", 13 | "allDeclaredFields": true, 14 | "allDeclaredMethods": true, 15 | "allDeclaredConstructors": true, 16 | "allPublicConstructors": true, 17 | "allPublicMethods": true, 18 | "allPublicFields": true 19 | }, 20 | { 21 | "name": "com.amazon.customerService.model.metrics.TaskMetric", 22 | "allDeclaredFields": true, 23 | "allDeclaredMethods": true, 24 | "allDeclaredConstructors": true, 25 | "allPublicConstructors": true, 26 | "allPublicMethods": true, 27 | "allPublicFields": true 28 | } 29 | ] -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/resources/META-INF/native-image/serialization-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "com.amazon.customerService.repository.CustomerRepository$$EnhancerBySpringCGLIB$$2563aeec", 4 | "customTargetConstructorClass": "java.lang.Object" 5 | }, 6 | { 7 | "name": "com.amazon.customerService.service.CustomerService$$EnhancerBySpringCGLIB$$9ed02915", 8 | "customTargetConstructorClass": "java.lang.Object" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=http://localhost:8000/ 2 | logging.level.root=DEBUG 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /spring-native-arm/CustomerService/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=https://dynamodb.eu-west-1.amazonaws.com 2 | logging.level.root=INFO 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | custom-jre/ -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/graalvm/graalvm-ce:22.3.0 AS build-aot 2 | LABEL maintainer="Sascha Möllering " 3 | 4 | RUN microdnf install -y unzip zip 5 | 6 | RUN \ 7 | curl -s "https://get.sdkman.io" | bash; \ 8 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 9 | sdk install maven;" 10 | 11 | COPY ./pom.xml ./pom.xml 12 | COPY src ./src/ 13 | 14 | ENV MAVEN_OPTS='-Xmx8g' 15 | 16 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && mvn -Dmaven.test.skip=true clean package -Pnative && cd target && unzip CustomerService-0.0.1.jar" 17 | 18 | #FROM gcr.io/distroless/static-debian11 19 | 20 | FROM public.ecr.aws/lts/ubuntu:22.04 21 | 22 | COPY --from=build-aot /app/target/CustomerService / 23 | 24 | EXPOSE 8080 25 | #USER nonroot 26 | 27 | CMD ["./CustomerService", "-Dspring.profiles.active=prod"] 28 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/Dockerfile-local: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-alpine 2 | RUN addgroup -S spring && adduser -S spring -G spring 3 | USER spring:spring 4 | ARG JAR_FILE=target/*.jar 5 | COPY ${JAR_FILE} CustomerService-0.0.1.jar 6 | ENTRYPOINT ["java","-jar", "-XX:TieredStopAtLevel=1", "-noverify", "-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService; 17 | 18 | import com.amazon.customerService.config.AppConfig; 19 | import com.amazon.customerService.model.metrics.MetricWrapper; 20 | import com.amazon.customerService.service.EcsMetaDataService; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.boot.SpringApplication; 26 | import org.springframework.boot.autoconfigure.SpringBootApplication; 27 | import org.springframework.boot.context.event.ApplicationReadyEvent; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.lang.management.ManagementFactory; 31 | import java.lang.management.RuntimeMXBean; 32 | import java.time.Duration; 33 | import java.time.Instant; 34 | 35 | @Slf4j 36 | @SpringBootApplication 37 | public class CustomerServiceApplication { 38 | 39 | private static Instant startTime; 40 | private static Instant endTime; 41 | 42 | public static void main(String[] args) { 43 | RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); 44 | startTime = Instant.ofEpochMilli(bean.getStartTime()); 45 | SpringApplication.run(CustomerServiceApplication.class, args); 46 | Duration springBootStartTime = Duration.between(startTime, endTime); 47 | 48 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 49 | MetricWrapper metricWrapper = ecsMetaDataService.getMetaData(); 50 | 51 | if (metricWrapper != null) { 52 | metricWrapper.setVersion(AppConfig.APPLICATION_VERSION); 53 | metricWrapper.setSpringBootStartDuration(springBootStartTime); 54 | metricWrapper.setSpringBootReadyTime(endTime); 55 | ObjectMapper mapper = new ObjectMapper() 56 | .registerModule(new JavaTimeModule()); 57 | 58 | try { 59 | String metricsJson = mapper.writeValueAsString(metricWrapper); 60 | log.info("Metrics: " + metricsJson); 61 | } catch (JsonProcessingException e) { 62 | log.error(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | @EventListener(ApplicationReadyEvent.class) 68 | public void startApp() { 69 | endTime = Instant.now(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.config; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 | import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; 23 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 24 | import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; 25 | 26 | import java.net.URI; 27 | 28 | @Configuration 29 | public class AppConfig { 30 | 31 | public final static Integer APPLICATION_VERSION = 7; 32 | 33 | @Value("${amazon.dynamodb.endpoint}") 34 | private String amazonDynamoDBEndpoint; 35 | 36 | @Bean 37 | public DynamoDbClient getDynamoDbClient() { 38 | AwsCredentialsProvider credentialsProvider = 39 | DefaultCredentialsProvider.builder() 40 | .profileName("default") 41 | .build(); 42 | 43 | DynamoDbClientBuilder clientBuilder = DynamoDbClient.builder(); 44 | clientBuilder 45 | .credentialsProvider(credentialsProvider); 46 | if(!amazonDynamoDBEndpoint.isEmpty()){ 47 | clientBuilder.endpointOverride(URI.create(amazonDynamoDBEndpoint)); 48 | } 49 | return clientBuilder.build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.controller; 17 | 18 | import com.amazon.customerService.exception.CustomerNotFoundException; 19 | import com.amazon.customerService.model.Customer; 20 | import com.amazon.customerService.service.CustomerService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import java.util.List; 26 | 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/api") 30 | public class CustomerController { 31 | 32 | @Autowired 33 | CustomerService customerService; 34 | 35 | @GetMapping("/customers") 36 | List getCustomers() { 37 | return customerService.findAll(); 38 | } 39 | 40 | @GetMapping("/customers/load") 41 | List loadCustomers() { 42 | customerService.loadCustomerData(100); 43 | return customerService.findAll(); 44 | } 45 | 46 | @PostMapping("/customers") 47 | Customer createCustomer(@RequestBody Customer customer) { 48 | return customerService.create(customer); 49 | } 50 | 51 | @GetMapping("/customers/{id}") 52 | Customer getCustomerbyId(@PathVariable String id) { 53 | return customerService.findById(id); 54 | } 55 | 56 | @PutMapping("/customers/{id}") 57 | Customer replaceCustomer(@RequestBody Customer newCustomer, @PathVariable String id) { 58 | Customer customer = customerService.findById(id); 59 | 60 | if (null == customer) { 61 | throw new CustomerNotFoundException(newCustomer.getId()); 62 | } 63 | 64 | customer.setId(newCustomer.getId()); 65 | customer.setRegDate(newCustomer.getRegDate()); 66 | customer.setEmail(newCustomer.getEmail()); 67 | customer.setAccountNumber(newCustomer.getAccountNumber()); 68 | customer.setName(newCustomer.getName()); 69 | 70 | customerService.update(customer); 71 | 72 | return customer; 73 | } 74 | 75 | @DeleteMapping("/customers/{id}") 76 | void deleteCustomerById(@PathVariable String id) { 77 | customerService.deleteById(id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.exception; 17 | 18 | public class CustomerNotFoundException extends RuntimeException { 19 | 20 | public CustomerNotFoundException(String id) { 21 | super("Could not find customer " + id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/model/metrics/ContainerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class ContainerMetric { 23 | private Instant createdAt; 24 | private Instant startedAt; 25 | 26 | public ContainerMetric() {} 27 | 28 | public ContainerMetric(Instant createdAt, Instant startedAt) { 29 | this.createdAt = createdAt; 30 | this.startedAt = startedAt; 31 | } 32 | 33 | public Duration calculateDuration() { 34 | if (startedAt == null || createdAt == null) 35 | return null; 36 | 37 | Duration duration = Duration.between(createdAt, startedAt); 38 | 39 | return duration; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "ContainerMetric{" + 45 | "createdAt=" + createdAt + 46 | ", startedAt=" + startedAt + 47 | '}'; 48 | } 49 | 50 | @Override 51 | public boolean equals(Object o) { 52 | if (this == o) return true; 53 | if (o == null || getClass() != o.getClass()) return false; 54 | ContainerMetric that = (ContainerMetric) o; 55 | return createdAt.equals(that.createdAt) && startedAt.equals(that.startedAt); 56 | } 57 | 58 | @Override 59 | public int hashCode() { 60 | return Objects.hash(createdAt, startedAt); 61 | } 62 | 63 | public Instant getCreatedAt() { 64 | return createdAt; 65 | } 66 | 67 | public void setCreatedAt(Instant createdAt) { 68 | this.createdAt = createdAt; 69 | } 70 | 71 | public Instant getStartedAt() { 72 | return startedAt; 73 | } 74 | 75 | public void setStartedAt(Instant startedAt) { 76 | this.startedAt = startedAt; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/model/metrics/MetricWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | 21 | public class MetricWrapper { 22 | 23 | private ContainerMetric containerMetric; 24 | private TaskMetric taskMetric; 25 | private Duration springBootStartDuration; 26 | private Instant springBootReadyTime; 27 | private Integer version; 28 | 29 | public MetricWrapper() {} 30 | 31 | public MetricWrapper(ContainerMetric containerMetric, TaskMetric taskMetric, Duration springBootStartTime, Instant springBootReadyTime, Integer version) { 32 | this.containerMetric = containerMetric; 33 | this.taskMetric = taskMetric; 34 | this.springBootStartDuration = springBootStartTime; 35 | this.springBootReadyTime = springBootReadyTime; 36 | this.version = version; 37 | } 38 | 39 | public Integer getVersion() { 40 | return version; 41 | } 42 | 43 | public void setVersion(Integer version) { 44 | this.version = version; 45 | } 46 | 47 | public ContainerMetric getContainerMetric() { 48 | return containerMetric; 49 | } 50 | 51 | public void setContainerMetric(ContainerMetric containerMetric) { 52 | this.containerMetric = containerMetric; 53 | } 54 | 55 | public TaskMetric getTaskMetric() { 56 | return taskMetric; 57 | } 58 | 59 | public void setTaskMetric(TaskMetric taskMetric) { 60 | this.taskMetric = taskMetric; 61 | } 62 | 63 | public Instant getSpringBootReadyTime() { 64 | return springBootReadyTime; 65 | } 66 | 67 | public void setSpringBootReadyTime(Instant springBootReadyTime) { 68 | this.springBootReadyTime = springBootReadyTime; 69 | } 70 | 71 | public Duration getSpringBootStartDuration() { 72 | return springBootStartDuration; 73 | } 74 | 75 | public void setSpringBootStartDuration(Duration springBootStartDuration) { 76 | this.springBootStartDuration = springBootStartDuration; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/model/metrics/TaskMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class TaskMetric { 23 | private Instant pullStartedAt; 24 | private Instant pullStoppedAt; 25 | private String taskArn; 26 | 27 | public TaskMetric() {} 28 | 29 | public TaskMetric(Instant pullStartedAt, Instant pullStoppedAt, String taskArn) { 30 | this.pullStartedAt = pullStartedAt; 31 | this.pullStoppedAt = pullStoppedAt; 32 | this.taskArn = taskArn; 33 | } 34 | 35 | public Instant getPullStartedAt() { 36 | return pullStartedAt; 37 | } 38 | 39 | public void setPullStartedAt(Instant pullStartedAt) { 40 | this.pullStartedAt = pullStartedAt; 41 | } 42 | 43 | public Instant getPullStoppedAt() { 44 | return pullStoppedAt; 45 | } 46 | 47 | public void setPullStoppedAt(Instant pullStoppedAt) { 48 | this.pullStoppedAt = pullStoppedAt; 49 | } 50 | 51 | public Duration calculateDuration() { 52 | if (pullStartedAt == null || pullStoppedAt == null) 53 | return null; 54 | 55 | Duration duration = Duration.between(pullStartedAt, pullStoppedAt); 56 | 57 | return duration; 58 | } 59 | 60 | public String getTaskArn() { 61 | return taskArn; 62 | } 63 | 64 | public void setTaskArn(String taskArn) { 65 | this.taskArn = taskArn; 66 | } 67 | 68 | @Override 69 | public boolean equals(Object o) { 70 | if (this == o) return true; 71 | if (o == null || getClass() != o.getClass()) return false; 72 | TaskMetric that = (TaskMetric) o; 73 | return taskArn.equals(that.taskArn); 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | return Objects.hash(taskArn); 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return "TaskMetric{" + 84 | "pullStartedAt=" + pullStartedAt + 85 | ", pullStoppedAt=" + pullStoppedAt + 86 | ", taskArn='" + taskArn + '\'' + 87 | '}'; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/java/com/amazon/customerService/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.Customer; 19 | import com.amazon.customerService.repository.CustomerRepository; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.sql.Date; 25 | import java.time.Instant; 26 | import java.util.List; 27 | import java.util.Random; 28 | import java.util.UUID; 29 | 30 | @Service 31 | public class CustomerService { 32 | 33 | @Autowired 34 | CustomerRepository customerRepository; 35 | 36 | public List findAll() { 37 | return customerRepository.findAll(); 38 | } 39 | 40 | public Customer findById(String id) { 41 | return customerRepository.findById(id); 42 | } 43 | 44 | public Customer create(Customer customer) { 45 | return customerRepository.save(customer); 46 | } 47 | 48 | public Customer update(Customer customer) { 49 | return customerRepository.save(customer); 50 | } 51 | 52 | public void deleteById(String id) { 53 | customerRepository.deleteById(id); 54 | } 55 | 56 | public void loadCustomerData(int count) { 57 | 58 | for (int i = 0; i < count; i++) { 59 | String generatedString = RandomStringUtils.randomAlphabetic(10); 60 | 61 | Customer cust = new Customer(); 62 | cust.setName(generatedString); 63 | cust.setId(UUID.randomUUID().toString()); 64 | cust.setRegDate(Date.from(Instant.now())); 65 | cust.setEmail(generatedString + "@test.com"); 66 | 67 | Random rnd = new Random(); 68 | int number = rnd.nextInt(999999); 69 | 70 | cust.setAccountNumber(String.format("%06d", number)); 71 | 72 | customerRepository.save(cust); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/resources/META-INF/native-image/jni-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"[Lcom.sun.management.internal.DiagnosticCommandArgumentInfo;"} 4 | , 5 | { 6 | "name":"[Lcom.sun.management.internal.DiagnosticCommandInfo;"} 7 | , 8 | { 9 | "name":"[Ljava.lang.Class;"} 10 | , 11 | { 12 | "name":"com.sun.management.internal.DiagnosticCommandArgumentInfo", 13 | "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String","java.lang.String","java.lang.String","boolean","boolean","boolean","int"] }]} 14 | , 15 | { 16 | "name":"com.sun.management.internal.DiagnosticCommandInfo", 17 | "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String","java.lang.String","java.lang.String","java.lang.String","java.lang.String","boolean","java.util.List"] }]} 18 | , 19 | { 20 | "name":"java.lang.Boolean", 21 | "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]} 22 | , 23 | { 24 | "name":"java.lang.Class"} 25 | , 26 | { 27 | "name":"java.util.Arrays", 28 | "methods":[{"name":"asList","parameterTypes":["java.lang.Object[]"] }]} 29 | , 30 | { 31 | "name":"sun.instrument.InstrumentationImpl", 32 | "methods":[ 33 | {"name":"","parameterTypes":["long","boolean","boolean"] }, 34 | {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, 35 | {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, 36 | {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] } 37 | ]} 38 | , 39 | { 40 | "name":"sun.management.VMManagementImpl", 41 | "fields":[ 42 | {"name":"compTimeMonitoringSupport"}, 43 | {"name":"currentThreadCpuTimeSupport"}, 44 | {"name":"objectMonitorUsageSupport"}, 45 | {"name":"otherThreadCpuTimeSupport"}, 46 | {"name":"remoteDiagnosticCommandsSupport"}, 47 | {"name":"synchronizerUsageSupport"}, 48 | {"name":"threadAllocatedMemorySupport"}, 49 | {"name":"threadContentionMonitoringSupport"} 50 | ]} 51 | 52 | ] 53 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/resources/META-INF/native-image/predefined-classes-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type":"agent-extracted", 4 | "classes":[ 5 | ] 6 | } 7 | ] 8 | 9 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/resources/META-INF/native-image/proxy-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "interfaces":["java.lang.reflect.GenericArrayType","org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy","java.io.Serializable"]} 4 | , 5 | { 6 | "interfaces":["java.lang.reflect.ParameterizedType","org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy","java.io.Serializable"]} 7 | , 8 | { 9 | "interfaces":["java.lang.reflect.TypeVariable","org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy","java.io.Serializable"]} 10 | , 11 | { 12 | "interfaces":["java.lang.reflect.WildcardType","org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy","java.io.Serializable"]} 13 | , 14 | { 15 | "interfaces":["java.util.List","org.springframework.aop.SpringProxy","org.springframework.aop.framework.Advised","org.springframework.core.DecoratingProxy"]} 16 | , 17 | { 18 | "interfaces":["org.springframework.boot.actuate.endpoint.annotation.EndpointExtension","org.springframework.core.annotation.SynthesizedAnnotation"]} 19 | , 20 | { 21 | "interfaces":["org.springframework.boot.context.properties.ConfigurationProperties","org.springframework.core.annotation.SynthesizedAnnotation"]} 22 | , 23 | { 24 | "interfaces":["org.springframework.context.event.EventListener","org.springframework.core.annotation.SynthesizedAnnotation"]} 25 | , 26 | { 27 | "interfaces":["org.springframework.stereotype.Controller","org.springframework.core.annotation.SynthesizedAnnotation"]} 28 | , 29 | { 30 | "interfaces":["org.springframework.web.bind.annotation.ControllerAdvice","org.springframework.core.annotation.SynthesizedAnnotation"]} 31 | , 32 | { 33 | "interfaces":["org.springframework.web.bind.annotation.RequestMapping","org.springframework.core.annotation.SynthesizedAnnotation"]} 34 | 35 | ] 36 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/resources/META-INF/native-image/reflect-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"com.amazon.customerService.model.metrics.MetricWrapper", 4 | "allDeclaredFields":true, 5 | "allDeclaredMethods":true, 6 | "allDeclaredConstructors":true, 7 | "allPublicConstructors" : true, 8 | "allPublicMethods" : true, 9 | "allPublicFields" : true 10 | }, 11 | { 12 | "name":"com.amazon.customerService.model.metrics.ContainerMetric", 13 | "allDeclaredFields":true, 14 | "allDeclaredMethods":true, 15 | "allDeclaredConstructors":true, 16 | "allPublicConstructors" : true, 17 | "allPublicMethods" : true, 18 | "allPublicFields" : true 19 | }, 20 | { 21 | "name":"com.amazon.customerService.model.metrics.TaskMetric", 22 | "allDeclaredFields":true, 23 | "allDeclaredMethods":true, 24 | "allDeclaredConstructors":true, 25 | "allPublicConstructors" : true, 26 | "allPublicMethods" : true, 27 | "allPublicFields" : true 28 | } 29 | ] -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/resources/META-INF/native-image/serialization-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"com.amazon.customerService.repository.CustomerRepository$$EnhancerBySpringCGLIB$$2563aeec", 4 | "customTargetConstructorClass":"java.lang.Object" 5 | }, 6 | { 7 | "name":"com.amazon.customerService.service.CustomerService$$EnhancerBySpringCGLIB$$9ed02915", 8 | "customTargetConstructorClass":"java.lang.Object" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=http://localhost:8000/ 2 | logging.level.root=DEBUG 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=https://dynamodb.eu-west-1.amazonaws.com 2 | logging.level.root=INFO 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /spring-native-distroless/CustomerService/src/test/java/com/amazon/customerService/service/EcsMetaDataServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.metrics.ContainerMetric; 19 | import com.amazon.customerService.model.metrics.TaskMetric; 20 | import org.junit.Assert; 21 | import org.junit.jupiter.api.*; 22 | import org.junit.jupiter.api.extension.ExtendWith; 23 | import org.springframework.boot.test.context.SpringBootTest; 24 | import org.springframework.test.context.ActiveProfiles; 25 | import org.springframework.test.context.TestPropertySource; 26 | import org.springframework.test.context.junit.jupiter.SpringExtension; 27 | import org.springframework.test.context.web.WebAppConfiguration; 28 | 29 | import java.nio.file.Path; 30 | import java.time.ZoneOffset; 31 | import java.time.ZonedDateTime; 32 | import java.time.format.DateTimeFormatter; 33 | 34 | @ExtendWith(SpringExtension.class) 35 | @SpringBootTest 36 | @WebAppConfiguration 37 | @ActiveProfiles("local") 38 | 39 | @TestInstance(TestInstance.Lifecycle.PER_CLASS) 40 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 41 | @TestPropertySource(locations="classpath:application-local.properties") 42 | 43 | public class EcsMetaDataServiceTest { 44 | 45 | @Test 46 | @Order(1) 47 | public void testParse() { 48 | 49 | try { 50 | Path workingDir = Path.of("", "src/test/resources"); 51 | Path file = workingDir.resolve("task_response.json"); 52 | System.out.println("Parsing file: " + file); 53 | 54 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 55 | TaskMetric taskMetric = ecsMetaDataService.parseTaskMetaData(file.toUri().toURL()); 56 | 57 | file = workingDir.resolve("container_response.json"); 58 | System.out.println("Parsing file: " + file); 59 | 60 | ContainerMetric containerMetric = ecsMetaDataService.parseContainerMetaData(file.toUri().toURL()); 61 | 62 | String pullStartedAt = ZonedDateTime.ofInstant(taskMetric.getPullStartedAt(), ZoneOffset.UTC).format(DateTimeFormatter.ISO_DATE_TIME); 63 | String pullStoppedAt = ZonedDateTime.ofInstant(taskMetric.getPullStoppedAt(), ZoneOffset.UTC).format(DateTimeFormatter.ISO_DATE_TIME); 64 | 65 | Assert.assertEquals(pullStartedAt, "2020-10-08T20:47:16.053330955Z"); 66 | Assert.assertEquals(pullStoppedAt, "2020-10-08T20:47:19.592684631Z"); 67 | 68 | } 69 | 70 | catch (Exception exc) { 71 | exc.printStackTrace(); 72 | Assert.fail(); 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /spring-native/CustomerService/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | custom-jre/ -------------------------------------------------------------------------------- /spring-native/CustomerService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/graalvm/graalvm-ce:22.3.0 AS build-aot 2 | 3 | RUN microdnf install -y unzip zip 4 | 5 | RUN \ 6 | curl -s "https://get.sdkman.io" | bash; \ 7 | bash -c "source $HOME/.sdkman/bin/sdkman-init.sh; \ 8 | sdk install maven;" 9 | 10 | COPY ./pom.xml ./pom.xml 11 | COPY src ./src/ 12 | 13 | ENV MAVEN_OPTS='-Xmx8g' 14 | 15 | RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && mvn -Dmaven.test.skip=true clean package -Pnative" 16 | 17 | FROM public.ecr.aws/lts/ubuntu:22.04 18 | RUN addgroup --system spring && adduser --system spring --ingroup spring 19 | USER spring:spring 20 | COPY --from=build-aot /app/target/CustomerService / 21 | EXPOSE 8080 22 | 23 | CMD ["./CustomerService", "-Dspring.profiles.active=prod"] 24 | -------------------------------------------------------------------------------- /spring-native/CustomerService/Dockerfile-local: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-alpine 2 | RUN addgroup -S spring && adduser -S spring -G spring 3 | USER spring:spring 4 | ARG JAR_FILE=target/*.jar 5 | COPY ${JAR_FILE} CustomerService-0.0.1.jar 6 | ENTRYPOINT ["java","-jar", "-XX:TieredStopAtLevel=1", "-noverify", "-Dspring.profiles.active=prod","/CustomerService-0.0.1.jar"] -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService; 17 | 18 | import com.amazon.customerService.config.AppConfig; 19 | import com.amazon.customerService.model.metrics.MetricWrapper; 20 | import com.amazon.customerService.service.EcsMetaDataService; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.boot.SpringApplication; 26 | import org.springframework.boot.autoconfigure.SpringBootApplication; 27 | import org.springframework.boot.context.event.ApplicationReadyEvent; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.lang.management.ManagementFactory; 31 | import java.lang.management.RuntimeMXBean; 32 | import java.time.Duration; 33 | import java.time.Instant; 34 | 35 | @Slf4j 36 | @SpringBootApplication 37 | public class CustomerServiceApplication { 38 | 39 | private static Instant startTime; 40 | private static Instant endTime; 41 | 42 | public static void main(String[] args) { 43 | RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); 44 | startTime = Instant.ofEpochMilli(bean.getStartTime()); 45 | SpringApplication.run(CustomerServiceApplication.class, args); 46 | Duration springBootStartTime = Duration.between(startTime, endTime); 47 | 48 | EcsMetaDataService ecsMetaDataService = new EcsMetaDataService(); 49 | MetricWrapper metricWrapper = ecsMetaDataService.getMetaData(); 50 | 51 | if (metricWrapper != null) { 52 | metricWrapper.setVersion(AppConfig.APPLICATION_VERSION); 53 | metricWrapper.setSpringBootStartDuration(springBootStartTime); 54 | metricWrapper.setSpringBootReadyTime(endTime); 55 | ObjectMapper mapper = new ObjectMapper() 56 | .registerModule(new JavaTimeModule()); 57 | 58 | try { 59 | String metricsJson = mapper.writeValueAsString(metricWrapper); 60 | log.info("Metrics: " + metricsJson); 61 | } catch (JsonProcessingException e) { 62 | log.error(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | @EventListener(ApplicationReadyEvent.class) 68 | public void startApp() { 69 | endTime = Instant.now(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.config; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 | import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; 23 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 24 | import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; 25 | 26 | import java.net.URI; 27 | 28 | @Configuration 29 | public class AppConfig { 30 | 31 | public final static Integer APPLICATION_VERSION = 5; 32 | 33 | @Value("${amazon.dynamodb.endpoint}") 34 | private String amazonDynamoDBEndpoint; 35 | 36 | @Bean 37 | public DynamoDbClient getDynamoDbClient() { 38 | AwsCredentialsProvider credentialsProvider = 39 | DefaultCredentialsProvider.builder() 40 | .profileName("default") 41 | .build(); 42 | 43 | DynamoDbClientBuilder clientBuilder = DynamoDbClient.builder(); 44 | clientBuilder 45 | .credentialsProvider(credentialsProvider); 46 | if (!amazonDynamoDBEndpoint.isEmpty()) { 47 | clientBuilder.endpointOverride(URI.create(amazonDynamoDBEndpoint)); 48 | } 49 | return clientBuilder.build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.controller; 17 | 18 | import com.amazon.customerService.exception.CustomerNotFoundException; 19 | import com.amazon.customerService.model.Customer; 20 | import com.amazon.customerService.service.CustomerService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import java.util.List; 26 | 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/api") 30 | public class CustomerController { 31 | 32 | @Autowired 33 | CustomerService customerService; 34 | 35 | @GetMapping("/customers") 36 | List getCustomers() { 37 | return customerService.findAll(); 38 | } 39 | 40 | @GetMapping("/customers/load") 41 | List loadCustomers() { 42 | customerService.loadCustomerData(100); 43 | return customerService.findAll(); 44 | } 45 | 46 | @PostMapping("/customers") 47 | Customer createCustomer(@RequestBody Customer customer) { 48 | return customerService.create(customer); 49 | } 50 | 51 | @GetMapping("/customers/{id}") 52 | Customer getCustomerbyId(@PathVariable String id) { 53 | return customerService.findById(id); 54 | } 55 | 56 | @PutMapping("/customers/{id}") 57 | Customer replaceCustomer(@RequestBody Customer newCustomer, @PathVariable String id) { 58 | Customer customer = customerService.findById(id); 59 | 60 | if (null == customer) { 61 | throw new CustomerNotFoundException(newCustomer.getId()); 62 | } 63 | 64 | customer.setId(newCustomer.getId()); 65 | customer.setRegDate(newCustomer.getRegDate()); 66 | customer.setEmail(newCustomer.getEmail()); 67 | customer.setAccountNumber(newCustomer.getAccountNumber()); 68 | customer.setName(newCustomer.getName()); 69 | 70 | customerService.update(customer); 71 | 72 | return customer; 73 | } 74 | 75 | @DeleteMapping("/customers/{id}") 76 | void deleteCustomerById(@PathVariable String id) { 77 | customerService.deleteById(id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.exception; 17 | 18 | public class CustomerNotFoundException extends RuntimeException { 19 | 20 | public CustomerNotFoundException(String id) { 21 | super("Could not find customer " + id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/model/metrics/ContainerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class ContainerMetric { 23 | private Instant createdAt; 24 | private Instant startedAt; 25 | 26 | public ContainerMetric() { 27 | } 28 | 29 | public ContainerMetric(Instant createdAt, Instant startedAt) { 30 | this.createdAt = createdAt; 31 | this.startedAt = startedAt; 32 | } 33 | 34 | public Duration calculateDuration() { 35 | if (startedAt == null || createdAt == null) 36 | return null; 37 | 38 | Duration duration = Duration.between(createdAt, startedAt); 39 | 40 | return duration; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "ContainerMetric{" + 46 | "createdAt=" + createdAt + 47 | ", startedAt=" + startedAt + 48 | '}'; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object o) { 53 | if (this == o) return true; 54 | if (o == null || getClass() != o.getClass()) return false; 55 | ContainerMetric that = (ContainerMetric) o; 56 | return createdAt.equals(that.createdAt) && startedAt.equals(that.startedAt); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(createdAt, startedAt); 62 | } 63 | 64 | public Instant getCreatedAt() { 65 | return createdAt; 66 | } 67 | 68 | public void setCreatedAt(Instant createdAt) { 69 | this.createdAt = createdAt; 70 | } 71 | 72 | public Instant getStartedAt() { 73 | return startedAt; 74 | } 75 | 76 | public void setStartedAt(Instant startedAt) { 77 | this.startedAt = startedAt; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/model/metrics/MetricWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | 21 | public class MetricWrapper { 22 | 23 | private ContainerMetric containerMetric; 24 | private TaskMetric taskMetric; 25 | private Duration springBootStartDuration; 26 | private Instant springBootReadyTime; 27 | private Integer version; 28 | 29 | public MetricWrapper() { 30 | } 31 | 32 | public MetricWrapper(ContainerMetric containerMetric, TaskMetric taskMetric, Duration springBootStartTime, Instant springBootReadyTime, Integer version) { 33 | this.containerMetric = containerMetric; 34 | this.taskMetric = taskMetric; 35 | this.springBootStartDuration = springBootStartTime; 36 | this.springBootReadyTime = springBootReadyTime; 37 | this.version = version; 38 | } 39 | 40 | public Integer getVersion() { 41 | return version; 42 | } 43 | 44 | public void setVersion(Integer version) { 45 | this.version = version; 46 | } 47 | 48 | public ContainerMetric getContainerMetric() { 49 | return containerMetric; 50 | } 51 | 52 | public void setContainerMetric(ContainerMetric containerMetric) { 53 | this.containerMetric = containerMetric; 54 | } 55 | 56 | public TaskMetric getTaskMetric() { 57 | return taskMetric; 58 | } 59 | 60 | public void setTaskMetric(TaskMetric taskMetric) { 61 | this.taskMetric = taskMetric; 62 | } 63 | 64 | public Instant getSpringBootReadyTime() { 65 | return springBootReadyTime; 66 | } 67 | 68 | public void setSpringBootReadyTime(Instant springBootReadyTime) { 69 | this.springBootReadyTime = springBootReadyTime; 70 | } 71 | 72 | public Duration getSpringBootStartDuration() { 73 | return springBootStartDuration; 74 | } 75 | 76 | public void setSpringBootStartDuration(Duration springBootStartDuration) { 77 | this.springBootStartDuration = springBootStartDuration; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/model/metrics/TaskMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.model.metrics; 17 | 18 | import java.time.Duration; 19 | import java.time.Instant; 20 | import java.util.Objects; 21 | 22 | public class TaskMetric { 23 | private Instant pullStartedAt; 24 | private Instant pullStoppedAt; 25 | private String taskArn; 26 | 27 | public TaskMetric() { 28 | } 29 | 30 | public TaskMetric(Instant pullStartedAt, Instant pullStoppedAt, String taskArn) { 31 | this.pullStartedAt = pullStartedAt; 32 | this.pullStoppedAt = pullStoppedAt; 33 | this.taskArn = taskArn; 34 | } 35 | 36 | public Instant getPullStartedAt() { 37 | return pullStartedAt; 38 | } 39 | 40 | public void setPullStartedAt(Instant pullStartedAt) { 41 | this.pullStartedAt = pullStartedAt; 42 | } 43 | 44 | public Instant getPullStoppedAt() { 45 | return pullStoppedAt; 46 | } 47 | 48 | public void setPullStoppedAt(Instant pullStoppedAt) { 49 | this.pullStoppedAt = pullStoppedAt; 50 | } 51 | 52 | public Duration calculateDuration() { 53 | if (pullStartedAt == null || pullStoppedAt == null) 54 | return null; 55 | 56 | Duration duration = Duration.between(pullStartedAt, pullStoppedAt); 57 | 58 | return duration; 59 | } 60 | 61 | public String getTaskArn() { 62 | return taskArn; 63 | } 64 | 65 | public void setTaskArn(String taskArn) { 66 | this.taskArn = taskArn; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object o) { 71 | if (this == o) return true; 72 | if (o == null || getClass() != o.getClass()) return false; 73 | TaskMetric that = (TaskMetric) o; 74 | return taskArn.equals(that.taskArn); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | return Objects.hash(taskArn); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "TaskMetric{" + 85 | "pullStartedAt=" + pullStartedAt + 86 | ", pullStoppedAt=" + pullStoppedAt + 87 | ", taskArn='" + taskArn + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/java/com/amazon/customerService/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.amazon.customerService.service; 17 | 18 | import com.amazon.customerService.model.Customer; 19 | import com.amazon.customerService.repository.CustomerRepository; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.sql.Date; 25 | import java.time.Instant; 26 | import java.util.List; 27 | import java.util.Random; 28 | import java.util.UUID; 29 | 30 | @Service 31 | public class CustomerService { 32 | 33 | @Autowired 34 | CustomerRepository customerRepository; 35 | 36 | public List findAll() { 37 | return customerRepository.findAll(); 38 | } 39 | 40 | public Customer findById(String id) { 41 | return customerRepository.findById(id); 42 | } 43 | 44 | public Customer create(Customer customer) { 45 | return customerRepository.save(customer); 46 | } 47 | 48 | public Customer update(Customer customer) { 49 | return customerRepository.save(customer); 50 | } 51 | 52 | public void deleteById(String id) { 53 | customerRepository.deleteById(id); 54 | } 55 | 56 | public void loadCustomerData(int count) { 57 | 58 | for (int i = 0; i < count; i++) { 59 | String generatedString = RandomStringUtils.randomAlphabetic(10); 60 | 61 | Customer cust = new Customer(); 62 | cust.setName(generatedString); 63 | cust.setId(UUID.randomUUID().toString()); 64 | cust.setRegDate(Date.from(Instant.now())); 65 | cust.setEmail(generatedString + "@test.com"); 66 | 67 | Random rnd = new Random(); 68 | int number = rnd.nextInt(999999); 69 | 70 | cust.setAccountNumber(String.format("%06d", number)); 71 | 72 | customerRepository.save(cust); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/resources/META-INF/native-image/predefined-classes-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "agent-extracted", 4 | "classes": [ 5 | ] 6 | } 7 | ] 8 | 9 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/resources/META-INF/native-image/proxy-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "interfaces": [ 4 | "java.lang.reflect.GenericArrayType", 5 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 6 | "java.io.Serializable" 7 | ] 8 | }, 9 | { 10 | "interfaces": [ 11 | "java.lang.reflect.ParameterizedType", 12 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 13 | "java.io.Serializable" 14 | ] 15 | }, 16 | { 17 | "interfaces": [ 18 | "java.lang.reflect.TypeVariable", 19 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 20 | "java.io.Serializable" 21 | ] 22 | }, 23 | { 24 | "interfaces": [ 25 | "java.lang.reflect.WildcardType", 26 | "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", 27 | "java.io.Serializable" 28 | ] 29 | }, 30 | { 31 | "interfaces": [ 32 | "java.util.List", 33 | "org.springframework.aop.SpringProxy", 34 | "org.springframework.aop.framework.Advised", 35 | "org.springframework.core.DecoratingProxy" 36 | ] 37 | }, 38 | { 39 | "interfaces": [ 40 | "org.springframework.boot.actuate.endpoint.annotation.EndpointExtension", 41 | "org.springframework.core.annotation.SynthesizedAnnotation" 42 | ] 43 | }, 44 | { 45 | "interfaces": [ 46 | "org.springframework.boot.context.properties.ConfigurationProperties", 47 | "org.springframework.core.annotation.SynthesizedAnnotation" 48 | ] 49 | }, 50 | { 51 | "interfaces": [ 52 | "org.springframework.context.event.EventListener", 53 | "org.springframework.core.annotation.SynthesizedAnnotation" 54 | ] 55 | }, 56 | { 57 | "interfaces": [ 58 | "org.springframework.stereotype.Controller", 59 | "org.springframework.core.annotation.SynthesizedAnnotation" 60 | ] 61 | }, 62 | { 63 | "interfaces": [ 64 | "org.springframework.web.bind.annotation.ControllerAdvice", 65 | "org.springframework.core.annotation.SynthesizedAnnotation" 66 | ] 67 | }, 68 | { 69 | "interfaces": [ 70 | "org.springframework.web.bind.annotation.RequestMapping", 71 | "org.springframework.core.annotation.SynthesizedAnnotation" 72 | ] 73 | } 74 | ] 75 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/resources/META-INF/native-image/reflect-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "com.amazon.customerService.model.metrics.MetricWrapper", 4 | "allDeclaredFields": true, 5 | "allDeclaredMethods": true, 6 | "allDeclaredConstructors": true, 7 | "allPublicConstructors": true, 8 | "allPublicMethods": true, 9 | "allPublicFields": true 10 | }, 11 | { 12 | "name": "com.amazon.customerService.model.metrics.ContainerMetric", 13 | "allDeclaredFields": true, 14 | "allDeclaredMethods": true, 15 | "allDeclaredConstructors": true, 16 | "allPublicConstructors": true, 17 | "allPublicMethods": true, 18 | "allPublicFields": true 19 | }, 20 | { 21 | "name": "com.amazon.customerService.model.metrics.TaskMetric", 22 | "allDeclaredFields": true, 23 | "allDeclaredMethods": true, 24 | "allDeclaredConstructors": true, 25 | "allPublicConstructors": true, 26 | "allPublicMethods": true, 27 | "allPublicFields": true 28 | } 29 | ] -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/resources/META-INF/native-image/serialization-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "com.amazon.customerService.repository.CustomerRepository$$EnhancerBySpringCGLIB$$2563aeec", 4 | "customTargetConstructorClass": "java.lang.Object" 5 | }, 6 | { 7 | "name": "com.amazon.customerService.service.CustomerService$$EnhancerBySpringCGLIB$$9ed02915", 8 | "customTargetConstructorClass": "java.lang.Object" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=http://localhost:8000/ 2 | logging.level.root=DEBUG 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false -------------------------------------------------------------------------------- /spring-native/CustomerService/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | amazon.dynamodb.endpoint=https://dynamodb.eu-west-1.amazonaws.com 2 | logging.level.root=INFO 3 | spring.main.lazy-initialization=true 4 | spring.jmx.enabled=false --------------------------------------------------------------------------------