sink = new FlinkKinesisProducer<>(new SimpleStringSchema(), outputProperties);
+ String outputStreamName = "log_data_stream";
+ sink.setDefaultStream(outputStreamName);
+ sink.setDefaultPartition("0");
+
+ return sink;
+ }
+
+
+
+ private File getFile(String fileName) throws IOException {
+ ClassLoader classLoader = getClass().getClassLoader();
+ URL resource = classLoader.getResource(fileName);
+
+ if (resource == null) {
+ throw new IllegalArgumentException("file is not found!");
+ } else {
+ return new File(resource.getFile());
+ }
+ }
+}
diff --git a/aws/kinesis/src/main/java/io/pratik/models/LogRecord.java b/aws/kinesis/src/main/java/io/pratik/models/LogRecord.java
new file mode 100644
index 000000000..560d8915d
--- /dev/null
+++ b/aws/kinesis/src/main/java/io/pratik/models/LogRecord.java
@@ -0,0 +1,40 @@
+/**
+ *
+ */
+package io.pratik.models;
+
+/**
+ * @author pratikdas
+ *
+ */
+public class LogRecord {
+ private String ip;
+ private String httpStatus;
+ private String url;
+ public String getIp() {
+ return ip;
+ }
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+ public String getHttpStatus() {
+ return httpStatus;
+ }
+ public void setHttpStatus(String httpStatus) {
+ this.httpStatus = httpStatus;
+ }
+ public String getUrl() {
+ return url;
+ }
+ public void setUrl(String url) {
+ this.url = url;
+ }
+ @Override
+ public String toString() {
+ return "LogRecord [ip=" + ip + ", httpStatus=" + httpStatus + ", url=" + url + "]";
+ }
+
+
+
+
+}
diff --git a/aws/kinesis/src/main/resources/apache_access_log b/aws/kinesis/src/main/resources/apache_access_log
new file mode 100644
index 000000000..3d8d626ca
--- /dev/null
+++ b/aws/kinesis/src/main/resources/apache_access_log
@@ -0,0 +1,33 @@
+83.149.9.216 - - [17/May/2015:10:05:03 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-search.png HTTP/1.1" 200 203023 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:43 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png HTTP/1.1" 200 171717 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:47 +0000] "GET /presentations/logstash-monitorama-2013/plugin/highlight/highlight.js HTTP/1.1" 200 26185 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:12 +0000] "GET /presentations/logstash-monitorama-2013/plugin/zoom-js/zoom.js HTTP/1.1" 200 7697 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:07 +0000] "GET /presentations/logstash-monitorama-2013/plugin/notes/notes.js HTTP/1.1" 200 2892 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:34 +0000] "GET /presentations/logstash-monitorama-2013/images/sad-medic.png HTTP/1.1" 200 430406 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:57 +0000] "GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Bold.ttf HTTP/1.1" 404 38720 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:50 +0000] "GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Regular.ttf HTTP/1.1" 200 41820 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+83.149.9.216 - - [17/May/2015:10:05:24 +0000] "GET /presentations/logstash-monitorama-2013/images/frontend-response-codes.png HTTP/1.1" 310 52878 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
+46.105.14.53 - - [17/May/2015:10:05:44 +0000] "GET /blog/tags/puppet?flav=rss20 HTTP/1.1" 200 14872 "-" "UniversalFeedParser/4.2-pre-314-svn +http://feedparser.org/"
+20.241.23.22 - - [17/May/2015:10:05:47 +0000] "GET /blog/geekery/soekris-gpio.html HTTP/1.0" 200 9587 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
+91.177.205.119 - - [17/May/2015:10:05:22 +0000] "GET /blog/geekery/xvfb-firefox.html HTTP/1.1" 200 10975 "http://en.wikipedia.org/wiki/Xvfb" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
+91.177.205.119 - - [17/May/2015:10:05:34 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
+91.177.205.119 - - [17/May/2015:10:05:37 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
+91.177.205.119 - - [17/May/2015:10:05:54 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
+91.177.205.119 - - [17/May/2015:10:05:31 +0000] "GET /images/web/2009/banner.png HTTP/1.1" 200 52315 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
+91.177.205.119 - - [17/May/2015:10:05:32 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Win64; x64; Trident/6.0)"
+66.249.73.185 - - [17/May/2015:10:05:22 +0000] "GET /doc/index.html?org/elasticsearch/action/search/SearchResponse.html HTTP/1.1" 404 294 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
+207.241.237.228 - - [17/May/2015:10:05:40 +0000] "GET /blog/tags/defcon HTTP/1.0" 200 24142 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
+207.241.237.101 - - [17/May/2015:10:05:51 +0000] "GET /blog/tags/regex HTTP/1.0" 200 14888 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
+87.169.99.232 - - [17/May/2015:10:05:59 +0000] "GET /presentations/puppet-at-loggly/puppet-at-loggly.pdf.html HTTP/1.1" 200 24747 "https://www.google.de/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
+209.85.238.199 - - [17/May/2015:10:05:30 +0000] "GET /blog/tags/firefox?flav=rss20 HTTP/1.1" 200 16021 "-" "Feedfetcher-Google; (+http://www.google.com/feedfetcher.html; 3 subscribers; feed-id=14171215010336145331)"
+209.85.238.199 - - [17/May/2015:10:05:15 +0000] "GET /test.xml HTTP/1.1" 200 1370 "-" "Feedfetcher-Google; (+http://www.google.com/feedfetcher.html; 1 subscribers; feed-id=11390274670024826467)"
+81.220.24.207 - - [17/May/2015:10:05:13 +0000] "GET /blog/geekery/ssl-latency.html HTTP/1.1" 200 17147 "http://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0CE4QFjAE&url=http%3A%2F%2Fwww.semicomplete.com%2Fblog%2Fgeekery%2Fssl-latency.html&ei=ZdEAU9mGGuWX1AW09IDoBw&usg=AFQjCNHw6zioJpizqX8Q0YpKKaF4zdCSEg&bvm=bv.61535280,d.d2k" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
+81.220.24.207 - - [17/May/2015:10:05:44 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
+81.220.24.207 - - [17/May/2015:10:05:26 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
+81.220.24.207 - - [17/May/2015:10:05:39 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
+81.220.24.207 - - [17/May/2015:10:05:52 +0000] "GET /images/web/2009/banner.png HTTP/1.1" 200 52315 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
+81.220.24.207 - - [17/May/2015:10:05:21 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
+66.249.73.135 - - [17/May/2015:11:05:17 +0000] "GET /blog/geekery/vmware-cpu-performance.html HTTP/1.1" 200 12908 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
+46.105.14.53 - - [17/May/2015:11:05:42 +0000] "GET /blog/tags/puppet?flav=rss20 HTTP/1.1" 200 14872 "-" "UniversalFeedParser/4.2-pre-314-svn +http://feedparser.org/"
+218.30.103.62 - - [17/May/2015:11:05:11 +0000] "GET /robots.txt HTTP/1.1" 200 - "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
+218.30.103.62 - - [17/May/2015:11:05:46 +0000] "GET /robots.txt HTTP/1.1" 200 - "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
\ No newline at end of file
diff --git a/aws/kinesis/src/main/resources/lambda_function/index.js b/aws/kinesis/src/main/resources/lambda_function/index.js
new file mode 100644
index 000000000..fde5c8ccd
--- /dev/null
+++ b/aws/kinesis/src/main/resources/lambda_function/index.js
@@ -0,0 +1,33 @@
+console.log('Loading function');
+
+const validateRecord = (recordElement)=>{
+ // record is considered valid if contains status field
+ return recordElement.includes("status")
+}
+
+exports.handler = async (event, context) => {
+ /* Process the list of records and transform them */
+ const output = event.records.map((record)=>{
+ const decodedData = Buffer.from(record.data, "base64").toString("utf-8")
+ let isValidRecord = validateRecord(decodedData)
+
+ if(isValidRecord){
+ let parsedRecord = JSON.parse(decodedData)
+ // read fields from parsed JSON for some more processing
+ const outputRecord = `status::${parsedRecord.status}`
+ return {
+ recordId: record.recordId,
+ result: 'Ok',
+ // payload is encoded back to base64 before returning the result
+ data: Buffer.from(outputRecord, "utf-8").toString("base64")
+ }
+
+ }else{
+ return {
+ recordId: record.recordId,
+ result: 'dropped',
+ data: record.data // payload is kept intact,
+ }
+ }
+ })
+};
diff --git a/aws/spring-cloud-aws-s3/.gitignore b/aws/spring-cloud-aws-s3/.gitignore
new file mode 100644
index 000000000..3f8f6096a
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/.gitignore
@@ -0,0 +1,26 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
diff --git a/aws/spring-cloud-aws-s3/.mvn/wrapper/maven-wrapper.jar b/aws/spring-cloud-aws-s3/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..cb28b0e37
Binary files /dev/null and b/aws/spring-cloud-aws-s3/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/spring-cloud-aws-s3/.mvn/wrapper/maven-wrapper.properties b/aws/spring-cloud-aws-s3/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..5f0536eb7
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/aws/spring-cloud-aws-s3/Dockerfile b/aws/spring-cloud-aws-s3/Dockerfile
new file mode 100644
index 000000000..ec285f483
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/Dockerfile
@@ -0,0 +1,15 @@
+FROM maven:3.9-amazoncorretto-21 as backend
+WORKDIR /backend
+COPY pom.xml .
+COPY lombok.config .
+RUN mvn dependency:go-offline -B
+COPY src ./src
+RUN mvn clean install -DskipITs
+RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
+
+FROM openjdk:21
+ARG DEPENDENCY=/backend/target/dependency
+COPY --from=backend ${DEPENDENCY}/BOOT-INF/lib /app/lib
+COPY --from=backend ${DEPENDENCY}/META-INF /app/META-INF
+COPY --from=backend ${DEPENDENCY}/BOOT-INF/classes /app
+ENTRYPOINT ["java", "-cp", "app:app/lib/*", "io.reflectoring.Application"]
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/README.md b/aws/spring-cloud-aws-s3/README.md
new file mode 100644
index 000000000..615f044fc
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/README.md
@@ -0,0 +1,26 @@
+## Interacting with Amazon S3 Bucket using Spring Cloud AWS
+
+Codebase demonstrating connection and interaction with provisioned Amazon S3 bucket using [Spring Cloud AWS](https://spring.io/projects/spring-cloud-aws).
+
+Contains integration tests to validate interaction between the application and Amazon S3 using [LocalStack](https://github.com/localstack/localstack) and [Testcontainers](https://github.com/testcontainers/testcontainers-java). Test cases can be executed with the command `./mvnw integration-test verify`.
+
+To run the application locally without provisioning actual AWS Resources, execute the below commands:
+
+```bash
+chmod +x localstack/init-s3-bucket.sh
+```
+
+```bash
+sudo docker-compose build
+```
+
+```bash
+sudo docker-compose up -d
+```
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Integrating Amazon S3 with Spring Boot Using Spring Cloud AWS](https://reflectoring.io/integrating-amazon-s3-with-spring-boot-using-spring-cloud-aws/)
+* [Offloading File Transfers with Amazon S3 Presigned URLs in Spring Boot](https://reflectoring.io/offloading-file-transfers-with-amazon-s3-presigned-urls-in-spring-boot/)
diff --git a/aws/spring-cloud-aws-s3/docker-compose.yml b/aws/spring-cloud-aws-s3/docker-compose.yml
new file mode 100644
index 000000000..a4248074e
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/docker-compose.yml
@@ -0,0 +1,37 @@
+version: '3.7'
+
+services:
+ localstack:
+ container_name: localstack
+ image: localstack/localstack:3.3
+ ports:
+ - 4566:4566
+ environment:
+ - SERVICES=s3
+ volumes:
+ - ./localstack/init-s3-bucket.sh:/etc/localstack/init/ready.d/init-s3-bucket.sh
+ networks:
+ - reflectoring
+
+ backend:
+ container_name: backend-application
+ build:
+ context: ./
+ dockerfile: Dockerfile
+ ports:
+ - 8080:8080
+ depends_on:
+ - localstack
+ environment:
+ spring.cloud.aws.s3.endpoint: 'http://localstack:4566'
+ spring.cloud.aws.s3.path-style-access-enabled: true
+ spring.cloud.aws.credentials.access-key: test
+ spring.cloud.aws.credentials.secret-key: test
+ spring.cloud.aws.s3.region: 'us-east-1'
+ io.reflectoring.aws.s3.bucket-name: 'reflectoring-bucket'
+ io.reflectoring.aws.s3.presigned-url.validity: 120
+ networks:
+ - reflectoring
+
+networks:
+ reflectoring:
diff --git a/aws/spring-cloud-aws-s3/localstack/init-s3-bucket.sh b/aws/spring-cloud-aws-s3/localstack/init-s3-bucket.sh
new file mode 100755
index 000000000..793209e5a
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/localstack/init-s3-bucket.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+bucket_name="reflectoring-bucket"
+
+awslocal s3api create-bucket --bucket $bucket_name
+
+echo "S3 bucket '$bucket_name' created successfully"
+echo "Executed init-s3-bucket.sh"
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/lombok.config b/aws/spring-cloud-aws-s3/lombok.config
new file mode 100644
index 000000000..a886d4642
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/lombok.config
@@ -0,0 +1 @@
+lombok.nonNull.exceptionType=IllegalArgumentException
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/mvnw b/aws/spring-cloud-aws-s3/mvnw
new file mode 100755
index 000000000..66df28542
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/spring-cloud-aws-s3/mvnw.cmd b/aws/spring-cloud-aws-s3/mvnw.cmd
new file mode 100644
index 000000000..95ba6f54a
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/aws/spring-cloud-aws-s3/pom.xml b/aws/spring-cloud-aws-s3/pom.xml
new file mode 100644
index 000000000..e1a9d5a35
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/pom.xml
@@ -0,0 +1,120 @@
+
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.0
+
+
+
+ io.reflectoring
+ spring-cloud-aws-s3
+ 0.0.1
+
+ spring-cloud-aws-s3
+ Proof-of-concept demonstrating connection and interaction with provisioned S3 bucket using spring cloud aws. Contains integration tests to validate interaction between the application and AWS S3 using LocalStack and Testcontainers.
+
+
+ 21
+ 3.1.1
+
+
+
+
+ hardikSinghBehl
+ Hardik Singh Behl
+ behl.hardiksingh@gmail.com
+
+ Developer
+
+ UTC +5:30
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-starter-s3
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.testcontainers
+ localstack
+ test
+
+
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws
+ ${spring.cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/Application.java b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/Application.java
new file mode 100644
index 000000000..7dd263b8d
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/Application.java
@@ -0,0 +1,13 @@
+package io.reflectoring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/configuration/AwsS3BucketProperties.java b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/configuration/AwsS3BucketProperties.java
new file mode 100644
index 000000000..2d5f577f0
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/configuration/AwsS3BucketProperties.java
@@ -0,0 +1,68 @@
+package io.reflectoring.configuration;
+
+import java.time.Duration;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+import io.reflectoring.validation.BucketExists;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Maps configuration values defined in the active {@code .yml} file to the
+ * corresponding instance variables below. The configuration properties are
+ * referenced within the application to interact with the provisioned AWS S3
+ * Bucket.
+ *
+ *
+ * Example YAML configuration:
+ *
+ *
+ * io:
+ * reflectoring:
+ * aws:
+ * s3:
+ * bucket-name: s3-bucket-name
+ * presigned-url:
+ * validity: url-validity-in-seconds
+ *
+ */
+@Getter
+@Setter
+@Validated
+@ConfigurationProperties(prefix = "io.reflectoring.aws.s3")
+public class AwsS3BucketProperties {
+
+ @BucketExists
+ @NotBlank(message = "S3 bucket name must be configured")
+ private String bucketName;
+
+ @Valid
+ private PresignedUrl presignedUrl = new PresignedUrl();
+
+ @Getter
+ @Setter
+ @Validated
+ public class PresignedUrl {
+
+ /**
+ * The validity period in seconds for the generated presigned URLs. The
+ * URLs would not be accessible post expiration.
+ */
+ @NotNull(message = "S3 presigned URL validity must be specified")
+ @Positive(message = "S3 presigned URL validity must be a positive value")
+ private Integer validity;
+
+ }
+
+ public Duration getPresignedUrlValidity() {
+ var urlValidity = this.presignedUrl.validity;
+ return Duration.ofSeconds(urlValidity);
+ }
+
+}
diff --git a/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/service/StorageService.java b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/service/StorageService.java
new file mode 100644
index 000000000..69e8fe3d2
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/service/StorageService.java
@@ -0,0 +1,56 @@
+package io.reflectoring.service;
+
+import java.net.URL;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import io.awspring.cloud.s3.S3Resource;
+import io.awspring.cloud.s3.S3Template;
+import io.reflectoring.configuration.AwsS3BucketProperties;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+
+@Service
+@RequiredArgsConstructor
+@EnableConfigurationProperties(AwsS3BucketProperties.class)
+public class StorageService {
+
+ private final S3Template s3Template;
+ private final AwsS3BucketProperties awsS3BucketProperties;
+
+ @SneakyThrows
+ public void save(@NonNull final MultipartFile file) {
+ final var key = file.getOriginalFilename();
+ final var bucketName = awsS3BucketProperties.getBucketName();
+
+ s3Template.upload(bucketName, key, file.getInputStream());
+ }
+
+ public S3Resource retrieve(@NonNull final String objectKey) {
+ final var bucketName = awsS3BucketProperties.getBucketName();
+ return s3Template.download(bucketName, objectKey);
+ }
+
+ public void delete(@NonNull final String objectKey) {
+ final var bucketName = awsS3BucketProperties.getBucketName();
+ s3Template.deleteObject(bucketName, objectKey);
+ }
+
+ public URL generateViewablePresignedUrl(@NonNull final String objectKey) {
+ final var bucketName = awsS3BucketProperties.getBucketName();
+ final var urlValidity = awsS3BucketProperties.getPresignedUrlValidity();
+
+ return s3Template.createSignedGetURL(bucketName, objectKey, urlValidity);
+ }
+
+ public URL generateUploadablePresignedUrl(@NonNull final String objectKey) {
+ final var bucketName = awsS3BucketProperties.getBucketName();
+ final var urlValidity = awsS3BucketProperties.getPresignedUrlValidity();
+
+ return s3Template.createSignedPutURL(bucketName, objectKey, urlValidity);
+ }
+
+}
diff --git a/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/validation/BucketExistenceValidator.java b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/validation/BucketExistenceValidator.java
new file mode 100644
index 000000000..59a5d13bd
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/validation/BucketExistenceValidator.java
@@ -0,0 +1,18 @@
+package io.reflectoring.validation;
+
+import io.awspring.cloud.s3.S3Template;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class BucketExistenceValidator implements ConstraintValidator {
+
+ private final S3Template s3Template;
+
+ @Override
+ public boolean isValid(final String bucketName, final ConstraintValidatorContext context) {
+ return s3Template.bucketExists(bucketName);
+ }
+
+}
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/validation/BucketExists.java b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/validation/BucketExists.java
new file mode 100644
index 000000000..1d48520f5
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/main/java/io/reflectoring/validation/BucketExists.java
@@ -0,0 +1,24 @@
+package io.reflectoring.validation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+
+@Documented
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = BucketExistenceValidator.class)
+public @interface BucketExists {
+
+ String message() default "No bucket exists with configured name.";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+}
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/src/main/resources/application.yaml b/aws/spring-cloud-aws-s3/src/main/resources/application.yaml
new file mode 100644
index 000000000..c94f4a895
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/main/resources/application.yaml
@@ -0,0 +1,16 @@
+spring:
+ cloud:
+ aws:
+ credentials:
+ access-key: ${AWS_ACCESS_KEY}
+ secret-key: ${AWS_SECRET_KEY}
+ s3:
+ region: ${AWS_S3_REGION}
+
+io:
+ reflectoring:
+ aws:
+ s3:
+ bucket-name: ${AWS_S3_BUCKET_NAME}
+ presigned-url:
+ validity: ${AWS_S3_PRESIGNED_URL_VALIDITY}
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/helper/InitializeS3Bucket.java b/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/helper/InitializeS3Bucket.java
new file mode 100644
index 000000000..05c47884c
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/helper/InitializeS3Bucket.java
@@ -0,0 +1,14 @@
+package io.reflectoring.helper;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(S3BucketInitializer.class)
+public @interface InitializeS3Bucket {
+}
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/helper/S3BucketInitializer.java b/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/helper/S3BucketInitializer.java
new file mode 100644
index 000000000..0d319776b
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/helper/S3BucketInitializer.java
@@ -0,0 +1,56 @@
+package io.reflectoring.helper;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.testcontainers.containers.localstack.LocalStackContainer;
+import org.testcontainers.containers.localstack.LocalStackContainer.Service;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+import org.testcontainers.utility.MountableFile;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class S3BucketInitializer implements BeforeAllCallback {
+
+ private static final DockerImageName LOCALSTACK_IMAGE = DockerImageName.parse("localstack/localstack:3.3");
+ private static final LocalStackContainer localStackContainer = new LocalStackContainer(LOCALSTACK_IMAGE)
+ .withCopyFileToContainer(MountableFile.forClasspathResource("init-s3-bucket.sh", 0744), "/etc/localstack/init/ready.d/init-s3-bucket.sh")
+ .withServices(Service.S3)
+ .waitingFor(Wait.forLogMessage(".*Executed init-s3-bucket.sh.*", 1));
+
+ // Bucket name as configured in src/test/resources/init-s3-bucket.sh
+ private static final String BUCKET_NAME = "reflectoring-bucket";
+ private static final Integer PRESIGNED_URL_VALIDITY = randomValiditySeconds();
+
+ @Override
+ public void beforeAll(final ExtensionContext context) {
+ log.info("Creating localstack container : {}", LOCALSTACK_IMAGE);
+
+ localStackContainer.start();
+ addConfigurationProperties();
+
+ log.info("Successfully started localstack container : {}", LOCALSTACK_IMAGE);
+ }
+
+ private void addConfigurationProperties() {
+ System.setProperty("spring.cloud.aws.credentials.access-key", localStackContainer.getAccessKey());
+ System.setProperty("spring.cloud.aws.credentials.secret-key", localStackContainer.getSecretKey());
+ System.setProperty("spring.cloud.aws.s3.region", localStackContainer.getRegion());
+ System.setProperty("spring.cloud.aws.s3.endpoint", localStackContainer.getEndpoint().toString());
+
+ System.setProperty("io.reflectoring.aws.s3.bucket-name", BUCKET_NAME);
+ System.setProperty("io.reflectoring.aws.s3.presigned-url.validity", String.valueOf(PRESIGNED_URL_VALIDITY));
+ }
+
+ private static int randomValiditySeconds() {
+ return ThreadLocalRandom.current().nextInt(5, 11);
+ }
+
+ public static String bucketName() {
+ return BUCKET_NAME;
+ }
+
+}
\ No newline at end of file
diff --git a/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/service/StorageServiceIT.java b/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/service/StorageServiceIT.java
new file mode 100644
index 000000000..0543ccdf0
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/test/java/io/reflectoring/service/StorageServiceIT.java
@@ -0,0 +1,205 @@
+package io.reflectoring.service;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.springframework.web.client.RestClient;
+import org.springframework.web.multipart.MultipartFile;
+import org.testcontainers.containers.localstack.LocalStackContainer;
+import org.testcontainers.containers.localstack.LocalStackContainer.Service;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+import org.testcontainers.utility.MountableFile;
+
+import io.awspring.cloud.s3.S3Exception;
+import io.awspring.cloud.s3.S3Template;
+import io.reflectoring.configuration.AwsS3BucketProperties;
+import lombok.SneakyThrows;
+import net.bytebuddy.utility.RandomString;
+import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
+
+@SpringBootTest
+class StorageServiceIT {
+
+ @Autowired
+ private S3Template s3Template;
+
+ @Autowired
+ private StorageService storageService;
+
+ @Autowired
+ private AwsS3BucketProperties awsS3BucketProperties;
+
+ private static final LocalStackContainer localStackContainer;
+
+ // Bucket name as configured in src/test/resources/init-s3-bucket.sh
+ private static final String BUCKET_NAME = "reflectoring-bucket";
+ private static final Integer PRESIGNED_URL_VALIDITY = randomValiditySeconds();
+
+ static {
+ localStackContainer = new LocalStackContainer(DockerImageName.parse("localstack/localstack:3.4"))
+ .withCopyFileToContainer(MountableFile.forClasspathResource("init-s3-bucket.sh", 0744), "/etc/localstack/init/ready.d/init-s3-bucket.sh")
+ .withServices(Service.S3)
+ .waitingFor(Wait.forLogMessage(".*Executed init-s3-bucket.sh.*", 1));
+ localStackContainer.start();
+ }
+
+ @DynamicPropertySource
+ static void properties(DynamicPropertyRegistry registry) {
+ registry.add("spring.cloud.aws.credentials.access-key", localStackContainer::getAccessKey);
+ registry.add("spring.cloud.aws.credentials.secret-key", localStackContainer::getSecretKey);
+ registry.add("spring.cloud.aws.s3.region", localStackContainer::getRegion);
+ registry.add("spring.cloud.aws.s3.endpoint", localStackContainer::getEndpoint);
+
+ registry.add("io.reflectoring.aws.s3.bucket-name", () -> BUCKET_NAME);
+ registry.add("io.reflectoring.aws.s3.presigned-url.validity", () -> PRESIGNED_URL_VALIDITY);
+ }
+
+ @Test
+ void shouldSaveFileSuccessfullyToBucket() {
+ // Prepare test file to upload
+ final var key = RandomString.make(10) + ".txt";
+ final var fileContent = RandomString.make(50);
+ final var fileToUpload = createTextFile(key, fileContent);
+
+ // Invoke method under test
+ storageService.save(fileToUpload);
+
+ // Verify that the file is saved successfully in S3 bucket
+ final var isFileSaved = s3Template.objectExists(BUCKET_NAME, key);
+ assertThat(isFileSaved).isTrue();
+ }
+
+ @Test
+ void saveShouldThrowExceptionForNonExistBucket() {
+ // Prepare test file to upload
+ final var key = RandomString.make(10) + ".txt";
+ final var fileContent = RandomString.make(50);
+ final var fileToUpload = createTextFile(key, fileContent);
+
+ // Configure a non-existent bucket name
+ final var nonExistingBucketName = RandomString.make(20).toLowerCase();
+ awsS3BucketProperties.setBucketName(nonExistingBucketName);
+
+ // Invoke method under test and assert exception
+ final var exception = assertThrows(S3Exception.class, () -> storageService.save(fileToUpload));
+ assertThat(exception.getCause()).hasCauseInstanceOf(NoSuchBucketException.class);
+
+ // Reset the bucket name to the original value
+ awsS3BucketProperties.setBucketName(BUCKET_NAME);
+ }
+
+ @Test
+ @SneakyThrows
+ void shouldFetchSavedFileSuccessfullyFromBucketForValidKey() {
+ // Prepare test file and upload to S3 Bucket
+ final var key = RandomString.make(10) + ".txt";
+ final var fileContent = RandomString.make(50);
+ final var fileToUpload = createTextFile(key, fileContent);
+ storageService.save(fileToUpload);
+
+ // Invoke method under test
+ final var retrievedObject = storageService.retrieve(key);
+
+ // Read the retrieved content and assert integrity
+ final var retrievedContent = readFile(retrievedObject.getContentAsByteArray());
+ assertThat(retrievedContent).isEqualTo(fileContent);
+ }
+
+ @Test
+ void shouldDeleteFileFromBucketSuccessfully() {
+ // Prepare test file and upload to S3 Bucket
+ final var key = RandomString.make(10) + ".txt";
+ final var fileContent = RandomString.make(50);
+ final var fileToUpload = createTextFile(key, fileContent);
+ storageService.save(fileToUpload);
+
+ // Verify that the file is saved successfully in S3 bucket
+ var isFileSaved = s3Template.objectExists(BUCKET_NAME, key);
+ assertThat(isFileSaved).isTrue();
+
+ // Invoke method under test
+ storageService.delete(key);
+
+ // Verify that file is deleted from the S3 bucket
+ isFileSaved = s3Template.objectExists(BUCKET_NAME, key);
+ assertThat(isFileSaved).isFalse();
+ }
+
+ @Test
+ @SneakyThrows
+ void shouldGeneratePresignedUrlToFetchStoredObjectFromBucket() {
+ // Prepare test file and upload to S3 Bucket
+ final var key = RandomString.make(10) + ".txt";
+ final var fileContent = RandomString.make(50);
+ final var fileToUpload = createTextFile(key, fileContent);
+ storageService.save(fileToUpload);
+
+ // Invoke method under test
+ final var presignedUrl = storageService.generateViewablePresignedUrl(key);
+
+ // Perform a GET request to the presigned URL
+ final var restClient = RestClient.builder().build();
+ final var responseBody = restClient.method(HttpMethod.GET).uri(URI.create(presignedUrl.toExternalForm()))
+ .retrieve().body(byte[].class);
+
+ // verify the retrieved content matches the expected file content.
+ final var retrievedContent = new String(responseBody, StandardCharsets.UTF_8);
+ assertThat(fileContent).isEqualTo(retrievedContent);
+ }
+
+ @Test
+ @SneakyThrows
+ void shouldGeneratePresignedUrlForUploadingObjectToBucket() {
+ // Prepare test file to upload
+ final var key = RandomString.make(10) + ".txt";
+ final var fileContent = RandomString.make(50);
+ final var fileToUpload = createTextFile(key, fileContent);
+
+ // Invoke method under test
+ final var presignedUrl = storageService.generateUploadablePresignedUrl(key);
+
+ // Upload the test file using the presigned URL
+ final var restClient = RestClient.builder().build();
+ final var response = restClient.method(HttpMethod.PUT).uri(URI.create(presignedUrl.toExternalForm()))
+ .body(fileToUpload.getBytes()).retrieve().toBodilessEntity();
+ assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
+
+ // Verify that the file is saved successfully in S3 bucket
+ var isFileSaved = s3Template.objectExists(BUCKET_NAME, key);
+ assertThat(isFileSaved).isTrue();
+ }
+
+ private String readFile(byte[] bytes) {
+ final var inputStreamReader = new InputStreamReader(new ByteArrayInputStream(bytes));
+ return new BufferedReader(inputStreamReader).lines().collect(Collectors.joining("\n"));
+ }
+
+ @SneakyThrows
+ private MultipartFile createTextFile(final String fileName, final String content) {
+ final var fileContentBytes = content.getBytes();
+ final var inputStream = new ByteArrayInputStream(fileContentBytes);
+ return new MockMultipartFile(fileName, fileName, "text/plain", inputStream);
+ }
+
+ private static int randomValiditySeconds() {
+ return ThreadLocalRandom.current().nextInt(5, 11);
+ }
+
+}
diff --git a/aws/spring-cloud-aws-s3/src/test/resources/init-s3-bucket.sh b/aws/spring-cloud-aws-s3/src/test/resources/init-s3-bucket.sh
new file mode 100644
index 000000000..793209e5a
--- /dev/null
+++ b/aws/spring-cloud-aws-s3/src/test/resources/init-s3-bucket.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+bucket_name="reflectoring-bucket"
+
+awslocal s3api create-bucket --bucket $bucket_name
+
+echo "S3 bucket '$bucket_name' created successfully"
+echo "Executed init-s3-bucket.sh"
\ No newline at end of file
diff --git a/aws/spring-cloud-caching-redis/Dockerfile b/aws/spring-cloud-caching-redis/Dockerfile
new file mode 100644
index 000000000..f5b6f2314
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/Dockerfile
@@ -0,0 +1,5 @@
+FROM --platform=linux/amd64 adoptopenjdk/openjdk11:jre-11.0.10_9-alpine
+ARG JAR_FILE=build/libs/*.jar
+COPY ${JAR_FILE} service.jar
+EXPOSE 8080
+ENTRYPOINT [ "sh", "-c", "java -jar -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 service.jar" ]
diff --git a/aws/spring-cloud-caching-redis/README.md b/aws/spring-cloud-caching-redis/README.md
new file mode 100644
index 000000000..f69b0d695
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/README.md
@@ -0,0 +1,4 @@
+# Caching In Spring Boot Application with ElastiCache for Redis
+
+* This example showcases how you can configure spring cache and connect it with
+AWS ElastiCache
diff --git a/aws/spring-cloud-caching-redis/build.gradle b/aws/spring-cloud-caching-redis/build.gradle
new file mode 100644
index 000000000..b46d9a0cc
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/build.gradle
@@ -0,0 +1,44 @@
+plugins {
+ id 'org.springframework.boot' version '2.4.5'
+ id 'io.spring.dependency-management' version '1.0.11.RELEASE'
+ id 'java'
+}
+
+group = 'io.reflectoring'
+version = '0.0.1-SNAPSHOT'
+sourceCompatibility = '11'
+
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+ implementation 'org.springframework.boot:spring-boot-starter-validation'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ implementation 'org.springframework.boot:spring-boot-starter-cache'
+ implementation 'org.springframework.boot:spring-boot-starter-data-redis'
+ implementation 'io.awspring.cloud:spring-cloud-starter-aws'
+// implementation 'com.amazonaws:aws-java-sdk-cloudformation'
+ implementation 'com.amazonaws:aws-java-sdk-elasticache'
+ compileOnly 'org.projectlombok:lombok'
+ runtimeOnly 'com.h2database:h2'
+ annotationProcessor 'org.projectlombok:lombok'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+dependencyManagement {
+ imports {
+ mavenBom 'io.awspring.cloud:spring-cloud-aws-dependencies:2.3.1'
+ }
+}
+
+test {
+ useJUnitPlatform()
+}
diff --git a/aws/spring-cloud-caching-redis/gradle/wrapper/gradle-wrapper.jar b/aws/spring-cloud-caching-redis/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..e708b1c02
Binary files /dev/null and b/aws/spring-cloud-caching-redis/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/spring-cloud/sleuth-upstream-service/gradle/wrapper/gradle-wrapper.properties b/aws/spring-cloud-caching-redis/gradle/wrapper/gradle-wrapper.properties
similarity index 92%
rename from spring-cloud/sleuth-upstream-service/gradle/wrapper/gradle-wrapper.properties
rename to aws/spring-cloud-caching-redis/gradle/wrapper/gradle-wrapper.properties
index 38c1d48d1..442d9132e 100644
--- a/spring-cloud/sleuth-upstream-service/gradle/wrapper/gradle-wrapper.properties
+++ b/aws/spring-cloud-caching-redis/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
diff --git a/spring-cloud/sleuth-downstream-service/gradlew b/aws/spring-cloud-caching-redis/gradlew
similarity index 74%
rename from spring-cloud/sleuth-downstream-service/gradlew
rename to aws/spring-cloud-caching-redis/gradlew
index 4453ccea3..4f906e0c8 100755
--- a/spring-cloud/sleuth-downstream-service/gradlew
+++ b/aws/spring-cloud-caching-redis/gradlew
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,16 +44,16 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
-warn ( ) {
+warn () {
echo "$*"
}
-die ( ) {
+die () {
echo
echo "$*"
echo
@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -138,35 +156,30 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
- i=$((i+1))
+ i=`expr $i + 1`
done
case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
-save ( ) {
+save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
-APP_ARGS=$(save "$@")
+APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
-fi
-
exec "$JAVACMD" "$@"
diff --git a/spring-cloud/sleuth-downstream-service/gradlew.bat b/aws/spring-cloud-caching-redis/gradlew.bat
similarity index 66%
rename from spring-cloud/sleuth-downstream-service/gradlew.bat
rename to aws/spring-cloud-caching-redis/gradlew.bat
index f9553162f..107acd32c 100644
--- a/spring-cloud/sleuth-downstream-service/gradlew.bat
+++ b/aws/spring-cloud-caching-redis/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/aws/spring-cloud-caching-redis/settings.gradle b/aws/spring-cloud-caching-redis/settings.gradle
new file mode 100644
index 000000000..43a95ed0b
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'spring-cloud-redis'
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/SpringCloudRedisApplication.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/SpringCloudRedisApplication.java
new file mode 100644
index 000000000..19757810f
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/SpringCloudRedisApplication.java
@@ -0,0 +1,12 @@
+package io.reflectoring.springcloudredis;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringCloudRedisApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringCloudRedisApplication.class, args);
+ }
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/configuration/EnableCache.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/configuration/EnableCache.java
new file mode 100644
index 000000000..5655b53e2
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/configuration/EnableCache.java
@@ -0,0 +1,10 @@
+package io.reflectoring.springcloudredis.configuration;
+
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableCaching
+public class EnableCache {
+
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/controller/ProductController.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/controller/ProductController.java
new file mode 100644
index 000000000..e08f41b1c
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/controller/ProductController.java
@@ -0,0 +1,41 @@
+package io.reflectoring.springcloudredis.controller;
+
+import io.reflectoring.springcloudredis.entity.Product;
+import io.reflectoring.springcloudredis.model.ProductInput;
+import io.reflectoring.springcloudredis.service.ProductService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+@Slf4j(topic = "PRODUCT_CONTROLLER")
+@RestController
+@RequestMapping("/product")
+@AllArgsConstructor
+public class ProductController {
+ private final ProductService productService;
+
+ @GetMapping("/{id}")
+ public Product getProduct(@PathVariable String id){
+ return productService.getProduct(id);
+ }
+
+ @DeleteMapping("/{id}")
+ public void deleteProduct(@PathVariable String id){
+ productService.deleteProduct(id);
+ }
+
+ @PutMapping("/{id}")
+ public Product updateProduct(@PathVariable String id, @RequestBody @Valid ProductInput input){
+ return productService.updateProduct(id, input);
+ }
+
+ @PostMapping
+ public Product addProduct(@RequestBody @Valid ProductInput input){
+ return productService.addProduct(input);
+ }
+
+
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/controller/UserController.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/controller/UserController.java
new file mode 100644
index 000000000..9f061c279
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/controller/UserController.java
@@ -0,0 +1,24 @@
+package io.reflectoring.springcloudredis.controller;
+
+import io.reflectoring.springcloudredis.entity.User;
+import io.reflectoring.springcloudredis.service.UserService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Slf4j(topic = "PRODUCT_CONTROLLER")
+@RestController
+@RequestMapping("/user")
+@AllArgsConstructor
+public class UserController {
+
+ private final UserService userService;
+
+ @GetMapping("/{id}")
+ public User getUser(@PathVariable String id) {
+ return userService.getUser(id);
+ }
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/Category.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/Category.java
new file mode 100644
index 000000000..fd1fd4999
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/Category.java
@@ -0,0 +1,12 @@
+package io.reflectoring.springcloudredis.entity;
+
+import java.io.Serializable;
+
+public enum Category implements Serializable {
+ MOBILE,
+ TV_APPLIANCES,
+ MEN_FASHION,
+ WOMEN_FASHION,
+ BOOKS,
+ BEAUTY
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/Product.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/Product.java
new file mode 100644
index 000000000..b62060a92
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/Product.java
@@ -0,0 +1,44 @@
+package io.reflectoring.springcloudredis.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Entity
+@Getter
+@Setter
+public class Product implements Serializable {
+ @Id
+ private String id;
+
+ private String name;
+
+ private Double price;
+
+ private LocalDateTime manufacturingDate;
+
+ @Transient
+ private Object data;
+
+ private Double weight;
+
+ @Embedded
+ private Dimension dimension;
+
+ @Enumerated(EnumType.STRING)
+ private Category category;
+
+ @Embeddable
+ @Getter
+ @Setter
+ public static class Dimension implements Serializable {
+ private Double height;
+
+ private Double width;
+ }
+
+
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/User.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/User.java
new file mode 100644
index 000000000..38ecef33b
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/entity/User.java
@@ -0,0 +1,20 @@
+package io.reflectoring.springcloudredis.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.io.Serializable;
+
+@Entity
+@Getter
+@Setter
+public class User implements Serializable {
+ @Id
+ private String id;
+
+ private String firstName;
+
+ private String lastName;
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/model/ProductInput.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/model/ProductInput.java
new file mode 100644
index 000000000..718e68037
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/model/ProductInput.java
@@ -0,0 +1,23 @@
+package io.reflectoring.springcloudredis.model;
+
+import io.reflectoring.springcloudredis.entity.Category;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class ProductInput {
+
+ @NotBlank
+ private String name;
+
+ @NotNull
+ private Double price;
+
+ private Double weight;
+
+ private Category category;
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/repository/ProductRepository.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/repository/ProductRepository.java
new file mode 100644
index 000000000..71208317e
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/repository/ProductRepository.java
@@ -0,0 +1,9 @@
+package io.reflectoring.springcloudredis.repository;
+
+import io.reflectoring.springcloudredis.entity.Product;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProductRepository extends JpaRepository {
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/repository/UserRepository.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/repository/UserRepository.java
new file mode 100644
index 000000000..ee78a1f24
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/repository/UserRepository.java
@@ -0,0 +1,9 @@
+package io.reflectoring.springcloudredis.repository;
+
+import io.reflectoring.springcloudredis.entity.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface UserRepository extends JpaRepository {
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/service/ProductService.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/service/ProductService.java
new file mode 100644
index 000000000..e5ded288d
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/service/ProductService.java
@@ -0,0 +1,52 @@
+package io.reflectoring.springcloudredis.service;
+
+import io.reflectoring.springcloudredis.entity.Category;
+import io.reflectoring.springcloudredis.entity.Product;
+import io.reflectoring.springcloudredis.model.ProductInput;
+import io.reflectoring.springcloudredis.repository.ProductRepository;
+import lombok.AllArgsConstructor;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+
+@Service
+@AllArgsConstructor
+@CacheConfig(cacheNames = "product-cache")
+public class ProductService {
+ private final ProductRepository repository;
+
+ @Cacheable
+ public Product getProduct(String id) {
+ return repository.findById(id).orElseThrow(()->
+ new RuntimeException("No such product found with id"));
+ }
+
+ public Product addProduct(ProductInput productInput){
+ var product = new Product();
+ product.setName(productInput.getName());
+ product.setPrice(productInput.getPrice());
+ product.setWeight(product.getWeight());
+ product.setCategory(Objects.isNull(productInput.getCategory())? Category.BOOKS: productInput.getCategory());
+ return repository.save(product);
+ }
+
+ @CacheEvict
+ public void deleteProduct(String id) {
+ repository.deleteById(id);
+ }
+
+ @CachePut(key = "#id")
+ public Product updateProduct(String id, ProductInput productInput) {
+ var product = new Product();
+ product.setId(id);
+ product.setName(productInput.getName());
+ product.setPrice(productInput.getPrice());
+ product.setWeight(product.getWeight());
+ product.setCategory(Objects.isNull(productInput.getCategory())? Category.BOOKS: productInput.getCategory());
+ return repository.save(product);
+ }
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/service/UserService.java b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/service/UserService.java
new file mode 100644
index 000000000..0a6f64e43
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/java/io/reflectoring/springcloudredis/service/UserService.java
@@ -0,0 +1,22 @@
+package io.reflectoring.springcloudredis.service;
+
+import io.reflectoring.springcloudredis.entity.User;
+import io.reflectoring.springcloudredis.repository.UserRepository;
+import lombok.AllArgsConstructor;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+@CacheConfig(cacheNames = "product-cache")
+public class UserService {
+
+ private final UserRepository repository;
+
+ @Cacheable
+ public User getUser(String id){
+ return repository.findById(id).orElseThrow(()->
+ new RuntimeException("No such user found with id"));
+ }
+}
diff --git a/aws/spring-cloud-caching-redis/src/main/resources/application.yaml b/aws/spring-cloud-caching-redis/src/main/resources/application.yaml
new file mode 100644
index 000000000..ac41674d7
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/resources/application.yaml
@@ -0,0 +1,24 @@
+spring:
+ datasource:
+ initialization-mode: always
+ application:
+ name: spring-cloud-redis
+ jpa:
+ show-sql: true
+ generate-ddl: true
+ hibernate:
+ ddl-auto: create-drop
+#cloud:
+# aws:
+# stack:
+# name: spring-cache-2
+cloud:
+ aws:
+ elasticache:
+ clusters:
+ -
+ name: product-cache
+ expiration: 100
+ -
+ name: user-cache
+ expiration: 6000
diff --git a/aws/spring-cloud-caching-redis/src/main/resources/data.sql b/aws/spring-cloud-caching-redis/src/main/resources/data.sql
new file mode 100644
index 000000000..eb6f4b5bc
--- /dev/null
+++ b/aws/spring-cloud-caching-redis/src/main/resources/data.sql
@@ -0,0 +1,39 @@
+insert into product
+(id, name, price, manufacturing_date, weight, height, width, category)
+values
+('prod_1', 'one plus 8T', 100, now(), 2.2, 3.4, 5.4, 'MOBILE');
+
+insert into product
+(id, name, price, manufacturing_date, weight, height, width, category)
+values
+('prod_2', 'Samsung 100 S', 200, now(), 5.6, 7.9, 4.3, 'MOBILE');
+
+insert into product
+(id, name, price, manufacturing_date, weight, height, width, category)
+values
+('prod_3', 'Armani jacket size 32', 1100, now(), 1.3, 10.4, 29.5, 'MEN_FASHION');
+
+insert into product
+(id, name, price, manufacturing_date, weight, height, width, category)
+values
+('prod_4', 'Zara purse', 500, now(), 3.7, 50.6, 70.6, 'WOMEN_FASHION');
+
+insert into product
+(id, name, price, manufacturing_date, weight, height, width, category)
+values
+('prod_5', 'Sony Bravia ', 2000, now(), 25.5, 48.8, 25.9, 'TV_APPLIANCES');
+
+insert into product
+(id, name, price, manufacturing_date, weight, height, width, category)
+values
+('prod_6', 'zara jacket green color', 1500, now(), 1.3, 10.4, 29.5, 'MEN_FASHION');
+
+insert into user
+(id, first_name, last_name)
+values
+('user_1', 'john', 'doe');
+
+insert into user
+(id, first_name, last_name)
+values
+('user_2', 'richard', 'mayor');
diff --git a/aws/spring-cloud-sns-sqs-pubsub/.gitignore b/aws/spring-cloud-sns-sqs-pubsub/.gitignore
new file mode 100644
index 000000000..aa1ef7223
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/.gitignore
@@ -0,0 +1,4 @@
+target
+.project
+.settings
+.DS_Store
diff --git a/aws/spring-cloud-sns-sqs-pubsub/.mvn/wrapper/maven-wrapper.jar b/aws/spring-cloud-sns-sqs-pubsub/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..cb28b0e37
Binary files /dev/null and b/aws/spring-cloud-sns-sqs-pubsub/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/spring-cloud-sns-sqs-pubsub/.mvn/wrapper/maven-wrapper.properties b/aws/spring-cloud-sns-sqs-pubsub/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..5f0536eb7
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/aws/spring-cloud-sns-sqs-pubsub/README.md b/aws/spring-cloud-sns-sqs-pubsub/README.md
new file mode 100644
index 000000000..3ad27502e
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/README.md
@@ -0,0 +1,18 @@
+## Publisher-Subscriber Pattern using AWS SNS and SQS in Spring Boot
+
+Codebase demonstrating the implementation of publisher-subscriber pattern using AWS SNS and SQS in Spring Boot. [Spring Cloud AWS](https://spring.io/projects/spring-cloud-aws) is used to interact with AWS services in context.
+
+[LocalStack](https://github.com/localstack/localstack) has been used to containerize the multi-module Maven project for local development. The below commands can be used to start the applications:
+
+```bash
+./mvnw clean package spring-boot:build-image
+```
+```bash
+sudo docker-compose up -d
+```
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Publisher-Subscriber Pattern using AWS SNS and SQS in Spring Boot](https://reflectoring.io/publisher-subscriber-pattern-using-aws-sns-and-sqs-in-spring-boot)
diff --git a/aws/spring-cloud-sns-sqs-pubsub/docker-compose.yml b/aws/spring-cloud-sns-sqs-pubsub/docker-compose.yml
new file mode 100644
index 000000000..bae6c8451
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/docker-compose.yml
@@ -0,0 +1,52 @@
+version: '3.7'
+
+services:
+ localstack:
+ container_name: localstack
+ image: localstack/localstack:3.3
+ ports:
+ - 4566:4566
+ environment:
+ - SERVICES=sns,sqs
+ volumes:
+ - ./localstack/init-sns-topic.sh:/etc/localstack/init/ready.d/init-sns-topic.sh
+ - ./localstack/init-sqs-queue.sh:/etc/localstack/init/ready.d/init-sqs-queue.sh
+ - ./localstack/subscribe-sqs-to-sns.sh:/etc/localstack/init/ready.d/subscribe-sqs-to-sns.sh
+ networks:
+ - reflectoring
+
+ user-management-service:
+ container_name: user-management-service
+ image: aws-pubsub-user-management-service
+ ports:
+ - 8080:8080
+ depends_on:
+ - localstack
+ environment:
+ spring.cloud.aws.sns.endpoint: 'http://localstack:4566'
+ spring.cloud.aws.credentials.access-key: test
+ spring.cloud.aws.credentials.secret-key: test
+ spring.cloud.aws.sns.region: 'us-east-1'
+ io.reflectoring.aws.sns.topic-arn: 'arn:aws:sns:us-east-1:000000000000:user-account-created'
+ networks:
+ - reflectoring
+
+ notification-dispatcher-service:
+ container_name: notification-dispatcher-service
+ image: aws-pubsub-notification-dispatcher-service
+ ports:
+ - 9090:8080
+ depends_on:
+ - localstack
+ - user-management-service
+ environment:
+ spring.cloud.aws.sqs.endpoint: 'http://localstack:4566'
+ spring.cloud.aws.credentials.access-key: test
+ spring.cloud.aws.credentials.secret-key: test
+ spring.cloud.aws.sqs.region: 'us-east-1'
+ io.reflectoring.aws.sqs.queue-url: 'http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/dispatch-email-notification'
+ networks:
+ - reflectoring
+
+networks:
+ reflectoring:
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/.gitignore b/aws/spring-cloud-sns-sqs-pubsub/integration-test/.gitignore
new file mode 100644
index 000000000..549e00a2a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/.mvn/wrapper/maven-wrapper.jar b/aws/spring-cloud-sns-sqs-pubsub/integration-test/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..cb28b0e37
Binary files /dev/null and b/aws/spring-cloud-sns-sqs-pubsub/integration-test/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/.mvn/wrapper/maven-wrapper.properties b/aws/spring-cloud-sns-sqs-pubsub/integration-test/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..5f0536eb7
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/mvnw b/aws/spring-cloud-sns-sqs-pubsub/integration-test/mvnw
new file mode 100755
index 000000000..66df28542
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/mvnw.cmd b/aws/spring-cloud-sns-sqs-pubsub/integration-test/mvnw.cmd
new file mode 100644
index 000000000..95ba6f54a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/pom.xml b/aws/spring-cloud-sns-sqs-pubsub/integration-test/pom.xml
new file mode 100644
index 000000000..4057f5551
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/pom.xml
@@ -0,0 +1,67 @@
+
+
+
+ 4.0.0
+
+
+ io.reflectoring
+ aws-pubsub
+ 0.0.1
+ ../pom.xml
+
+
+ integration-test
+ integration-test
+ Integration testing the publisher subscriber functionality of this proof-of-concept
+
+
+ 21
+
+
+
+
+ io.reflectoring
+ user-management-service
+ 0.0.1
+
+
+ io.reflectoring
+ notification-dispatcher-service
+ 0.0.1
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+ org.testcontainers
+ localstack
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/main/java/io/reflectoring/Application.java b/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/main/java/io/reflectoring/Application.java
new file mode 100644
index 000000000..7dd263b8d
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/main/java/io/reflectoring/Application.java
@@ -0,0 +1,13 @@
+package io.reflectoring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/test/java/io/reflectoring/PubSubIT.java b/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/test/java/io/reflectoring/PubSubIT.java
new file mode 100644
index 000000000..5d71cc888
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/test/java/io/reflectoring/PubSubIT.java
@@ -0,0 +1,96 @@
+package io.reflectoring;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.util.concurrent.TimeUnit;
+
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.system.CapturedOutput;
+import org.springframework.boot.test.system.OutputCaptureExtension;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.springframework.test.web.servlet.MockMvc;
+import org.testcontainers.containers.localstack.LocalStackContainer;
+import org.testcontainers.containers.localstack.LocalStackContainer.Service;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+import org.testcontainers.utility.MountableFile;
+
+import lombok.SneakyThrows;
+import net.bytebuddy.utility.RandomString;
+
+@AutoConfigureMockMvc
+@ExtendWith(OutputCaptureExtension.class)
+@SpringBootTest(classes = Application.class)
+class PubSubIT {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ private static final LocalStackContainer localStackContainer;
+
+ // as configured in initializing hook script 'provision-resources.sh' in src/test/resources
+ private static final String TOPIC_ARN = "arn:aws:sns:us-east-1:000000000000:user-account-created";
+ private static final String QUEUE_URL = "http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/dispatch-email-notification";
+
+ static {
+ localStackContainer = new LocalStackContainer(DockerImageName.parse("localstack/localstack:3.4"))
+ .withCopyFileToContainer(MountableFile.forClasspathResource("provision-resources.sh", 0744), "/etc/localstack/init/ready.d/provision-resources.sh")
+ .withServices(Service.SNS, Service.SQS)
+ .waitingFor(Wait.forLogMessage(".*Successfully provisioned resources.*", 1));
+ localStackContainer.start();
+ }
+
+ @DynamicPropertySource
+ static void properties(DynamicPropertyRegistry registry) {
+ registry.add("spring.cloud.aws.credentials.access-key", localStackContainer::getAccessKey);
+ registry.add("spring.cloud.aws.credentials.secret-key", localStackContainer::getSecretKey);
+
+ registry.add("spring.cloud.aws.sns.region", localStackContainer::getRegion);
+ registry.add("spring.cloud.aws.sns.endpoint", localStackContainer::getEndpoint);
+ registry.add("io.reflectoring.aws.sns.topic-arn", () -> TOPIC_ARN);
+
+ registry.add("spring.cloud.aws.sqs.region", localStackContainer::getRegion);
+ registry.add("spring.cloud.aws.sqs.endpoint", localStackContainer::getEndpoint);
+ registry.add("io.reflectoring.aws.sqs.queue-url", () -> QUEUE_URL);
+ }
+
+ @Test
+ @SneakyThrows
+ void test(CapturedOutput output) {
+ // prepare API request body to create user
+ final var name = RandomString.make();
+ final var emailId = RandomString.make() + "@reflectoring.io";
+ final var password = RandomString.make();
+ final var userCreationRequestBody = String.format("""
+ {
+ "name" : "%s",
+ "emailId" : "%s",
+ "password" : "%s"
+ }
+ """, name, emailId, password);
+
+ // execute API request to create user
+ final var userCreationApiPath = "/api/v1/users";
+ mockMvc.perform(post(userCreationApiPath)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(userCreationRequestBody))
+ .andExpect(status().isCreated());
+
+ // assert that message has been published to SNS topic
+ final var expectedPublisherLog = String.format("Successfully published message to topic ARN: %s", TOPIC_ARN);
+ Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> output.getAll().contains(expectedPublisherLog));
+
+ // assert that message has been received by the SQS queue
+ final var expectedSubscriberLog = String.format("Dispatching account creation email to %s on %s", name, emailId);
+ Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> output.getAll().contains(expectedSubscriberLog));
+ }
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/test/resources/provision-resources.sh b/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/test/resources/provision-resources.sh
new file mode 100644
index 000000000..121bf79c4
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/integration-test/src/test/resources/provision-resources.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+topic_name="user-account-created"
+queue_name="dispatch-email-notification"
+
+sns_arn_prefix="arn:aws:sns:us-east-1:000000000000"
+sqs_arn_prefix="arn:aws:sqs:us-east-1:000000000000"
+
+awslocal sns create-topic --name $topic_name
+echo "SNS topic '$topic_name' created successfully"
+
+awslocal sqs create-queue --queue-name $queue_name
+echo "SQS queue '$queue_name' created successfully"
+
+awslocal sns subscribe --topic-arn "$sns_arn_prefix:$topic_name" --protocol sqs --notification-endpoint "$sqs_arn_prefix:$queue_name"
+echo "Subscribed SQS queue '$queue_name' to SNS topic '$topic_name' successfully"
+
+echo "Successfully provisioned resources"
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/localstack/init-sns-topic.sh b/aws/spring-cloud-sns-sqs-pubsub/localstack/init-sns-topic.sh
new file mode 100755
index 000000000..14e480ced
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/localstack/init-sns-topic.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+topic_name="user-account-created"
+
+awslocal sns create-topic --name $topic_name
+
+echo "SNS topic '$topic_name' created successfully"
+echo "Executed init-sns-topic.sh"
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/localstack/init-sqs-queue.sh b/aws/spring-cloud-sns-sqs-pubsub/localstack/init-sqs-queue.sh
new file mode 100755
index 000000000..93dc9ec28
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/localstack/init-sqs-queue.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+queue_name="dispatch-email-notification"
+
+awslocal sqs create-queue --queue-name $queue_name
+
+echo "SQS queue '$queue_name' created successfully"
+echo "Executed init-sqs-queue.sh"
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/localstack/subscribe-sqs-to-sns.sh b/aws/spring-cloud-sns-sqs-pubsub/localstack/subscribe-sqs-to-sns.sh
new file mode 100755
index 000000000..5dff55b53
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/localstack/subscribe-sqs-to-sns.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+topic_name="user-account-created"
+queue_name="dispatch-email-notification"
+
+awslocal sns subscribe --topic-arn "arn:aws:sns:us-east-1:000000000000:$topic_name" --protocol sqs --notification-endpoint "arn:aws:sqs:us-east-1:000000000000:$queue_name"
+
+echo "Subscribed SQS queue '$queue_name' to SNS topic '$topic_name' successfully"
+echo "Executed subscribe-sqs-to-sns.sh"
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/mvnw b/aws/spring-cloud-sns-sqs-pubsub/mvnw
new file mode 100755
index 000000000..66df28542
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/spring-cloud-sns-sqs-pubsub/mvnw.cmd b/aws/spring-cloud-sns-sqs-pubsub/mvnw.cmd
new file mode 100644
index 000000000..95ba6f54a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.gitignore b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.gitignore
new file mode 100644
index 000000000..549e00a2a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.mvn/wrapper/maven-wrapper.jar b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..cb28b0e37
Binary files /dev/null and b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.mvn/wrapper/maven-wrapper.properties b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..5f0536eb7
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/mvnw b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/mvnw
new file mode 100755
index 000000000..66df28542
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/mvnw.cmd b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/mvnw.cmd
new file mode 100644
index 000000000..95ba6f54a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/pom.xml b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/pom.xml
new file mode 100644
index 000000000..2e8e0a96c
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ 4.0.0
+
+
+ io.reflectoring
+ aws-pubsub
+ 0.0.1
+ ../pom.xml
+
+
+ notification-dispatcher-service
+ notification-dispatcher-service
+ Microservice acting as a subscriber to an AWS SQS queue
+
+
+ ${project.parent.artifactId}-${project.artifactId}
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-starter-sqs
+
+
+
+
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/SubscriberApplication.java b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/SubscriberApplication.java
new file mode 100644
index 000000000..2df73612b
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/SubscriberApplication.java
@@ -0,0 +1,13 @@
+package io.reflectoring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SubscriberApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SubscriberApplication.class, args);
+ }
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/configuration/AwsSqsQueueProperties.java b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/configuration/AwsSqsQueueProperties.java
new file mode 100644
index 000000000..a6dc7df19
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/configuration/AwsSqsQueueProperties.java
@@ -0,0 +1,19 @@
+package io.reflectoring.configuration;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Validated
+@ConfigurationProperties(prefix = "io.reflectoring.aws.sqs")
+public class AwsSqsQueueProperties {
+
+ @NotBlank(message = "SQS queue URL must be configured")
+ private String queueUrl;
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/dto/UserCreatedEventDto.java b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/dto/UserCreatedEventDto.java
new file mode 100644
index 000000000..ebf3da74e
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/dto/UserCreatedEventDto.java
@@ -0,0 +1,13 @@
+package io.reflectoring.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class UserCreatedEventDto {
+
+ private String name;
+ private String emailId;
+
+}
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/listener/EmailNotificationListener.java b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/listener/EmailNotificationListener.java
new file mode 100644
index 000000000..2865d72d7
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/java/io/reflectoring/listener/EmailNotificationListener.java
@@ -0,0 +1,22 @@
+package io.reflectoring.listener;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.stereotype.Component;
+import io.awspring.cloud.sqs.annotation.SqsListener;
+import io.awspring.cloud.sqs.annotation.SnsNotificationMessage;
+import io.reflectoring.configuration.AwsSqsQueueProperties;
+import io.reflectoring.dto.UserCreatedEventDto;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+@EnableConfigurationProperties(AwsSqsQueueProperties.class)
+public class EmailNotificationListener {
+
+ @SqsListener("${io.reflectoring.aws.sqs.queue-url}")
+ public void listen(@SnsNotificationMessage final UserCreatedEventDto userCreatedEvent) {
+ log.info("Dispatching account creation email to {} on {}", userCreatedEvent.getName(), userCreatedEvent.getEmailId());
+ // business logic to send email
+ }
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/resources/application.yaml b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/resources/application.yaml
new file mode 100644
index 000000000..b42b5f5dd
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/notification-dispatcher-service/src/main/resources/application.yaml
@@ -0,0 +1,14 @@
+spring:
+ cloud:
+ aws:
+ credentials:
+ access-key: ${AWS_ACCESS_KEY}
+ secret-key: ${AWS_SECRET_KEY}
+ sqs:
+ region: ${AWS_SQS_REGION}
+
+io:
+ reflectoring:
+ aws:
+ sqs:
+ queue-url: ${AWS_SQS_QUEUE_URL}
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/pom.xml b/aws/spring-cloud-sns-sqs-pubsub/pom.xml
new file mode 100644
index 000000000..5b8e661ac
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/pom.xml
@@ -0,0 +1,103 @@
+
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+ io.reflectoring
+ aws-pubsub
+ 0.0.1
+ pom
+
+
+ 21
+ 3.1.1
+
+
+
+
+ hardikSinghBehl
+ Hardik Singh Behl
+ behl.hardiksingh@gmail.com
+
+ Developer
+
+ UTC +5:30
+
+
+
+
+ user-management-service
+ notification-dispatcher-service
+ integration-test
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws
+ ${spring.cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ ${java.version}
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.gitignore b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.gitignore
new file mode 100644
index 000000000..549e00a2a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.mvn/wrapper/maven-wrapper.jar b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..cb28b0e37
Binary files /dev/null and b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.mvn/wrapper/maven-wrapper.properties b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..5f0536eb7
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/lombok.config b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/lombok.config
new file mode 100644
index 000000000..a886d4642
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/lombok.config
@@ -0,0 +1 @@
+lombok.nonNull.exceptionType=IllegalArgumentException
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/mvnw b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/mvnw
new file mode 100755
index 000000000..66df28542
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/mvnw.cmd b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/mvnw.cmd
new file mode 100644
index 000000000..95ba6f54a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/pom.xml b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/pom.xml
new file mode 100644
index 000000000..f992bf553
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ 4.0.0
+
+
+ io.reflectoring
+ aws-pubsub
+ 0.0.1
+ ../pom.xml
+
+
+ user-management-service
+ user-management-service
+ Microservice acting as a publisher to an AWS SNS topic
+
+
+ ${project.parent.artifactId}-${project.artifactId}
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-starter-sns
+
+
+
+
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/PublisherApplication.java b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/PublisherApplication.java
new file mode 100644
index 000000000..8fc70791a
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/PublisherApplication.java
@@ -0,0 +1,13 @@
+package io.reflectoring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PublisherApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PublisherApplication.class, args);
+ }
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/configuration/AwsSnsTopicProperties.java b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/configuration/AwsSnsTopicProperties.java
new file mode 100644
index 000000000..70a9362d8
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/configuration/AwsSnsTopicProperties.java
@@ -0,0 +1,19 @@
+package io.reflectoring.configuration;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Validated
+@ConfigurationProperties(prefix = "io.reflectoring.aws.sns")
+public class AwsSnsTopicProperties {
+
+ @NotBlank(message = "SNS topic ARN must be configured")
+ private String topicArn;
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/controller/UserController.java b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/controller/UserController.java
new file mode 100644
index 000000000..6e7043343
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/controller/UserController.java
@@ -0,0 +1,29 @@
+package io.reflectoring.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.reflectoring.dto.UserCreationRequestDto;
+import io.reflectoring.service.UserService;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/api/v1/users")
+public class UserController {
+
+ private final UserService userService;
+
+ @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity createUser(@Valid @RequestBody final UserCreationRequestDto userCreationRequest) {
+ userService.create(userCreationRequest);
+ return ResponseEntity.status(HttpStatus.CREATED).build();
+ }
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/dto/UserCreatedEventDto.java b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/dto/UserCreatedEventDto.java
new file mode 100644
index 000000000..ebf3da74e
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/dto/UserCreatedEventDto.java
@@ -0,0 +1,13 @@
+package io.reflectoring.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class UserCreatedEventDto {
+
+ private String name;
+ private String emailId;
+
+}
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/dto/UserCreationRequestDto.java b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/dto/UserCreationRequestDto.java
new file mode 100644
index 000000000..a54729527
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/dto/UserCreationRequestDto.java
@@ -0,0 +1,20 @@
+package io.reflectoring.dto;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Getter;
+
+@Getter
+public class UserCreationRequestDto {
+
+ @NotBlank(message = "Name must not be empty")
+ private String name;
+
+ @NotBlank(message = "EmailId must not be empty")
+ @Email(message = "EmailId must be of valid format")
+ private String emailId;
+
+ @NotBlank(message = "Password must not be empty")
+ private String password;
+
+}
\ No newline at end of file
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/service/UserService.java b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/service/UserService.java
new file mode 100644
index 000000000..5cc0cf017
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/java/io/reflectoring/service/UserService.java
@@ -0,0 +1,39 @@
+package io.reflectoring.service;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.stereotype.Service;
+
+import io.awspring.cloud.sns.core.SnsTemplate;
+import io.reflectoring.configuration.AwsSnsTopicProperties;
+import io.reflectoring.dto.UserCreatedEventDto;
+import io.reflectoring.dto.UserCreationRequestDto;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@EnableConfigurationProperties(AwsSnsTopicProperties.class)
+public class UserService {
+
+ private final SnsTemplate snsTemplate;
+ private final AwsSnsTopicProperties awsSnsTopicProperties;
+
+ public void create(@NonNull final UserCreationRequestDto userCreationRequest) {
+ // save user record in database
+
+ final var topicArn = awsSnsTopicProperties.getTopicArn();
+ final var payload = convert(userCreationRequest);
+ snsTemplate.convertAndSend(topicArn, payload);
+ log.info("Successfully published message to topic ARN: {}", topicArn);
+ }
+
+ private UserCreatedEventDto convert(@NonNull final UserCreationRequestDto userCreationRequest) {
+ final var userCreatedEvent = new UserCreatedEventDto();
+ userCreatedEvent.setName(userCreationRequest.getName());
+ userCreatedEvent.setEmailId(userCreationRequest.getEmailId());
+ return userCreatedEvent;
+ }
+
+}
diff --git a/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/resources/application.yaml b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/resources/application.yaml
new file mode 100644
index 000000000..00b74ea4f
--- /dev/null
+++ b/aws/spring-cloud-sns-sqs-pubsub/user-management-service/src/main/resources/application.yaml
@@ -0,0 +1,14 @@
+spring:
+ cloud:
+ aws:
+ credentials:
+ access-key: ${AWS_ACCESS_KEY}
+ secret-key: ${AWS_SECRET_KEY}
+ sns:
+ region: ${AWS_SNS_REGION}
+
+io:
+ reflectoring:
+ aws:
+ sns:
+ topic-arn: ${AWS_SNS_TOPIC_ARN}
\ No newline at end of file
diff --git a/aws/springcloudrds/.mvn/wrapper/MavenWrapperDownloader.java b/aws/springcloudrds/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/aws/springcloudrds/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/aws/springcloudrds/.mvn/wrapper/maven-wrapper.jar b/aws/springcloudrds/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/aws/springcloudrds/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/springcloudrds/.mvn/wrapper/maven-wrapper.properties b/aws/springcloudrds/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/aws/springcloudrds/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/aws/springcloudrds/README.md b/aws/springcloudrds/README.md
new file mode 100644
index 000000000..61b95a5dd
--- /dev/null
+++ b/aws/springcloudrds/README.md
@@ -0,0 +1,10 @@
+# Working with AWS RDS and Spring Cloud
+
+Example code for using Spring Cloud AWS JDBC
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Working with AWS RDS and Spring Cloud](https://reflectoring.io/spring-cloud-aws-rds/)
+
diff --git a/aws/springcloudrds/mvnw b/aws/springcloudrds/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/aws/springcloudrds/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/springcloudrds/mvnw.cmd b/aws/springcloudrds/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/aws/springcloudrds/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/aws/springcloudrds/pom.xml b/aws/springcloudrds/pom.xml
new file mode 100644
index 000000000..c40df3f14
--- /dev/null
+++ b/aws/springcloudrds/pom.xml
@@ -0,0 +1,89 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.5
+
+
+ io.pratik
+ springcloudrds
+ 0.0.1-SNAPSHOT
+ springcloudrds
+ Demo project for Spring Cloud RDS
+
+ 11
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ io.awspring.cloud
+ spring-cloud-starter-aws-jdbc
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ org.aspectj
+ aspectjrt
+
+
+ org.aspectj
+ aspectjweaver
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-dependencies
+ 2.3.0
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+
diff --git a/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/ApplicationConfiguration.java b/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/ApplicationConfiguration.java
new file mode 100644
index 000000000..ade9eb530
--- /dev/null
+++ b/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/ApplicationConfiguration.java
@@ -0,0 +1,27 @@
+/**
+ *
+ */
+package io.pratik.springcloudrds;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import io.awspring.cloud.jdbc.config.annotation.RdsInstanceConfigurer;
+import io.awspring.cloud.jdbc.datasource.TomcatJdbcDataSourceFactory;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Configuration
+public class ApplicationConfiguration {
+ @Bean
+ public RdsInstanceConfigurer instanceConfigurer() {
+ return ()-> {
+ TomcatJdbcDataSourceFactory dataSourceFactory = new TomcatJdbcDataSourceFactory();
+ dataSourceFactory.setInitialSize(10);
+ dataSourceFactory.setValidationQuery("SELECT 1 FROM DUAL");
+ return dataSourceFactory;
+ };
+ }
+}
diff --git a/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/SpringcloudrdsApplication.java b/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/SpringcloudrdsApplication.java
new file mode 100644
index 000000000..1bf148b26
--- /dev/null
+++ b/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/SpringcloudrdsApplication.java
@@ -0,0 +1,13 @@
+package io.pratik.springcloudrds;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringcloudrdsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringcloudrdsApplication.class, args);
+ }
+
+}
diff --git a/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/SystemRepository.java b/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/SystemRepository.java
new file mode 100644
index 000000000..38575f38e
--- /dev/null
+++ b/aws/springcloudrds/src/main/java/io/pratik/springcloudrds/SystemRepository.java
@@ -0,0 +1,58 @@
+/**
+ *
+ */
+package io.pratik.springcloudrds;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Service
+public class SystemRepository {
+
+ private final JdbcTemplate jdbcTemplate;
+
+ @Autowired
+ public SystemRepository(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ public String getCurrentDate() {
+ String result = jdbcTemplate.queryForObject("SELECT CURRENT_DATE FROM DUAL", new RowMapper(){
+
+ @Override
+ public String mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return rs.getString(1);
+ }
+
+ });
+ return result;
+ }
+
+
+ @Transactional(readOnly = true)
+ public List getUsers(){
+ List result = jdbcTemplate.query("SELECT USER() FROM DUAL", new RowMapper(){
+
+ @Override
+ public String mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return rs.getString(1);
+ }
+
+ });
+ return result;
+ }
+
+}
diff --git a/aws/springcloudrds/src/main/resources/application.properties b/aws/springcloudrds/src/main/resources/application.properties
new file mode 100644
index 000000000..82829d9b5
--- /dev/null
+++ b/aws/springcloudrds/src/main/resources/application.properties
@@ -0,0 +1,10 @@
+cloud.aws.credentials.profile-name=pratikpoc
+cloud.aws.region.auto=false
+cloud.aws.region.static=us-east-1
+
+cloud.aws.rds.instances[0].db-instance-identifier=testinstance
+cloud.aws.rds.instances[0].username=pocadmin
+cloud.aws.rds.instances[0].password=pocadmin
+cloud.aws.rds.instances[0].databaseName=mysql
+
+cloud.aws.rds.instances[0].readReplicaSupport=true
diff --git a/aws/springcloudrds/src/main/resources/beanconfig.xml b/aws/springcloudrds/src/main/resources/beanconfig.xml
new file mode 100644
index 000000000..731bbeb5d
--- /dev/null
+++ b/aws/springcloudrds/src/main/resources/beanconfig.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aws/springcloudrds/src/test/java/io/pratik/springcloudrds/SpringcloudrdsApplicationTests.java b/aws/springcloudrds/src/test/java/io/pratik/springcloudrds/SpringcloudrdsApplicationTests.java
new file mode 100644
index 000000000..ef533d4a9
--- /dev/null
+++ b/aws/springcloudrds/src/test/java/io/pratik/springcloudrds/SpringcloudrdsApplicationTests.java
@@ -0,0 +1,19 @@
+package io.pratik.springcloudrds;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class SpringcloudrdsApplicationTests {
+
+ @Autowired
+ private SystemRepository systemRepository;
+
+ @Test
+ void testCurrentDate() {
+ String currentDate = systemRepository.getCurrentDate();
+ System.out.println("currentDate "+currentDate);
+ }
+
+}
diff --git a/aws/springcloudses/.mvn/wrapper/MavenWrapperDownloader.java b/aws/springcloudses/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/aws/springcloudses/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/aws/springcloudses/.mvn/wrapper/maven-wrapper.jar b/aws/springcloudses/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/aws/springcloudses/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/springcloudses/.mvn/wrapper/maven-wrapper.properties b/aws/springcloudses/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/aws/springcloudses/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/aws/springcloudses/README.md b/aws/springcloudses/README.md
new file mode 100644
index 000000000..828d9a823
--- /dev/null
+++ b/aws/springcloudses/README.md
@@ -0,0 +1,10 @@
+# Working with AWS SES and Spring Cloud
+
+Example code for using Spring Cloud AWS SES
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Working with AWS SES and Spring Cloud](https://reflectoring.io/spring-cloud-aws-ses/)
+
diff --git a/aws/springcloudses/mvnw b/aws/springcloudses/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/aws/springcloudses/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/springcloudses/mvnw.cmd b/aws/springcloudses/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/aws/springcloudses/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/aws/springcloudses/pom.xml b/aws/springcloudses/pom.xml
new file mode 100644
index 000000000..27429724f
--- /dev/null
+++ b/aws/springcloudses/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+ io.pratik
+ springses
+ 0.0.1-SNAPSHOT
+ springses
+ Demo project for Sending email with SES
+
+ 11
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+ io.awspring.cloud
+ spring-cloud-starter-aws-ses
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-dependencies
+ 2.3.0
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+
diff --git a/aws/springcloudses/src/main/java/io/pratik/springses/MailConfig.java b/aws/springcloudses/src/main/java/io/pratik/springses/MailConfig.java
new file mode 100644
index 000000000..0ddf625e6
--- /dev/null
+++ b/aws/springcloudses/src/main/java/io/pratik/springses/MailConfig.java
@@ -0,0 +1,43 @@
+/**
+ *
+ */
+package io.pratik.springses;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.mail.MailSender;
+import org.springframework.mail.javamail.JavaMailSender;
+
+import com.amazonaws.auth.profile.ProfileCredentialsProvider;
+import com.amazonaws.regions.Regions;
+import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
+import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
+
+import io.awspring.cloud.ses.SimpleEmailServiceJavaMailSender;
+import io.awspring.cloud.ses.SimpleEmailServiceMailSender;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Configuration
+public class MailConfig {
+ @Bean
+ public AmazonSimpleEmailService amazonSimpleEmailService() {
+
+ return AmazonSimpleEmailServiceClientBuilder.standard()
+ .withCredentials(new ProfileCredentialsProvider("pratikpoc"))
+ .withRegion(Regions.US_EAST_1)
+ .build();
+ }
+
+ @Bean
+ public JavaMailSender javaMailSender(AmazonSimpleEmailService amazonSimpleEmailService) {
+ return new SimpleEmailServiceJavaMailSender(amazonSimpleEmailService);
+ }
+
+ @Bean
+ public MailSender mailSender(AmazonSimpleEmailService amazonSimpleEmailService) {
+ return new SimpleEmailServiceMailSender(amazonSimpleEmailService);
+ }
+}
diff --git a/aws/springcloudses/src/main/java/io/pratik/springses/NotificationService.java b/aws/springcloudses/src/main/java/io/pratik/springses/NotificationService.java
new file mode 100644
index 000000000..aaa9128c2
--- /dev/null
+++ b/aws/springcloudses/src/main/java/io/pratik/springses/NotificationService.java
@@ -0,0 +1,53 @@
+/**
+ *
+ */
+package io.pratik.springses;
+
+import javax.mail.internet.MimeMessage;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.InputStreamSource;
+import org.springframework.mail.MailSender;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.mail.javamail.MimeMessagePreparator;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Service
+public class NotificationService {
+
+ @Autowired
+ private MailSender mailSender;
+
+ @Autowired
+ private JavaMailSender javaMailSender;
+
+ public void sendMailMessage(final SimpleMailMessage simpleMailMessage) {
+ System.out.println("mailSender "+mailSender.getClass().getName());
+ this.mailSender.send(simpleMailMessage);
+ }
+
+ public void sendMailMessageWithAttachments() {
+ this.javaMailSender.send(new MimeMessagePreparator() {
+
+ @Override
+ public void prepare(MimeMessage mimeMessage) throws Exception {
+ MimeMessageHelper helper =
+ new MimeMessageHelper(mimeMessage, true, "UTF-8");
+ helper.addTo("foo@bar.com");
+ helper.setFrom("bar@baz.com");
+
+ InputStreamSource data = new ByteArrayResource("".getBytes());
+ helper.addAttachment("test.txt", data );
+ helper.setSubject("test subject with attachment");
+ helper.setText("mime body", false);
+ }
+ });
+ }
+}
diff --git a/aws/springcloudses/src/main/java/io/pratik/springses/SpringsesApplication.java b/aws/springcloudses/src/main/java/io/pratik/springses/SpringsesApplication.java
new file mode 100644
index 000000000..03ced6c06
--- /dev/null
+++ b/aws/springcloudses/src/main/java/io/pratik/springses/SpringsesApplication.java
@@ -0,0 +1,13 @@
+package io.pratik.springses;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringsesApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringsesApplication.class, args);
+ }
+
+}
diff --git a/aws/springcloudses/src/main/resources/application.properties b/aws/springcloudses/src/main/resources/application.properties
new file mode 100644
index 000000000..7f88691f7
--- /dev/null
+++ b/aws/springcloudses/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+cloud.aws.credentials.profile-name=pratikpoc
+cloud.aws.region.auto=false
+cloud.aws.region.static=us-east-1
+
diff --git a/aws/springcloudses/src/test/java/io/pratik/springses/NotificationServiceTest.java b/aws/springcloudses/src/test/java/io/pratik/springses/NotificationServiceTest.java
new file mode 100644
index 000000000..29e835613
--- /dev/null
+++ b/aws/springcloudses/src/test/java/io/pratik/springses/NotificationServiceTest.java
@@ -0,0 +1,61 @@
+/**
+ *
+ */
+package io.pratik.springses;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.mail.SimpleMailMessage;
+
+/**
+ * @author pratikdas
+ *
+ */
+@SpringBootTest
+class NotificationServiceTest {
+
+ @Autowired
+ private NotificationService notificationService;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeEach
+ void setUp() throws Exception {
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @AfterEach
+ void tearDown() throws Exception {
+ }
+
+ @Test
+ void testSendMail() {
+ SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
+ simpleMailMessage.setFrom("pratikd2000@gmail.com");
+ simpleMailMessage.setTo("pratikd2027@gmail.com");
+ simpleMailMessage.setSubject("test subject");
+ simpleMailMessage.setText("test text");
+
+ notificationService.sendMailMessage(simpleMailMessage);
+ }
+
+ @Test
+ void testSendMailWithAttachments() {
+ SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
+ simpleMailMessage.setFrom("pratikd2000@gmail.com");
+ simpleMailMessage.setTo("pratikd2027@gmail.com");
+ simpleMailMessage.setSubject("test subject");
+ simpleMailMessage.setText("test text");
+
+ notificationService.sendMailMessage(simpleMailMessage);
+ }
+
+}
diff --git a/aws/springcloudses/src/test/java/io/pratik/springses/SpringsesApplicationTests.java b/aws/springcloudses/src/test/java/io/pratik/springses/SpringsesApplicationTests.java
new file mode 100644
index 000000000..f27d9efd5
--- /dev/null
+++ b/aws/springcloudses/src/test/java/io/pratik/springses/SpringsesApplicationTests.java
@@ -0,0 +1,13 @@
+package io.pratik.springses;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class SpringsesApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/aws/springcloudsqs/.mvn/wrapper/MavenWrapperDownloader.java b/aws/springcloudsqs/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/aws/springcloudsqs/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/aws/springcloudsqs/.mvn/wrapper/maven-wrapper.jar b/aws/springcloudsqs/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/aws/springcloudsqs/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/springcloudsqs/.mvn/wrapper/maven-wrapper.properties b/aws/springcloudsqs/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/aws/springcloudsqs/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/aws/springcloudsqs/README.md b/aws/springcloudsqs/README.md
new file mode 100644
index 000000000..69f0e05e6
--- /dev/null
+++ b/aws/springcloudsqs/README.md
@@ -0,0 +1,10 @@
+# Working with AWS SQS and Spring Cloud
+
+Example code for using Spring Cloud AWS Messaging
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Working with AWS SQS and Spring Cloud](https://reflectoring.io/spring-cloud-aws-sqs/)
+
diff --git a/aws/springcloudsqs/mvnw b/aws/springcloudsqs/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/aws/springcloudsqs/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/springcloudsqs/mvnw.cmd b/aws/springcloudsqs/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/aws/springcloudsqs/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/aws/springcloudsqs/pom.xml b/aws/springcloudsqs/pom.xml
new file mode 100644
index 000000000..51903b47c
--- /dev/null
+++ b/aws/springcloudsqs/pom.xml
@@ -0,0 +1,67 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.5
+
+
+ io.pratik
+ springcloudsqs
+ 0.0.1-SNAPSHOT
+ springcloudsqs
+ Demo project for Spring Cloud AWS SQS
+
+ 11
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ io.awspring.cloud
+ spring-cloud-starter-aws-messaging
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-dependencies
+ 2.3.0
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+
diff --git a/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/CustomSqsConfiguration.java b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/CustomSqsConfiguration.java
new file mode 100644
index 000000000..781f8fb98
--- /dev/null
+++ b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/CustomSqsConfiguration.java
@@ -0,0 +1,53 @@
+/**
+ *
+ */
+package io.pratik.springcloudsqs;
+
+import java.util.Collections;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.messaging.converter.MappingJackson2MessageConverter;
+import org.springframework.messaging.converter.MessageConverter;
+import org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver;
+
+import com.amazonaws.services.sqs.AmazonSQSAsync;
+import com.amazonaws.services.sqs.buffered.AmazonSQSBufferedAsyncClient;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import io.awspring.cloud.messaging.config.QueueMessageHandlerFactory;
+import io.awspring.cloud.messaging.core.QueueMessagingTemplate;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Configuration
+public class CustomSqsConfiguration {
+
+ @Bean
+ public QueueMessagingTemplate queueMessagingTemplate(AmazonSQSAsync amazonSQSAsync) {
+ return new QueueMessagingTemplate(amazonSQSAsync);
+ }
+
+ @Bean
+ public QueueMessageHandlerFactory queueMessageHandlerFactory(final ObjectMapper mapper,
+ final AmazonSQSAsync amazonSQSAsync) {
+ final QueueMessageHandlerFactory queueHandlerFactory = new QueueMessageHandlerFactory();
+ queueHandlerFactory.setAmazonSqs(amazonSQSAsync);
+
+ queueHandlerFactory.setArgumentResolvers(
+ Collections.singletonList(new PayloadMethodArgumentResolver(jackson2MessageConverter(mapper))));
+ return queueHandlerFactory;
+ }
+
+ private MessageConverter jackson2MessageConverter(final ObjectMapper mapper) {
+
+ final MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
+
+ // set strict content type match to false to enable the listener to handle AWS events
+ converter.setStrictContentTypeMatch(false);
+ converter.setObjectMapper(mapper);
+ return converter;
+ }
+}
diff --git a/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageReceiver.java b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageReceiver.java
new file mode 100644
index 000000000..670bfb622
--- /dev/null
+++ b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageReceiver.java
@@ -0,0 +1,42 @@
+/**
+ *
+ */
+package io.pratik.springcloudsqs;
+
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Service;
+
+import com.amazonaws.services.s3.event.S3EventNotification;
+
+import io.awspring.cloud.messaging.listener.SqsMessageDeletionPolicy;
+import io.awspring.cloud.messaging.listener.annotation.SqsListener;
+import io.pratik.springcloudsqs.models.SignupEvent;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Slf4j
+@Service
+public class MessageReceiver {
+
+ @SqsListener(value = "testQueue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS )
+ public void receiveStringMessage(final String message,
+ @Header("SenderId") String senderId) {
+ log.info("message received {} {}",senderId,message);
+ }
+
+ @SqsListener(value = "testObjectQueue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS )
+ public void receiveObjectMessage(final SignupEvent message,
+ @Header("SenderId") String senderId) {
+ log.info("object message received {} {}",senderId,message);
+ }
+
+ @SqsListener(value = "testS3Queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
+ public void receiveS3Event(S3EventNotification s3EventNotificationRecord) {
+ S3EventNotification.S3Entity s3Entity = s3EventNotificationRecord.getRecords().get(0).getS3();
+ String objectKey = s3Entity.getObject().getKey();
+ log.info("s3 event::objectKey:: {}",objectKey);
+ }
+}
diff --git a/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageSender.java b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageSender.java
new file mode 100644
index 000000000..39cffd050
--- /dev/null
+++ b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageSender.java
@@ -0,0 +1,52 @@
+/**
+ *
+ */
+package io.pratik.springcloudsqs;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+
+import com.amazonaws.services.sqs.AmazonSQSAsync;
+
+import io.awspring.cloud.messaging.core.QueueMessageChannel;
+import io.awspring.cloud.messaging.core.QueueMessagingTemplate;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Service
+public class MessageSender {
+ private static final Logger logger = LoggerFactory.getLogger(MessageSender.class);
+
+ private static final String QUEUE_NAME = "https://sqs.us-east-1.amazonaws.com/474715013863/testQueue";
+
+ @Autowired
+ private final AmazonSQSAsync amazonSqs;
+
+ @Autowired
+ public MessageSender(final AmazonSQSAsync amazonSQSAsync) {
+ this.amazonSqs = amazonSQSAsync;
+ }
+
+ public boolean send(final String messagePayload) {
+ MessageChannel messageChannel = new QueueMessageChannel(amazonSqs, QUEUE_NAME);
+
+ Message msg = MessageBuilder.withPayload(messagePayload)
+ .setHeader("sender", "app1")
+ .setHeaderIfAbsent("country", "AE")
+ .build();
+
+ long waitTimeoutMillis = 5000;
+ boolean sentStatus = messageChannel.send(msg,waitTimeoutMillis);
+ logger.info("message sent");
+ return sentStatus;
+ }
+
+}
diff --git a/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageSenderWithTemplate.java b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageSenderWithTemplate.java
new file mode 100644
index 000000000..459e5acc2
--- /dev/null
+++ b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/MessageSenderWithTemplate.java
@@ -0,0 +1,45 @@
+/**
+ *
+ */
+package io.pratik.springcloudsqs;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.stereotype.Service;
+
+import io.awspring.cloud.messaging.core.QueueMessagingTemplate;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Slf4j
+@Service
+public class MessageSenderWithTemplate {
+ private static final String TEST_QUEUE = "testQueue";
+
+ @Autowired
+ private QueueMessagingTemplate messagingTemplate;
+
+ public void send(final String messagePayload) {
+
+ Message msg = MessageBuilder.withPayload(messagePayload)
+ .setHeader("sender", "app1")
+ .setHeaderIfAbsent("country", "AE")
+ .build();
+ messagingTemplate.convertAndSend(TEST_QUEUE, msg);
+ log.info("message sent");
+ }
+
+ public void sendToFifoQueue(final String messagePayload, final String messageGroupID, final String messageDedupID) {
+
+ Message msg = MessageBuilder.withPayload(messagePayload)
+ .setHeader("message-group-id", messageGroupID)
+ .setHeader("message-deduplication-id", messageDedupID)
+ .build();
+ messagingTemplate.convertAndSend(TEST_QUEUE, msg);
+ log.info("message sent");
+ }
+}
diff --git a/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/SpringcloudsqsApplication.java b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/SpringcloudsqsApplication.java
new file mode 100644
index 000000000..15e262fc6
--- /dev/null
+++ b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/SpringcloudsqsApplication.java
@@ -0,0 +1,12 @@
+package io.pratik.springcloudsqs;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringcloudsqsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringcloudsqsApplication.class, args);
+ }
+}
diff --git a/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/models/SignupEvent.java b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/models/SignupEvent.java
new file mode 100644
index 000000000..be6ba897a
--- /dev/null
+++ b/aws/springcloudsqs/src/main/java/io/pratik/springcloudsqs/models/SignupEvent.java
@@ -0,0 +1,19 @@
+/**
+ *
+ */
+package io.pratik.springcloudsqs.models;
+
+import lombok.Data;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Data
+public class SignupEvent {
+
+ private String signupTime;
+ private String userName;
+ private String email;
+
+}
diff --git a/aws/springcloudsqs/src/main/resources/application.properties b/aws/springcloudsqs/src/main/resources/application.properties
new file mode 100644
index 000000000..a15033aa3
--- /dev/null
+++ b/aws/springcloudsqs/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+cloud.aws.credentials.profile-name=default
+cloud.aws.region.auto=false
+cloud.aws.region.static=us-east-1
diff --git a/aws/springcloudsqs/src/test/java/io/pratik/springcloudsqs/SpringcloudsqsApplicationTests.java b/aws/springcloudsqs/src/test/java/io/pratik/springcloudsqs/SpringcloudsqsApplicationTests.java
new file mode 100644
index 000000000..02a866fd0
--- /dev/null
+++ b/aws/springcloudsqs/src/test/java/io/pratik/springcloudsqs/SpringcloudsqsApplicationTests.java
@@ -0,0 +1,34 @@
+package io.pratik.springcloudsqs;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class SpringcloudsqsApplicationTests {
+ private static final Logger logger = LoggerFactory.getLogger(SpringcloudsqsApplicationTests.class.getName());
+
+ @Autowired
+ private MessageSender messageSender;
+
+ @Autowired
+ private MessageSenderWithTemplate messageSenderWithTemplate;
+
+ @Test
+ void contextLoads() {
+ }
+
+ void send_message_with_message_template() {
+ logger.info("test with message template.");
+ messageSenderWithTemplate.send("Test Message1");
+ }
+
+ @Test
+ void send_message_with_message_channel() {
+ logger.info("test with message channel.");
+ messageSender.send("Test msg");
+ }
+
+}
diff --git a/aws/springcloudwatch/.mvn/wrapper/MavenWrapperDownloader.java b/aws/springcloudwatch/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/aws/springcloudwatch/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/aws/springcloudwatch/.mvn/wrapper/maven-wrapper.jar b/aws/springcloudwatch/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/aws/springcloudwatch/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/springcloudwatch/.mvn/wrapper/maven-wrapper.properties b/aws/springcloudwatch/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/aws/springcloudwatch/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/aws/springcloudwatch/README.md b/aws/springcloudwatch/README.md
new file mode 100644
index 000000000..c2e7e20d3
--- /dev/null
+++ b/aws/springcloudwatch/README.md
@@ -0,0 +1,9 @@
+# Publishing Metrics from Spring Boot Application to Amazon CloudWatch
+
+Example code for using Spring Boot Application with Amazon CloudWatch
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Publishing Metrics from Spring Boot Application to Amazon CloudWatch](https://reflectoring.io/spring-aws-cloudwatch/)
diff --git a/aws/springcloudwatch/mvnw b/aws/springcloudwatch/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/aws/springcloudwatch/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/springcloudwatch/mvnw.cmd b/aws/springcloudwatch/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/aws/springcloudwatch/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/aws/springcloudwatch/pom.xml b/aws/springcloudwatch/pom.xml
new file mode 100644
index 000000000..fd13456d9
--- /dev/null
+++ b/aws/springcloudwatch/pom.xml
@@ -0,0 +1,90 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.3
+
+
+ io.pratik
+ metricscapture
+ 0.0.1-SNAPSHOT
+ metricscapture
+ Demo project for capturing cloudwatch metrics in Spring Boot
+
+ 11
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ io.micrometer
+ micrometer-core
+
+
+
+
+ io.micrometer
+ micrometer-registry-cloudwatch2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-dependencies
+ 2.3.0
+ pom
+ import
+
+
+ software.amazon.awssdk
+ bom
+ 2.17.14
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/AppConfig.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/AppConfig.java
new file mode 100644
index 000000000..e67fb874f
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/AppConfig.java
@@ -0,0 +1,62 @@
+/**
+ *
+ */
+package io.pratik.metricscapture;
+
+import java.time.Duration;
+import java.util.Map;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import io.micrometer.cloudwatch2.CloudWatchConfig;
+import io.micrometer.cloudwatch2.CloudWatchMeterRegistry;
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Metrics;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Configuration
+public class AppConfig {
+
+
+
+ @Bean
+ public CloudWatchAsyncClient cloudWatchAsyncClient() {
+ return CloudWatchAsyncClient.builder().region(Region.US_EAST_1)
+ .credentialsProvider(ProfileCredentialsProvider.create("pratikpoc")).build();
+ }
+
+ @Bean
+ public MeterRegistry getMeterRegistry() {
+ CloudWatchConfig cloudWatchConfig = setupCloudWatchConfig();
+
+ MeterRegistry meterRegistry = new CloudWatchMeterRegistry(cloudWatchConfig, Clock.SYSTEM,
+ cloudWatchAsyncClient());
+
+ return meterRegistry;
+ }
+
+ private CloudWatchConfig setupCloudWatchConfig() {
+ CloudWatchConfig cloudWatchConfig = new CloudWatchConfig() {
+
+ private Map configuration
+ = Map.of("cloudwatch.namespace", "productsApp",
+ "cloudwatch.step", Duration.ofMinutes(1).toString());
+
+ @Override
+ public String get(String key) {
+ return configuration.get(key);
+ }
+ };
+ return cloudWatchConfig;
+ }
+
+}
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/MetricPublisher.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/MetricPublisher.java
new file mode 100644
index 000000000..2c1913a28
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/MetricPublisher.java
@@ -0,0 +1,87 @@
+/**
+ *
+ */
+package io.pratik.metricscapture;
+
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import io.pratik.metricscapture.models.MetricTag;
+import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient;
+import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
+import software.amazon.awssdk.services.cloudwatch.model.Dimension;
+import software.amazon.awssdk.services.cloudwatch.model.MetricDatum;
+import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataRequest;
+import software.amazon.awssdk.services.cloudwatch.model.StandardUnit;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Service
+public class MetricPublisher {
+
+ private CloudWatchAsyncClient cloudWatchAsyncClient;
+
+
+ @Autowired
+ public MetricPublisher(CloudWatchAsyncClient cloudWatchAsyncClient) {
+ super();
+ this.cloudWatchAsyncClient = cloudWatchAsyncClient;
+ }
+
+
+
+ public void putMetricData(final String nameSpace,
+ final String metricName,
+ final Double dataPoint,
+ final List metricTags) {
+
+ try {
+
+ List dimensions = metricTags
+ .stream()
+ .map((metricTag)->{
+ return Dimension
+ .builder()
+ .name(metricTag.getName())
+ .value(metricTag.getValue())
+ .build();
+ }).collect(Collectors.toList());
+
+ // Set an Instant object
+ String time = ZonedDateTime
+ .now(ZoneOffset.UTC)
+ .format(DateTimeFormatter.ISO_INSTANT);
+ Instant instant = Instant.parse(time);
+
+ MetricDatum datum = MetricDatum
+ .builder()
+ .metricName(metricName)
+ .unit(StandardUnit.NONE)
+ .value(dataPoint)
+ .timestamp(instant)
+ .dimensions(dimensions)
+ .build();
+
+ PutMetricDataRequest request =
+ PutMetricDataRequest
+ .builder()
+ .namespace(nameSpace)
+ .metricData(datum)
+ .build();
+
+ cloudWatchAsyncClient.putMetricData(request);
+
+ } catch (CloudWatchException e) {
+ System.err.println(e.awsErrorDetails().errorMessage());
+ }
+ }
+}
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/MetricscaptureApplication.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/MetricscaptureApplication.java
new file mode 100644
index 000000000..230e325ff
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/MetricscaptureApplication.java
@@ -0,0 +1,27 @@
+package io.pratik.metricscapture;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.client.RestTemplate;
+
+@SpringBootApplication
+@EnableScheduling
+public class MetricscaptureApplication {
+
+ @Bean
+ RestTemplate restTemplate(RestTemplateBuilder builder) {
+ return builder
+ .messageConverters(new StringHttpMessageConverter(), new MappingJackson2HttpMessageConverter())
+ .build();
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(MetricscaptureApplication.class, args);
+ }
+
+}
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/PricingEngine.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/PricingEngine.java
new file mode 100644
index 000000000..4d2d9ab37
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/PricingEngine.java
@@ -0,0 +1,34 @@
+/**
+ *
+ */
+package io.pratik.metricscapture;
+
+import java.util.Random;
+
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Service
+public class PricingEngine {
+
+ private Double price;
+
+ public Double getProductPrice() {
+ return price;
+
+ }
+
+ @Scheduled(fixedRate = 70000)
+ public void computePrice() {
+
+ Random random = new Random();
+ price = random.nextDouble() * 100;
+ System.out.println("computing price "+price);
+
+ }
+
+}
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/ProductController.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/ProductController.java
new file mode 100644
index 000000000..875db2e18
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/ProductController.java
@@ -0,0 +1,89 @@
+/**
+ *
+ */
+package io.pratik.metricscapture;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.micrometer.core.instrument.Counter;
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Timer;
+import io.pratik.metricscapture.models.Order;
+import io.pratik.metricscapture.models.Product;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author pratikdas
+ *
+ */
+@RestController
+@Slf4j
+public class ProductController {
+ private Counter pageViewsCounter;
+ private Timer productTimer;
+ private Gauge priceGauge;
+
+ private MeterRegistry meterRegistry;
+
+ private PricingEngine pricingEngine;
+
+ @Autowired
+ ProductController(MeterRegistry meterRegistry, PricingEngine pricingEngine){
+
+ this.meterRegistry = meterRegistry;
+ this.pricingEngine = pricingEngine;
+
+ priceGauge = Gauge
+ .builder("product.price", pricingEngine ,
+ (pe)->{return pe != null? pe.getProductPrice() : null;})
+ .description("Product price")
+ .baseUnit("ms")
+ .register(meterRegistry);
+
+ pageViewsCounter = meterRegistry
+ .counter("PAGE_VIEWS.ProductList");
+
+ productTimer = meterRegistry
+ .timer("execution.time.fetchProducts");
+
+ }
+
+
+
+
+ @GetMapping("/products")
+ @ResponseBody
+ public List fetchProducts() {
+ long startTime = System.currentTimeMillis();
+
+ List products = fetchProductsFromStore();
+
+ // increment page views counter
+ pageViewsCounter.increment();
+
+ // record time to execute the method
+ System.out.println("productTimer "+productTimer + " " + pageViewsCounter + " " + priceGauge);
+ productTimer.record(Duration.ofMillis(System.currentTimeMillis() - startTime));
+
+ return products;
+ }
+
+ private List fetchProductsFromStore(){
+ List products = new ArrayList();
+ products.add(Product.builder().name("Television").build());
+ products.add(Product.builder().name("Book").build());
+ return products;
+ }
+
+
+
+}
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/MetricTag.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/MetricTag.java
new file mode 100644
index 000000000..2a8317bda
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/MetricTag.java
@@ -0,0 +1,25 @@
+/**
+ *
+ */
+package io.pratik.metricscapture.models;
+
+/**
+ * @author pratikdas
+ *
+ */
+public class MetricTag {
+ private String name;
+ private String value;
+ public MetricTag(String name, String value) {
+ super();
+ this.name = name;
+ this.value = value;
+ }
+ public String getName() {
+ return name;
+ }
+ public String getValue() {
+ return value;
+ }
+
+}
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/Order.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/Order.java
new file mode 100644
index 000000000..e7317d9c5
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/Order.java
@@ -0,0 +1,21 @@
+/**
+ *
+ */
+package io.pratik.metricscapture.models;
+
+import java.util.List;
+
+import lombok.Builder;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Builder
+public class Order {
+ private List products;
+
+ private String orderDate;
+
+
+}
diff --git a/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/Product.java b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/Product.java
new file mode 100644
index 000000000..8dbbd00e5
--- /dev/null
+++ b/aws/springcloudwatch/src/main/java/io/pratik/metricscapture/models/Product.java
@@ -0,0 +1,19 @@
+/**
+ *
+ */
+package io.pratik.metricscapture.models;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Builder
+@Data
+public class Product {
+ private String name;
+ private Double price;
+
+}
diff --git a/aws/springcloudwatch/src/main/resources/application.properties b/aws/springcloudwatch/src/main/resources/application.properties
new file mode 100644
index 000000000..2640097c8
--- /dev/null
+++ b/aws/springcloudwatch/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+cloud.aws.credentials.profile-name=pratikpoc
+cloud.aws.region.auto=false
+cloud.aws.region.static=us-east-1
+
+logging.level.io.micrometer=DEBUG
+
+
+
diff --git a/aws/springcloudwatch/src/test/java/io/pratik/metricscapture/MetricscaptureApplicationTests.java b/aws/springcloudwatch/src/test/java/io/pratik/metricscapture/MetricscaptureApplicationTests.java
new file mode 100644
index 000000000..7610f1b11
--- /dev/null
+++ b/aws/springcloudwatch/src/test/java/io/pratik/metricscapture/MetricscaptureApplicationTests.java
@@ -0,0 +1,13 @@
+package io.pratik.metricscapture;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class MetricscaptureApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/aws/springdynamodb/README.md b/aws/springdynamodb/README.md
new file mode 100644
index 000000000..dced30abe
--- /dev/null
+++ b/aws/springdynamodb/README.md
@@ -0,0 +1,20 @@
+# Working with AWS DynamoDB and Spring
+
+Example code for using Spring AWS DynamoDB
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Working with AWS DynamoDB and Spring ](https://reflectoring.io/spring-dynamodb/)
+
+This is a nested Maven project composed of two modules:
+
+1. dynamodbec: Contains a Spring Boot project which uses Enhanced DynamoDB Client to make database operations on DynamoDB.
+
+2. dynamodbspringdata: Contains a Spring Boot project which uses Spring Data to perform operations on DynamoDB.
+
+In both projects, the Spring Boot dependency is added in the `dependencyManagement` block in `pom.xml`
+.
+
+
diff --git a/aws/springdynamodb/dynamodbec/.mvn/wrapper/MavenWrapperDownloader.java b/aws/springdynamodb/dynamodbec/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbec/.mvn/wrapper/maven-wrapper.jar b/aws/springdynamodb/dynamodbec/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/springdynamodb/dynamodbec/.mvn/wrapper/maven-wrapper.properties b/aws/springdynamodb/dynamodbec/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/aws/springdynamodb/dynamodbec/mvnw b/aws/springdynamodb/dynamodbec/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/springdynamodb/dynamodbec/mvnw.cmd b/aws/springdynamodb/dynamodbec/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/aws/springdynamodb/dynamodbec/pom.xml b/aws/springdynamodb/dynamodbec/pom.xml
new file mode 100644
index 000000000..c99704f09
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/pom.xml
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+
+ io.pratik
+ dynamodbapp
+ 0.0.1-SNAPSHOT
+
+ io.pratik
+ dynamodbec
+ 0.0.1-SNAPSHOT
+ dynamodbec
+ Demo project for Spring Boot for dynamodb enhanced client
+
+ 11
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ software.amazon.awssdk
+ dynamodb-enhanced
+ 2.16.74
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ 2.4.0
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-compiler-plugin
+ 3.5.1
+
+ 11
+ 11
+
+
+
+
+
+
diff --git a/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/DynamodbappsApplication.java b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/DynamodbappsApplication.java
new file mode 100644
index 000000000..d9a6a2458
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/DynamodbappsApplication.java
@@ -0,0 +1,12 @@
+package io.pratik.dynamodbapps;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DynamodbappsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(DynamodbappsApplication.class, args);
+ }
+}
diff --git a/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/OrderRepository.java b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/OrderRepository.java
new file mode 100644
index 000000000..da9c37a5c
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/OrderRepository.java
@@ -0,0 +1,107 @@
+/**
+ *
+ */
+package io.pratik.dynamodbapps;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import io.pratik.dynamodbapps.models.Order;
+import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
+import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
+import software.amazon.awssdk.enhanced.dynamodb.Expression;
+import software.amazon.awssdk.enhanced.dynamodb.Key;
+import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
+import software.amazon.awssdk.enhanced.dynamodb.model.DeleteItemEnhancedRequest;
+import software.amazon.awssdk.enhanced.dynamodb.model.PageIterable;
+import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
+import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Repository
+public class OrderRepository {
+
+ @Autowired
+ private DynamoDbEnhancedClient dynamoDbenhancedClient;
+
+ public OrderRepository() {
+ super();
+ }
+
+ // Store this order item in the database
+ public void save(final Order order) {
+ DynamoDbTable orderTable = getTable();
+ orderTable.putItem(order);
+ }
+
+ /**
+ * @return
+ */
+ private DynamoDbTable getTable() {
+ DynamoDbTable orderTable = dynamoDbenhancedClient.table("Order", TableSchema.fromBean(Order.class));
+ return orderTable;
+ }
+
+ // Retrieve a single order item from the database
+ public Order getOrder(final String customerID, final String orderID) {
+ DynamoDbTable orderTable = getTable();
+ // Construct the key with partition and sort key
+ Key key = Key.builder().partitionValue(customerID).sortValue(orderID).build();
+
+ Order order = orderTable.getItem(key);
+
+ return order;
+ }
+
+ public void deleteOrder(final String customerID, final String orderID) {
+ DynamoDbTable orderTable = getTable();
+
+ Key key = Key.builder().partitionValue(customerID).sortValue(orderID).build();
+
+ DeleteItemEnhancedRequest deleteRequest = DeleteItemEnhancedRequest
+ .builder()
+ .key(key)
+ .build();
+
+ orderTable.deleteItem(deleteRequest);
+ }
+
+ public PageIterable scanOrders(final String customerID, final String orderID) {
+ DynamoDbTable orderTable = getTable();
+
+ return orderTable.scan();
+ }
+
+ public PageIterable findOrdersByValue(final String customerID, final double orderValue) {
+ DynamoDbTable orderTable = getTable();
+
+ AttributeValue attributeValue = AttributeValue.builder()
+ .n(String.valueOf(orderValue))
+ .build();
+
+ Map expressionValues = new HashMap<>();
+ expressionValues.put(":value", attributeValue);
+
+ Expression expression = Expression.builder()
+ .expression("orderValue > :value")
+ .expressionValues(expressionValues)
+ .build();
+
+ // Create a QueryConditional object that is used in the query operation
+ QueryConditional queryConditional = QueryConditional
+ .keyEqualTo(Key.builder().partitionValue(customerID)
+ .build());
+
+ // Get items in the Customer table and write out the ID value
+ PageIterable results = orderTable.query(r -> r.queryConditional(queryConditional).filterExpression(expression));
+ return results;
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/config/AppConfig.java b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/config/AppConfig.java
new file mode 100644
index 000000000..db423bf55
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/config/AppConfig.java
@@ -0,0 +1,37 @@
+/**
+ *
+ */
+package io.pratik.dynamodbapps.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Configuration
+public class AppConfig {
+
+ @Bean
+ public DynamoDbClient getDynamoDbClient() {
+ AwsCredentialsProvider credentialsProvider = DefaultCredentialsProvider.builder().profileName("pratikpoc")
+ .build();
+
+ return DynamoDbClient.builder().region(Region.US_EAST_1).credentialsProvider(credentialsProvider).build();
+ }
+
+ @Bean
+ public DynamoDbEnhancedClient getDynamoDbEnhancedClient() {
+ return DynamoDbEnhancedClient.builder()
+ .dynamoDbClient(getDynamoDbClient())
+ .build();
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Order.java b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Order.java
new file mode 100644
index 000000000..958cf06f8
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Order.java
@@ -0,0 +1,63 @@
+/**
+ *
+ */
+package io.pratik.dynamodbapps.models;
+
+import java.time.Instant;
+import java.util.List;
+
+import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute;
+import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
+import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
+import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;
+
+/**
+ * @author pratikdas
+ *
+ */
+@DynamoDbBean
+public class Order {
+ private String customerID;
+ private String orderID;
+ private double orderValue;
+ private Instant createdDate;
+
+ private List products;
+
+ @DynamoDbPartitionKey
+ @DynamoDbAttribute("CustomerID")
+ public String getCustomerID() {
+ return customerID;
+ }
+ public void setCustomerID(String customerID) {
+ this.customerID = customerID;
+ }
+
+ @DynamoDbSortKey
+ @DynamoDbAttribute("OrderID")
+ public String getOrderID() {
+ return orderID;
+ }
+ public void setOrderID(String orderID) {
+ this.orderID = orderID;
+ }
+
+ public Instant getCreatedDate() {
+ return createdDate;
+ }
+ public void setCreatedDate(Instant createdDate) {
+ this.createdDate = createdDate;
+ }
+ public double getOrderValue() {
+ return orderValue;
+ }
+ public void setOrderValue(double orderValue) {
+ this.orderValue = orderValue;
+ }
+ public List getProducts() {
+ return products;
+ }
+ public void setProducts(List products) {
+ this.products = products;
+ }
+}
diff --git a/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Product.java b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Product.java
new file mode 100644
index 000000000..ab098da03
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Product.java
@@ -0,0 +1,38 @@
+/**
+ *
+ */
+package io.pratik.dynamodbapps.models;
+
+import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
+
+/**
+ * @author pratikdas
+ *
+ */
+@DynamoDbBean
+public class Product {
+ private String name;
+ private String brand;
+ private double price;
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getBrand() {
+ return brand;
+ }
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+ public double getPrice() {
+ return price;
+ }
+ public void setPrice(double price) {
+ this.price = price;
+ }
+
+
+
+}
diff --git a/aws/springdynamodb/dynamodbec/src/main/resources/application.properties b/aws/springdynamodb/dynamodbec/src/main/resources/application.properties
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/aws/springdynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/DynamodbappsApplicationTests.java b/aws/springdynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/DynamodbappsApplicationTests.java
new file mode 100644
index 000000000..9fcc5efb4
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/DynamodbappsApplicationTests.java
@@ -0,0 +1,13 @@
+package io.pratik.dynamodbapps;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class DynamodbappsApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/OrderRepositoryTest.java b/aws/springdynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/OrderRepositoryTest.java
new file mode 100644
index 000000000..68244aec4
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/OrderRepositoryTest.java
@@ -0,0 +1,83 @@
+/**
+ *
+ */
+package io.pratik.dynamodbapps;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import io.pratik.dynamodbapps.models.Order;
+import io.pratik.dynamodbapps.models.Product;
+import software.amazon.awssdk.enhanced.dynamodb.model.PageIterable;
+
+/**
+ * @author pratikdas
+ *
+ */
+@SpringBootTest
+class OrderRepositoryTest {
+
+ @Autowired
+ private OrderRepository orderRepository;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeEach
+ void setUp() throws Exception {
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @AfterEach
+ void tearDown() throws Exception {
+ }
+
+ @Test
+ void testCreateOrder() {
+ Order order = new Order();
+ order.setOrderID("ORD-010");
+ order.setCustomerID("CUST-001");
+
+ List products = new ArrayList();
+
+ Product product = new Product();
+ product.setName("Television");
+ product.setBrand("samsung");
+ product.setPrice(112.56);
+ products.add(product);
+
+ product = new Product();
+ product.setName("Washing Machine");
+ product.setBrand("panasonic");
+ product.setPrice(119.99);
+ products.add(product);
+
+ order.setProducts(products );
+ order.setOrderValue(56.7);
+ order.setCreatedDate(Instant.now());
+ orderRepository.save(order);
+ }
+
+ @Test
+ void testGetOrder() {
+ Order order =
+ orderRepository.getOrder("CUST-001", "ORD-010");
+ System.out.println("order "+order.getProducts());
+ }
+
+ @Test
+ void testFindOrdersByValue() {
+ PageIterable orders =
+ orderRepository.findOrdersByValue("CUST-001", 5.0d);
+ System.out.println("orders "+orders.items());
+ }
+}
diff --git a/aws/springdynamodb/dynamodbec/target/classes/application.properties b/aws/springdynamodb/dynamodbec/target/classes/application.properties
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/target/classes/application.properties
@@ -0,0 +1 @@
+
diff --git a/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/DynamodbappsApplication.class b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/DynamodbappsApplication.class
new file mode 100644
index 000000000..610609343
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/DynamodbappsApplication.class differ
diff --git a/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/OrderRepository.class b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/OrderRepository.class
new file mode 100644
index 000000000..e4a25ea11
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/OrderRepository.class differ
diff --git a/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/config/AppConfig.class b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/config/AppConfig.class
new file mode 100644
index 000000000..1e4fd488c
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/config/AppConfig.class differ
diff --git a/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/models/Order.class b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/models/Order.class
new file mode 100644
index 000000000..4db2bd2f3
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/models/Order.class differ
diff --git a/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/models/Product.class b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/models/Product.class
new file mode 100644
index 000000000..cdd8bc0fa
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/classes/io/pratik/dynamodbapps/models/Product.class differ
diff --git a/aws/springdynamodb/dynamodbec/target/dynamodbec-0.0.1-SNAPSHOT.jar b/aws/springdynamodb/dynamodbec/target/dynamodbec-0.0.1-SNAPSHOT.jar
new file mode 100644
index 000000000..463e94cc2
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/dynamodbec-0.0.1-SNAPSHOT.jar differ
diff --git a/aws/springdynamodb/dynamodbec/target/maven-archiver/pom.properties b/aws/springdynamodb/dynamodbec/target/maven-archiver/pom.properties
new file mode 100644
index 000000000..728926b94
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/target/maven-archiver/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Maven
+#Thu Jun 03 12:13:17 GST 2021
+groupId=io.pratik
+artifactId=dynamodbec
+version=0.0.1-SNAPSHOT
diff --git a/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
new file mode 100644
index 000000000..71dfc288b
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
@@ -0,0 +1,5 @@
+io/pratik/dynamodbapps/models/Product.class
+io/pratik/dynamodbapps/config/AppConfig.class
+io/pratik/dynamodbapps/models/Order.class
+io/pratik/dynamodbapps/OrderRepository.class
+io/pratik/dynamodbapps/DynamodbappsApplication.class
diff --git a/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
new file mode 100644
index 000000000..133ef2e15
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
@@ -0,0 +1,5 @@
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/DynamodbappsApplication.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/OrderRepository.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/config/AppConfig.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Product.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbec/src/main/java/io/pratik/dynamodbapps/models/Order.java
diff --git a/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
new file mode 100644
index 000000000..924e17abc
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
@@ -0,0 +1,2 @@
+io/pratik/dynamodbapps/OrderRepositoryTest.class
+io/pratik/dynamodbapps/DynamodbappsApplicationTests.class
diff --git a/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
new file mode 100644
index 000000000..a25d9357e
--- /dev/null
+++ b/aws/springdynamodb/dynamodbec/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
@@ -0,0 +1,2 @@
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/OrderRepositoryTest.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbec/src/test/java/io/pratik/dynamodbapps/DynamodbappsApplicationTests.java
diff --git a/aws/springdynamodb/dynamodbec/target/test-classes/io/pratik/dynamodbapps/DynamodbappsApplicationTests.class b/aws/springdynamodb/dynamodbec/target/test-classes/io/pratik/dynamodbapps/DynamodbappsApplicationTests.class
new file mode 100644
index 000000000..7c57789b8
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/test-classes/io/pratik/dynamodbapps/DynamodbappsApplicationTests.class differ
diff --git a/aws/springdynamodb/dynamodbec/target/test-classes/io/pratik/dynamodbapps/OrderRepositoryTest.class b/aws/springdynamodb/dynamodbec/target/test-classes/io/pratik/dynamodbapps/OrderRepositoryTest.class
new file mode 100644
index 000000000..5755012d7
Binary files /dev/null and b/aws/springdynamodb/dynamodbec/target/test-classes/io/pratik/dynamodbapps/OrderRepositoryTest.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/MavenWrapperDownloader.java b/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/maven-wrapper.jar b/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/maven-wrapper.properties b/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/aws/springdynamodb/dynamodbspringdata/mvnw b/aws/springdynamodb/dynamodbspringdata/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/springdynamodb/dynamodbspringdata/mvnw.cmd b/aws/springdynamodb/dynamodbspringdata/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/aws/springdynamodb/dynamodbspringdata/pom.xml b/aws/springdynamodb/dynamodbspringdata/pom.xml
new file mode 100644
index 000000000..5ab380fd1
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+ io.pratik
+ dynamodbapp
+ 0.0.1-SNAPSHOT
+
+ io.pratik
+ dynamodbspringdata
+ 0.0.1-SNAPSHOT
+ dynamodbspringdata
+ Demo project for Spring Boot
+
+ 11
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.github.derjust
+ spring-data-dynamodb
+ 5.1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.data
+ spring-data-releasetrain
+ Lovelace-SR1
+ pom
+ import
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ 2.4.0
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-compiler-plugin
+ 3.5.1
+
+ 11
+ 11
+
+
+
+
+
+
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/CustomerService.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/CustomerService.java
new file mode 100644
index 000000000..d4bad32f8
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/CustomerService.java
@@ -0,0 +1,26 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import io.pratik.dynamodbspring.models.Customer;
+import io.pratik.dynamodbspring.repositories.CustomerRepository;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Service
+public class CustomerService {
+
+ @Autowired
+ private CustomerRepository customerRepository;
+
+ public void createCustomer(final Customer customer) {
+ customerRepository.save(customer);
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/DynamodbspringApplication.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/DynamodbspringApplication.java
new file mode 100644
index 000000000..0cd68aff1
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/DynamodbspringApplication.java
@@ -0,0 +1,13 @@
+package io.pratik.dynamodbspring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DynamodbspringApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(DynamodbspringApplication.class, args);
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/OrderService.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/OrderService.java
new file mode 100644
index 000000000..a44846399
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/OrderService.java
@@ -0,0 +1,26 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import io.pratik.dynamodbspring.models.Order;
+import io.pratik.dynamodbspring.repositories.OrderRepository;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Service
+public class OrderService {
+
+ @Autowired
+ private OrderRepository orderRepository;
+
+ public void createOrder(final Order order) {
+ orderRepository.save(order);
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/config/AppConfig.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/config/AppConfig.java
new file mode 100644
index 000000000..e9783c3a9
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/config/AppConfig.java
@@ -0,0 +1,33 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring.config;
+
+import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.auth.profile.ProfileCredentialsProvider;
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
+
+/**
+ * @author pratikdas
+ *
+ */
+@Configuration
+@EnableDynamoDBRepositories
+(basePackages = "io.pratik.dynamodbspring.repositories")
+public class AppConfig {
+
+ @Bean
+ public AmazonDynamoDB amazonDynamoDB() {
+ AWSCredentialsProvider credentials = new ProfileCredentialsProvider("pratikpoc");
+ AmazonDynamoDB amazonDynamoDB
+ = AmazonDynamoDBClientBuilder.standard().withCredentials(credentials).build();
+
+ return amazonDynamoDB;
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Customer.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Customer.java
new file mode 100644
index 000000000..5a407557e
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Customer.java
@@ -0,0 +1,53 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring.models;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
+
+/**
+ * @author pratikdas
+ *
+ */
+@DynamoDBTable(tableName = "Customer")
+public class Customer {
+
+ private String customerID;
+
+ private String name;
+
+ private String email;
+
+ // Partition key
+ @DynamoDBHashKey(attributeName = "CustomerID")
+ public String getCustomerID() {
+ return customerID;
+ }
+
+ public void setCustomerID(String customerID) {
+ this.customerID = customerID;
+ }
+
+ @DynamoDBAttribute(attributeName = "Name")
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @DynamoDBAttribute(attributeName = "Email")
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Order.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Order.java
new file mode 100644
index 000000000..e1faed91c
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Order.java
@@ -0,0 +1,83 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring.models;
+
+import java.time.Instant;
+
+import org.springframework.data.annotation.Id;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
+
+/**
+ * @author pratikdas
+ *
+ */
+@DynamoDBTable(tableName = "Order")
+public class Order {
+ private String customerID;
+ private String orderSerial;
+ private double orderValue;
+ private Instant createdDate;
+
+ @Id
+ private OrderID orderID;
+
+
+
+ public Order() {
+ super();
+ }
+// private List products;
+
+ public Order(OrderID orderID) {
+ super();
+ this.orderID = orderID;
+ }
+ /*
+ * public OrderID getOrderID() { return orderID; } public void
+ * setOrderID(OrderID orderID) { this.orderID = orderID; }
+ */
+ @DynamoDBHashKey(attributeName = "customerID")
+ public String getCustomerID() {
+ return customerID;
+ }
+ public void setCustomerID(String customerID) {
+ this.customerID = customerID;
+ }
+
+ @DynamoDBRangeKey(attributeName = "orderID")
+ public String getOrderSerial() {
+ return orderSerial;
+ }
+ public void setOrderSerial(String orderSerial) {
+ this.orderSerial = orderSerial;
+ }
+
+ @DynamoDBAttribute
+ public Instant getCreatedDate() {
+ return createdDate;
+ }
+ public void setCreatedDate(Instant createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ @DynamoDBAttribute
+ public double getOrderValue() {
+ return orderValue;
+ }
+ public void setOrderValue(double orderValue) {
+ this.orderValue = orderValue;
+ }
+
+ /*@DynamoDBAttribute
+ public List getProducts() {
+ return products;
+ }
+ public void setProducts(List products) {
+ this.products = products;
+ }*/
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/OrderID.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/OrderID.java
new file mode 100644
index 000000000..c89f520ad
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/OrderID.java
@@ -0,0 +1,50 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring.models;
+
+import java.io.Serializable;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
+
+/**
+ * @author pratikdas
+ *
+ */
+public class OrderID implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+ private String customerID;
+ private String orderSerial;
+
+ public OrderID() {
+ super();
+ this.customerID = null;
+ this.orderSerial = null;
+ }
+
+ public OrderID(String customerID, String orderSerial) {
+ super();
+ this.customerID = customerID;
+ this.orderSerial = orderSerial;
+ }
+
+ @DynamoDBHashKey
+ public String getCustomerID() {
+ return customerID;
+ }
+ public void setCustomerID(String customerID) {
+ this.customerID = customerID;
+ }
+
+ @DynamoDBRangeKey
+ public String getOrderSerial() {
+ return orderSerial;
+ }
+ public void setOrderSerial(String orderSerial) {
+ this.orderSerial = orderSerial;
+ }
+
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Product.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Product.java
new file mode 100644
index 000000000..e1c5badf7
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Product.java
@@ -0,0 +1,38 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring.models;
+
+//import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
+
+/**
+ * @author pratikdas
+ *
+ */
+//@DynamoDbBean
+public class Product {
+ private String name;
+ private String brand;
+ private double price;
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getBrand() {
+ return brand;
+ }
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+ public double getPrice() {
+ return price;
+ }
+ public void setPrice(double price) {
+ this.price = price;
+ }
+
+
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/CustomerRepository.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/CustomerRepository.java
new file mode 100644
index 000000000..2e7195d3c
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/CustomerRepository.java
@@ -0,0 +1,20 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring.repositories;
+
+import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
+import org.springframework.data.repository.CrudRepository;
+
+import io.pratik.dynamodbspring.models.Customer;
+
+/**
+ * @author pratikdas
+ *
+ */
+@EnableScan
+public interface CustomerRepository extends
+ CrudRepository {
+
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/OrderRepository.java b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/OrderRepository.java
new file mode 100644
index 000000000..0295aa9c9
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/OrderRepository.java
@@ -0,0 +1,21 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring.repositories;
+
+import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
+import org.springframework.data.repository.CrudRepository;
+
+import io.pratik.dynamodbspring.models.Order;
+import io.pratik.dynamodbspring.models.OrderID;
+
+/**
+ * @author pratikdas
+ *
+ */
+@EnableScan
+public interface OrderRepository extends
+ CrudRepository {
+
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/main/resources/application.properties b/aws/springdynamodb/dynamodbspringdata/src/main/resources/application.properties
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/aws/springdynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/CustomerServiceTest.java b/aws/springdynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/CustomerServiceTest.java
new file mode 100644
index 000000000..b0a3a6072
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/CustomerServiceTest.java
@@ -0,0 +1,48 @@
+/**
+ *
+ */
+package io.pratik.dynamodbspring;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import io.pratik.dynamodbspring.models.Customer;
+
+/**
+ * @author pratikdas
+ *
+ */
+@SpringBootTest
+class CustomerServiceTest {
+
+ @Autowired
+ private CustomerService customerService;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeEach
+ void setUp() throws Exception {
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @AfterEach
+ void tearDown() throws Exception {
+ }
+
+ @Test
+ void testCreateCustomer() {
+ Customer customer = new Customer();
+ customer.setCustomerID("CUST-001");
+ customer.setName("pratik");
+ customer.setEmail("hgjgjh");
+ customerService.createCustomer(customer);
+ }
+
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/DynamodbspringApplicationTests.java b/aws/springdynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/DynamodbspringApplicationTests.java
new file mode 100644
index 000000000..a2fc1984f
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/DynamodbspringApplicationTests.java
@@ -0,0 +1,13 @@
+package io.pratik.dynamodbspring;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class DynamodbspringApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/application.properties b/aws/springdynamodb/dynamodbspringdata/target/classes/application.properties
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/target/classes/application.properties
@@ -0,0 +1 @@
+
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/CustomerService.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/CustomerService.class
new file mode 100644
index 000000000..6e74793fa
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/CustomerService.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/DynamodbspringApplication.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/DynamodbspringApplication.class
new file mode 100644
index 000000000..fa6597274
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/DynamodbspringApplication.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/OrderService.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/OrderService.class
new file mode 100644
index 000000000..22080c89d
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/OrderService.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/config/AppConfig.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/config/AppConfig.class
new file mode 100644
index 000000000..b70ceee73
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/config/AppConfig.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Customer.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Customer.class
new file mode 100644
index 000000000..7d5c7f6f6
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Customer.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Order.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Order.class
new file mode 100644
index 000000000..133a4c32a
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Order.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/OrderID.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/OrderID.class
new file mode 100644
index 000000000..31656607c
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/OrderID.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Product.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Product.class
new file mode 100644
index 000000000..7cd742455
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/models/Product.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/repositories/CustomerRepository.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/repositories/CustomerRepository.class
new file mode 100644
index 000000000..28236afed
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/repositories/CustomerRepository.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/repositories/OrderRepository.class b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/repositories/OrderRepository.class
new file mode 100644
index 000000000..0accc9cb1
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/classes/io/pratik/dynamodbspring/repositories/OrderRepository.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/dynamodbspringdata-0.0.1-SNAPSHOT.jar b/aws/springdynamodb/dynamodbspringdata/target/dynamodbspringdata-0.0.1-SNAPSHOT.jar
new file mode 100644
index 000000000..699f0102d
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/dynamodbspringdata-0.0.1-SNAPSHOT.jar differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/maven-archiver/pom.properties b/aws/springdynamodb/dynamodbspringdata/target/maven-archiver/pom.properties
new file mode 100644
index 000000000..977782b52
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/target/maven-archiver/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Maven
+#Thu Jun 03 12:13:08 GST 2021
+groupId=io.pratik
+artifactId=dynamodbspringdata
+version=0.0.1-SNAPSHOT
diff --git a/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
new file mode 100644
index 000000000..b5b855bc4
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
@@ -0,0 +1,10 @@
+io/pratik/dynamodbspring/repositories/OrderRepository.class
+io/pratik/dynamodbspring/repositories/CustomerRepository.class
+io/pratik/dynamodbspring/CustomerService.class
+io/pratik/dynamodbspring/models/Product.class
+io/pratik/dynamodbspring/DynamodbspringApplication.class
+io/pratik/dynamodbspring/models/Order.class
+io/pratik/dynamodbspring/models/OrderID.class
+io/pratik/dynamodbspring/config/AppConfig.class
+io/pratik/dynamodbspring/OrderService.class
+io/pratik/dynamodbspring/models/Customer.class
diff --git a/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
new file mode 100644
index 000000000..04f2f608e
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
@@ -0,0 +1,10 @@
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Order.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Product.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/OrderService.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/OrderID.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/config/AppConfig.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/models/Customer.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/DynamodbspringApplication.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/CustomerRepository.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/repositories/OrderRepository.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/main/java/io/pratik/dynamodbspring/CustomerService.java
diff --git a/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
new file mode 100644
index 000000000..295a13b85
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
@@ -0,0 +1,2 @@
+io/pratik/dynamodbspring/DynamodbspringApplicationTests.class
+io/pratik/dynamodbspring/CustomerServiceTest.class
diff --git a/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
new file mode 100644
index 000000000..252dc2ade
--- /dev/null
+++ b/aws/springdynamodb/dynamodbspringdata/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
@@ -0,0 +1,2 @@
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/CustomerServiceTest.java
+/Users/pratikdas/pratik/code-examples/aws/aws-dynamodb/dynamodbspringdata/src/test/java/io/pratik/dynamodbspring/DynamodbspringApplicationTests.java
diff --git a/aws/springdynamodb/dynamodbspringdata/target/test-classes/io/pratik/dynamodbspring/CustomerServiceTest.class b/aws/springdynamodb/dynamodbspringdata/target/test-classes/io/pratik/dynamodbspring/CustomerServiceTest.class
new file mode 100644
index 000000000..69e3dcea6
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/test-classes/io/pratik/dynamodbspring/CustomerServiceTest.class differ
diff --git a/aws/springdynamodb/dynamodbspringdata/target/test-classes/io/pratik/dynamodbspring/DynamodbspringApplicationTests.class b/aws/springdynamodb/dynamodbspringdata/target/test-classes/io/pratik/dynamodbspring/DynamodbspringApplicationTests.class
new file mode 100644
index 000000000..55056ae1b
Binary files /dev/null and b/aws/springdynamodb/dynamodbspringdata/target/test-classes/io/pratik/dynamodbspring/DynamodbspringApplicationTests.class differ
diff --git a/aws/springdynamodb/pom.xml b/aws/springdynamodb/pom.xml
new file mode 100644
index 000000000..6f5c369f6
--- /dev/null
+++ b/aws/springdynamodb/pom.xml
@@ -0,0 +1,11 @@
+
+ 4.0.0
+ io.pratik
+ dynamodbapp
+ 0.0.1-SNAPSHOT
+ pom
+
+ dynamodbspringdata
+ dynamodbec
+
+
\ No newline at end of file
diff --git a/aws/sqs/.mvn/wrapper/MavenWrapperDownloader.java b/aws/sqs/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/aws/sqs/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/aws/sqs/.mvn/wrapper/maven-wrapper.jar b/aws/sqs/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/aws/sqs/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/sqs/.mvn/wrapper/maven-wrapper.properties b/aws/sqs/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/aws/sqs/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/aws/sqs/README.md b/aws/sqs/README.md
new file mode 100644
index 000000000..45483a223
--- /dev/null
+++ b/aws/sqs/README.md
@@ -0,0 +1,8 @@
+# Getting started with AWS SQS
+
+
+
+Blog posts about this topic:
+
+* [Getting started with AWS SQS](https://reflectoring.io/getting-started-with-aws-sqs/)
+
diff --git a/aws/sqs/mvnw b/aws/sqs/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/aws/sqs/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/sqs/mvnw.cmd b/aws/sqs/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/aws/sqs/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/aws/sqs/pom.xml b/aws/sqs/pom.xml
new file mode 100644
index 000000000..519d1e993
--- /dev/null
+++ b/aws/sqs/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+ io.pratik
+ sqs
+ 1.0
+
+
+ UTF-8
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+
+
+
+ software.amazon.awssdk
+ sqs
+
+
+
+ software.amazon.awssdk
+ sns
+
+
+
+
+
+
+
+ software.amazon.awssdk
+ bom
+ 2.17.116
+ pom
+ import
+
+
+
+
diff --git a/aws/sqs/resources/index.js b/aws/sqs/resources/index.js
new file mode 100644
index 000000000..63ddae359
--- /dev/null
+++ b/aws/sqs/resources/index.js
@@ -0,0 +1,7 @@
+exports.handler = async function(event, context) {
+ event.Records.forEach(record => {
+ const { body } = record;
+ console.log(body);
+ });
+ return {};
+}
\ No newline at end of file
diff --git a/aws/sqs/src/main/java/io/pratik/sqs/AppConfig.java b/aws/sqs/src/main/java/io/pratik/sqs/AppConfig.java
new file mode 100644
index 000000000..aba1b094f
--- /dev/null
+++ b/aws/sqs/src/main/java/io/pratik/sqs/AppConfig.java
@@ -0,0 +1,14 @@
+/**
+ *
+ */
+package io.pratik.sqs;
+
+/**
+ * @author pratikdas
+ *
+ */
+public interface AppConfig {
+
+ String ACCOUNT_NO = "*********";
+
+}
diff --git a/aws/sqs/src/main/java/io/pratik/sqs/MessageReceiver.java b/aws/sqs/src/main/java/io/pratik/sqs/MessageReceiver.java
new file mode 100644
index 000000000..99fe074c4
--- /dev/null
+++ b/aws/sqs/src/main/java/io/pratik/sqs/MessageReceiver.java
@@ -0,0 +1,86 @@
+/**
+ *
+ */
+package io.pratik.sqs;
+
+import java.util.List;
+
+import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageRequest;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageResponse;
+import software.amazon.awssdk.services.sqs.model.Message;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
+
+/**
+ * @author pratikdas
+ *
+ */
+public class MessageReceiver {
+
+ /**
+ * @param args
+ * @throws InterruptedException
+ */
+ public static void main(String[] args) throws InterruptedException {
+ // receiveMessage();
+ receiveFifoMessage();
+
+ }
+
+ public static void receiveMessage() {
+ SqsClient sqsClient = getSQSClient();
+ final String queueURL = "https://sqs.us-east-1.amazonaws.com/" +AppConfig.ACCOUNT_NO + "/myqueue";
+
+ // long polling and wait for waitTimeSeconds before timed out
+ ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
+ .queueUrl(queueURL)
+ .waitTimeSeconds(20)
+ .messageAttributeNames("trace-id") // returns the trace Id
+ .build();
+ List messages = sqsClient.receiveMessage(receiveMessageRequest).messages();
+ }
+
+ public static void receiveFifoMessage() throws InterruptedException {
+ SqsClient sqsClient = getSQSClient();
+ final String queueURL = "https://sqs.us-east-1.amazonaws.com/" +AppConfig.ACCOUNT_NO + "/myfifoqueue.fifo";
+
+ // long polling and wait for waitTimeSeconds before timed out
+ ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
+ .queueUrl(queueURL)
+ .waitTimeSeconds(20)
+ .messageAttributeNames("trace-id") // returns the trace Id
+ .build();
+
+ while(true) {
+
+ Thread.sleep(20000l);
+ List messages = sqsClient.receiveMessage(receiveMessageRequest).messages();
+ messages.stream().forEach(msg->{
+ System.out.println(msg.body() + " " + msg.attributesAsStrings());
+
+ String receiptHandle = msg.receiptHandle();
+ DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder().queueUrl(queueURL).receiptHandle(receiptHandle).build();
+ DeleteMessageResponse deleteMessageResponse = sqsClient.deleteMessage(deleteMessageRequest );
+
+ // logger.info(deleteMessageResponse.responseMetadata());
+ });
+
+ }
+
+
+ }
+
+ private static SqsClient getSQSClient() {
+ AwsCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create("pratikpoc");
+
+ SqsClient sqsClient = SqsClient
+ .builder()
+ .credentialsProvider(credentialsProvider)
+ .region(Region.US_EAST_1).build();
+ return sqsClient;
+ }
+
+}
diff --git a/aws/sqs/src/main/java/io/pratik/sqs/MessageSender.java b/aws/sqs/src/main/java/io/pratik/sqs/MessageSender.java
new file mode 100644
index 000000000..80ef12877
--- /dev/null
+++ b/aws/sqs/src/main/java/io/pratik/sqs/MessageSender.java
@@ -0,0 +1,147 @@
+/**
+ *
+ */
+package io.pratik.sqs;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sns.SnsClient;
+import software.amazon.awssdk.services.sns.model.PublishRequest;
+import software.amazon.awssdk.services.sns.model.PublishResponse;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.MessageAttributeValue;
+import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
+import software.amazon.awssdk.services.sqs.model.SendMessageResponse;
+
+/**
+ * @author pratikdas
+ *
+ */
+public class MessageSender {
+
+ private static final String TRACE_ID_NAME = "trace-id";
+ private static Logger logger = Logger.getLogger(MessageSender.class.getName());
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ // sendMessage();
+ // sendMessageToFifo();
+ sendMessageToSnsTopic();
+ }
+ public static void sendMessageToSnsTopic() {
+ SnsClient snsClient = getSNSClient();
+
+ Map messageAttributes = new HashMap();
+ // generates a UUID as the traceId
+ String traceId = UUID.randomUUID().toString();
+ // add traceId as a message attribute
+ messageAttributes.put(TRACE_ID_NAME, MessageAttributeValue.builder().dataType("String").stringValue(traceId).build());
+ final String topicArn = "arn:aws:sns:us-east-1:" + AppConfig.ACCOUNT_NO + ":mytopic";
+
+ PublishRequest publishRequest = PublishRequest.builder().topicArn(topicArn).message("Test message published to topic").build();
+ PublishResponse publishResponse = snsClient.publish(publishRequest);
+
+ logger.info("message id: "+ publishResponse.messageId());
+
+ snsClient.close();
+ }
+
+
+ public static void sendMessage() {
+ SqsClient sqsClient = getSQSClient();
+
+ Map messageAttributes = new HashMap();
+ // generates a UUID as the traceId
+ String traceId = UUID.randomUUID().toString();
+ // add traceId as a message attribute
+ messageAttributes.put(TRACE_ID_NAME, MessageAttributeValue.builder().dataType("String").stringValue(traceId).build());
+
+ final String queueURL = "https://sqs.us-east-1.amazonaws.com/" +AppConfig.ACCOUNT_NO + "/myqueue";
+ SendMessageRequest sendMessageRequest = SendMessageRequest.builder().queueUrl(queueURL).messageBody("Test message")
+ .messageAttributes(messageAttributes)
+ .build();
+ SendMessageResponse sendMessageResponse = sqsClient.sendMessage(sendMessageRequest);
+
+ logger.info("message id: "+ sendMessageResponse.messageId() );
+
+ sqsClient.close();
+ }
+
+ public static void sendMessageToFifo() {
+ SqsClient sqsClient = getSQSClient();
+
+ Map messageAttributes = new HashMap();
+ // generates a UUID as the traceId
+ String traceId = UUID.randomUUID().toString();
+ // add traceId as a message attribute
+ messageAttributes.put(TRACE_ID_NAME, MessageAttributeValue.builder().dataType("String").stringValue(traceId).build());
+
+ final String queueURL = "https://sqs.us-east-1.amazonaws.com/" +AppConfig.ACCOUNT_NO + "/myfifoqueue.fifo";
+
+
+ List dedupIds = List.of("dedupid1","dedupid2","dedupid3","dedupid2","dedupid1");
+
+ String messageGroupId = "signup";
+
+ List messages = List.of(
+ "My fifo message1",
+ "My fifo message2",
+ "My fifo message3",
+ "My fifo message2",
+ "My fifo message1");
+ short loop = 0;
+ for (String message : messages) {
+
+ SendMessageRequest sendMessageRequest = SendMessageRequest.builder()
+ .queueUrl(queueURL)
+ .messageBody(message)
+ .messageAttributes(messageAttributes)
+ .messageDeduplicationId(dedupIds.get(loop))
+ .messageGroupId(messageGroupId)
+ .build();
+
+ SendMessageResponse sendMessageResponse = sqsClient
+ .sendMessage(sendMessageRequest);
+
+ logger.info("message id and sequence no.: "+ sendMessageResponse.messageId() + " | " + sendMessageResponse.sequenceNumber());
+
+ logger.info("responseMetadata " + sendMessageResponse.responseMetadata());
+ loop+=1;
+ }
+
+
+ sqsClient.close();
+ }
+
+
+
+ private static SqsClient getSQSClient() {
+ AwsCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create("pratikpoc");
+
+ SqsClient sqsClient = SqsClient
+ .builder()
+ .credentialsProvider(credentialsProvider)
+ .region(Region.US_EAST_1).build();
+ return sqsClient;
+ }
+
+ private static SnsClient getSNSClient() {
+ AwsCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create("pratikpoc");
+
+ SnsClient snsClient = SnsClient
+ .builder()
+ .credentialsProvider(credentialsProvider)
+ .region(Region.US_EAST_1).build();
+ return snsClient;
+ }
+
+}
diff --git a/aws/sqs/src/main/java/io/pratik/sqs/ResourceHelper.java b/aws/sqs/src/main/java/io/pratik/sqs/ResourceHelper.java
new file mode 100644
index 000000000..ec3efcf00
--- /dev/null
+++ b/aws/sqs/src/main/java/io/pratik/sqs/ResourceHelper.java
@@ -0,0 +1,138 @@
+/**
+ *
+ */
+package io.pratik.sqs;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sns.SnsClient;
+import software.amazon.awssdk.services.sns.model.CreateTopicRequest;
+import software.amazon.awssdk.services.sns.model.CreateTopicResponse;
+import software.amazon.awssdk.services.sns.model.SubscribeRequest;
+import software.amazon.awssdk.services.sns.model.SubscribeResponse;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.CreateQueueRequest;
+import software.amazon.awssdk.services.sqs.model.CreateQueueResponse;
+import software.amazon.awssdk.services.sqs.model.QueueAttributeName;
+
+/**
+ * @author pratikdas
+ *
+ */
+public class ResourceHelper {
+ private static Logger logger = Logger.getLogger(ResourceHelper.class.getName());
+
+ public static void main(String[] args) {
+ // createStandardQueue();
+ // createFifoQueue();
+ createSNSTopicWithSubscription();
+ }
+
+
+
+ public static void createStandardQueue() {
+ SqsClient sqsClient = getSQSClient();
+
+ String dlqName = "mydlq";
+ CreateQueueRequest createQueueRequest = CreateQueueRequest.builder()
+ .queueName(dlqName)
+ .build();
+
+
+ // Create dead letter queue
+ CreateQueueResponse createQueueResponse = sqsClient.createQueue(createQueueRequest);
+
+
+ String dlqArn = getQueueArn(dlqName,"us-east-1");
+
+ Map attributeMap = new HashMap();
+ attributeMap.put(QueueAttributeName.REDRIVE_POLICY,
+ "{\"maxReceiveCount\":10,\"deadLetterTargetArn\":\""+dlqArn+"\"}");
+
+ // Prepare request for creating the standard queue
+ createQueueRequest = CreateQueueRequest.builder()
+ .queueName("myqueue")
+ .attributes(attributeMap)
+ .build();
+
+ // create the queue
+ createQueueResponse = sqsClient.createQueue(createQueueRequest);
+
+ logger.info("Queue URL " + createQueueResponse.queueUrl());
+ }
+
+ public static void createFifoQueue() {
+ SqsClient sqsClient = getSQSClient();
+
+
+ Map attributeMap = new HashMap();
+
+ attributeMap.put(QueueAttributeName.FIFO_QUEUE, "true");
+ attributeMap.put(QueueAttributeName.DEDUPLICATION_SCOPE, "messageGroup");
+ attributeMap.put(QueueAttributeName.CONTENT_BASED_DEDUPLICATION, "false");
+
+ CreateQueueRequest createQueueRequest = CreateQueueRequest.builder()
+ .queueName("myfifoqueue.fifo")
+ .attributes(attributeMap )
+ .build();
+
+ CreateQueueResponse createQueueResponse = sqsClient.createQueue(createQueueRequest);
+ logger.info("url "+createQueueResponse.queueUrl());
+ }
+
+ public static void createSNSTopicWithSubscription() {
+ SnsClient snsClient = getSNSClient();
+
+ CreateTopicRequest createTopicRequest = CreateTopicRequest.builder().name("mytopic").build();
+ CreateTopicResponse createTopicResponse = snsClient.createTopic(createTopicRequest );
+
+ String topicArn = createTopicResponse.topicArn();
+ //Topic topic = Topic.builder().topicArn(topicArn).build();
+
+ String queueArn= getQueueArn("myqueue","us-east-1");
+
+ SubscribeRequest subscribeRequest = SubscribeRequest.builder()
+ .protocol("sqs")
+ .topicArn(topicArn)
+ .endpoint(queueArn)
+ .build();
+ SubscribeResponse subscribeResponse = snsClient.subscribe(subscribeRequest );
+
+
+ logger.info("subscriptionArn " + subscribeResponse.subscriptionArn());
+ }
+
+
+
+ private static SqsClient getSQSClient() {
+ AwsCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create("pratikpoc");
+
+ SqsClient sqsClient = SqsClient
+ .builder()
+ .credentialsProvider(credentialsProvider)
+ .region(Region.US_EAST_1).build();
+ return sqsClient;
+ }
+
+ private static SnsClient getSNSClient() {
+ AwsCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create("pratikpoc");
+
+ SnsClient snsClient = SnsClient
+ .builder()
+ .credentialsProvider(credentialsProvider)
+ .region(Region.US_EAST_1).build();
+ return snsClient;
+ }
+
+
+
+ private static String getQueueArn(final String queueName, final String region) {
+ return "arn:aws:sqs:"+region + ":" + AppConfig.ACCOUNT_NO+ ":" + queueName;
+ }
+
+}
diff --git a/aws/structured-logging-cw/.mvn/wrapper/maven-wrapper.jar b/aws/structured-logging-cw/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..cb28b0e37
Binary files /dev/null and b/aws/structured-logging-cw/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/aws/structured-logging-cw/.mvn/wrapper/maven-wrapper.properties b/aws/structured-logging-cw/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..6f40a26ed
--- /dev/null
+++ b/aws/structured-logging-cw/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/aws/structured-logging-cw/README.md b/aws/structured-logging-cw/README.md
new file mode 100644
index 000000000..790b449d0
--- /dev/null
+++ b/aws/structured-logging-cw/README.md
@@ -0,0 +1,10 @@
+# Structured logging with Amazon CloudWatch
+
+Example code for producing Structured logs and ingesting and visualizing with Amazon CloudWatch.
+
+## Blog posts
+
+Blog posts about this topic:
+
+* [Structured Logging with Amazon CloudWatch](https://reflectoring.io/struct-log-with-cw/)
+
diff --git a/aws/structured-logging-cw/iac_aws/manage-VM/.terraform.lock.hcl b/aws/structured-logging-cw/iac_aws/manage-VM/.terraform.lock.hcl
new file mode 100644
index 000000000..93181f4c4
--- /dev/null
+++ b/aws/structured-logging-cw/iac_aws/manage-VM/.terraform.lock.hcl
@@ -0,0 +1,62 @@
+# This file is maintained automatically by "terraform init".
+# Manual edits may be lost in future updates.
+
+provider "registry.terraform.io/hashicorp/aws" {
+ version = "4.63.0"
+ hashes = [
+ "h1:dN7hK7srLB0ZScbsoqEP25/3yXX9kauF3elbEQ0yXFM=",
+ "zh:0162a9b61f45deed9fcc4a3c4a90341904b0c1c864b2226c8c6df14a87671d86",
+ "zh:230db13f43ced8e9dcb7966c32a2b11cff0708b639083cfc92bdb6cb92902c86",
+ "zh:2d630ef2ff0c5b6395799112d8101f75445e42e40cb55c7e280209310bdb5ce4",
+ "zh:34f7d6bee1e0be7cac99bd0812625a6a76823b0e59957e02120a3c27f847c2d8",
+ "zh:6137d3d63f03265fe0ab21b87c8f9fb9b5776780de9924107e21333ad347ae7b",
+ "zh:6d03651e7e2106f247a9e22883ec7f650b8a78202575fbc7409278ebe4278da4",
+ "zh:6eb7a55e6320c650aac3b3d9b973317ce29510d78b334294864d886ba468e4e6",
+ "zh:71d819f87edcb5345bc451a4079dda223e037bf0b960c10e65737ff4f925b2a1",
+ "zh:7e8792065385d6353e67905ae115e1dd30752c8310baa73c5100de4dedb78843",
+ "zh:8e761b2064a56b98c82bfe8fa4666837e7cfa953e0b91744b8609e88f94db7c0",
+ "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
+ "zh:9ffb31588e06851e55618677b6c60f94399423e8c47fd43bab753700a4699a96",
+ "zh:e2417386f0ae3e7c44e789481f9054f68e590f8672bc667197a190d57b61b6f9",
+ "zh:e554812bff64e3c7e93839ec6905dbf696b9b1d5d8336e9c9fc69659ea4f39a0",
+ "zh:e61f064190045b5bd982fefa59de9f342fb07f8407d6cfa4aa39c370b93d2117",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/local" {
+ version = "2.4.0"
+ hashes = [
+ "h1:ZUEYUmm2t4vxwzxy1BvN1wL6SDWrDxfH7pxtzX8c6d0=",
+ "zh:53604cd29cb92538668fe09565c739358dc53ca56f9f11312b9d7de81e48fab9",
+ "zh:66a46e9c508716a1c98efbf793092f03d50049fa4a83cd6b2251e9a06aca2acf",
+ "zh:70a6f6a852dd83768d0778ce9817d81d4b3f073fab8fa570bff92dcb0824f732",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ "zh:82a803f2f484c8b766e2e9c32343e9c89b91997b9f8d2697f9f3837f62926b35",
+ "zh:9708a4e40d6cc4b8afd1352e5186e6e1502f6ae599867c120967aebe9d90ed04",
+ "zh:973f65ce0d67c585f4ec250c1e634c9b22d9c4288b484ee2a871d7fa1e317406",
+ "zh:c8fa0f98f9316e4cfef082aa9b785ba16e36ff754d6aba8b456dab9500e671c6",
+ "zh:cfa5342a5f5188b20db246c73ac823918c189468e1382cb3c48a9c0c08fc5bf7",
+ "zh:e0e2b477c7e899c63b06b38cd8684a893d834d6d0b5e9b033cedc06dd7ffe9e2",
+ "zh:f62d7d05ea1ee566f732505200ab38d94315a4add27947a60afa29860822d3fc",
+ "zh:fa7ce69dde358e172bd719014ad637634bbdabc49363104f4fca759b4b73f2ce",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/tls" {
+ version = "4.0.4"
+ hashes = [
+ "h1:GZcFizg5ZT2VrpwvxGBHQ/hO9r6g0vYdQqx3bFD3anY=",
+ "zh:23671ed83e1fcf79745534841e10291bbf34046b27d6e68a5d0aab77206f4a55",
+ "zh:45292421211ffd9e8e3eb3655677700e3c5047f71d8f7650d2ce30242335f848",
+ "zh:59fedb519f4433c0fdb1d58b27c210b27415fddd0cd73c5312530b4309c088be",
+ "zh:5a8eec2409a9ff7cd0758a9d818c74bcba92a240e6c5e54b99df68fff312bbd5",
+ "zh:5e6a4b39f3171f53292ab88058a59e64825f2b842760a4869e64dc1dc093d1fe",
+ "zh:810547d0bf9311d21c81cc306126d3547e7bd3f194fc295836acf164b9f8424e",
+ "zh:824a5f3617624243bed0259d7dd37d76017097dc3193dac669be342b90b2ab48",
+ "zh:9361ccc7048be5dcbc2fafe2d8216939765b3160bd52734f7a9fd917a39ecbd8",
+ "zh:aa02ea625aaf672e649296bce7580f62d724268189fe9ad7c1b36bb0fa12fa60",
+ "zh:c71b4cd40d6ec7815dfeefd57d88bc592c0c42f5e5858dcc88245d371b4b8b1e",
+ "zh:dabcd52f36b43d250a3d71ad7abfa07b5622c69068d989e60b79b2bb4f220316",
+ "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
+ ]
+}
diff --git a/aws/structured-logging-cw/iac_aws/manage-VM/cloudwatch-agent-config.json b/aws/structured-logging-cw/iac_aws/manage-VM/cloudwatch-agent-config.json
new file mode 100644
index 000000000..c9def1e06
--- /dev/null
+++ b/aws/structured-logging-cw/iac_aws/manage-VM/cloudwatch-agent-config.json
@@ -0,0 +1,121 @@
+{
+ "agent": {
+ "metrics_collection_interval": 10,
+ "logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log"
+ },
+ "metrics": {
+ "metrics_collected": {
+ "cpu": {
+ "resources": [
+ "*"
+ ],
+ "measurement": [
+ {"name": "cpu_usage_idle", "rename": "CPU_USAGE_IDLE", "unit": "Percent"},
+ {"name": "cpu_usage_nice", "unit": "Percent"},
+ "cpu_usage_guest"
+ ],
+ "totalcpu": false,
+ "metrics_collection_interval": 10,
+ "append_dimensions": {
+ "customized_dimension_key_1": "customized_dimension_value_1",
+ "customized_dimension_key_2": "customized_dimension_value_2"
+ }
+ },
+ "disk": {
+ "resources": [
+ "/",
+ "/tmp"
+ ],
+ "measurement": [
+ {"name": "free", "rename": "DISK_FREE", "unit": "Gigabytes"},
+ "total",
+ "used"
+ ],
+ "ignore_file_system_types": [
+ "sysfs", "devtmpfs"
+ ],
+ "metrics_collection_interval": 60,
+ "append_dimensions": {
+ "customized_dimension_key_3": "customized_dimension_value_3",
+ "customized_dimension_key_4": "customized_dimension_value_4"
+ }
+ },
+ "diskio": {
+ "resources": [
+ "*"
+ ],
+ "measurement": [
+ "reads",
+ "writes",
+ "read_time",
+ "write_time",
+ "io_time"
+ ],
+ "metrics_collection_interval": 60
+ },
+ "swap": {
+ "measurement": [
+ "swap_used",
+ "swap_free",
+ "swap_used_percent"
+ ]
+ },
+ "mem": {
+ "measurement": [
+ "mem_used",
+ "mem_cached",
+ "mem_total"
+ ],
+ "metrics_collection_interval": 10
+ },
+ "net": {
+ "resources": [
+ "eth0"
+ ],
+ "measurement": [
+ "bytes_sent",
+ "bytes_recv",
+ "drop_in",
+ "drop_out"
+ ]
+ },
+ "netstat": {
+ "measurement": [
+ "tcp_established",
+ "tcp_syn_sent",
+ "tcp_close"
+ ],
+ "metrics_collection_interval": 60
+ },
+ "processes": {
+ "measurement": [
+ "running",
+ "sleeping",
+ "dead"
+ ]
+ }
+ },
+ "append_dimensions": {
+ "ImageId": "${aws:ImageId}",
+ "InstanceId": "${aws:InstanceId}",
+ "InstanceType": "${aws:InstanceType}",
+ "AutoScalingGroupName": "${aws:AutoScalingGroupName}"
+ },
+ "aggregation_dimensions" : [["ImageId"], ["InstanceId", "InstanceType"], ["d1"],[]]
+ },
+ "logs": {
+ "logs_collected": {
+ "files": {
+ "collect_list": [
+ {
+ "file_path": "/home/ec2-user/accountprocessor/logs/accountprocessor-logging-dev.log",
+ "log_group_name": "accountprocessor",
+ "log_stream_name": "{instance_id}_{hostname}",
+ "timezone": "Local"
+ }
+ ]
+ }
+ },
+ "log_stream_name": "/ec2/catchall"
+ }
+}
\ No newline at end of file
diff --git a/aws/structured-logging-cw/iac_aws/manage-VM/main.tf b/aws/structured-logging-cw/iac_aws/manage-VM/main.tf
new file mode 100644
index 000000000..3b055a0ed
--- /dev/null
+++ b/aws/structured-logging-cw/iac_aws/manage-VM/main.tf
@@ -0,0 +1,133 @@
+provider "aws" {
+ profile = "Admin-Account-Access-489455091964"
+ region = "eu-central-1"
+}
+
+data "aws_ami" "latest-linux" {
+ most_recent = true
+
+ filter {
+ name = "name"
+ values = ["*Linux 2023*"]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+}
+
+resource "aws_key_pair" "tf-key-pair" {
+ key_name = "tf-key-pair"
+ public_key = tls_private_key.rsa.public_key_openssh
+}
+
+resource "tls_private_key" "rsa" {
+ algorithm = "RSA"
+ rsa_bits = 4096
+}
+
+resource "local_file" "tf-key" {
+ content = tls_private_key.rsa.private_key_pem
+ filename = "tf-key-pair.pem"
+}
+
+resource "aws_vpc_security_group_ingress_rule" "sg-ssh" {
+ security_group_id = aws_security_group.main.id
+
+ cidr_ipv4 = "0.0.0.0/0"
+ from_port = 22
+ ip_protocol = "tcp"
+ to_port = 22
+}
+
+resource "aws_vpc_security_group_egress_rule" "sg-down" {
+ security_group_id = aws_security_group.main.id
+
+ cidr_ipv4 = "0.0.0.0/0"
+ from_port = 443
+ ip_protocol = "tcp"
+ to_port = 443
+}
+
+resource "aws_cloudwatch_log_group" "accountsAppLogs" {
+ name = "accounts"
+
+ tags = {
+ Environment = "production"
+ Application = "accountsApi"
+ }
+}
+
+resource "aws_security_group" "main" {
+
+}
+
+resource "aws_instance" "ec2-web1" {
+ # ami = data.aws_ami.latest-linux.id
+ ami = "ami-0b7fd829e7758b06d"
+ instance_type = "t2.micro"
+ tags = {
+ Name = "app-ec2-server",
+ Created_By = "pratik"
+ }
+ key_name = "tf-key-pair"
+ vpc_security_group_ids = [aws_security_group.main.id]
+ user_data = <<-EOF
+ #!/bin/bash
+ echo "installing jdk"
+ yum update -y
+ wget https://download.java.net/java/GA/jdk20.0.1/b4887098932d415489976708ad6d1a4b/9/GPL/openjdk-20.0.1_linux-x64_bin.tar.gz
+ tar xvf openjdk*
+ export JAVA_HOME=jdk-20.0.1
+ export PATH=$JAVA_HOME/bin:$PATH
+ export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
+ sudo yum install amazon-cloudwatch-agent
+ EOF
+}
+
+resource "aws_iam_role" "ec2_role" {
+ name = "ec2_role"
+
+ # Terraform's "jsonencode" function converts a
+ # Terraform expression result to valid JSON syntax.
+ assume_role_policy = jsonencode({
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:PutMetricData",
+ "ec2:DescribeVolumes",
+ "ec2:DescribeTags",
+ "logs:PutLogEvents",
+ "logs:DescribeLogStreams",
+ "logs:DescribeLogGroups",
+ "logs:CreateLogStream",
+ "logs:CreateLogGroup"
+ ],
+ "Resource": "*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ssm:GetParameter"
+ ],
+ "Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*"
+ }
+ ]
+ })
+
+ tags = {
+ tag-key = "tag-value"
+ }
+}
+output "server_private_ip" {
+value = aws_instance.ec2-web1.private_ip
+}
+output "server_public_ipv4" {
+value = aws_instance.ec2-web1.public_ip
+}
+output "server_id" {
+value = aws_instance.ec2-web1.id
+}
diff --git a/aws/structured-logging-cw/mvnw b/aws/structured-logging-cw/mvnw
new file mode 100755
index 000000000..8d937f4c1
--- /dev/null
+++ b/aws/structured-logging-cw/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/aws/structured-logging-cw/mvnw.cmd b/aws/structured-logging-cw/mvnw.cmd
new file mode 100644
index 000000000..f80fbad3e
--- /dev/null
+++ b/aws/structured-logging-cw/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/aws/structured-logging-cw/pom.xml b/aws/structured-logging-cw/pom.xml
new file mode 100644
index 000000000..1036729d2
--- /dev/null
+++ b/aws/structured-logging-cw/pom.xml
@@ -0,0 +1,73 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.0.5
+
+
+ io.pratik
+ accountProcessor
+ 0.0.1-SNAPSHOT
+ accountProcessor
+ Sample project for Spring Boot
+
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ org.apache.logging.log4j
+ log4j-to-slf4j
+
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
+
diff --git a/aws/structured-logging-cw/src/main/java/io/pratik/AccountInquiryApplication.java b/aws/structured-logging-cw/src/main/java/io/pratik/AccountInquiryApplication.java
new file mode 100644
index 000000000..916f532dc
--- /dev/null
+++ b/aws/structured-logging-cw/src/main/java/io/pratik/AccountInquiryApplication.java
@@ -0,0 +1,19 @@
+package io.pratik;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class AccountInquiryApplication {
+ private static final Logger LOG = LogManager.getLogger(AccountInquiryApplication.class);
+
+ public static void main(String[] args) {
+ LOG.info("Starting application");
+
+ SpringApplication.run(AccountInquiryApplication.class, args);
+
+ }
+
+}
diff --git a/aws/structured-logging-cw/src/main/java/io/pratik/accountProcessor/AccountInquiryController.java b/aws/structured-logging-cw/src/main/java/io/pratik/accountProcessor/AccountInquiryController.java
new file mode 100644
index 000000000..86c1691e5
--- /dev/null
+++ b/aws/structured-logging-cw/src/main/java/io/pratik/accountProcessor/AccountInquiryController.java
@@ -0,0 +1,33 @@
+package io.pratik.accountProcessor;
+
+import io.pratik.models.AccountDetail;
+import io.pratik.services.AccountService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.ThreadContext;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Optional;
+
+
+@RestController
+@RequestMapping("/accounts")
+public class AccountInquiryController {
+ private AccountService accountService;
+ private static final Logger LOG = LogManager.getLogger(AccountInquiryController.class);
+
+
+ public AccountInquiryController(final AccountService accountService){
+ this.accountService = accountService;
+ }
+ @GetMapping("/{accountNo}")
+ @ResponseBody
+ public AccountDetail getAccountDetails(@PathVariable("accountNo") String accountNo) {
+ ThreadContext.put("accountNo", accountNo);
+ LOG.info("fetching account details for account ");
+ Optional accountDetail = accountService.getAccount(accountNo);
+ LOG.info("Details of account {}", accountDetail);
+ ThreadContext.clearAll();
+ return accountDetail.orElse(AccountDetail.builder().build());
+ }
+}
diff --git a/aws/structured-logging-cw/src/main/java/io/pratik/models/AccountDetail.java b/aws/structured-logging-cw/src/main/java/io/pratik/models/AccountDetail.java
new file mode 100644
index 000000000..e50db51e9
--- /dev/null
+++ b/aws/structured-logging-cw/src/main/java/io/pratik/models/AccountDetail.java
@@ -0,0 +1,15 @@
+package io.pratik.models;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class AccountDetail {
+ private String accountNo;
+ private Double balance;
+ private String currency;
+ private String openingDate;
+ private String accountHolder;
+
+}
diff --git a/aws/structured-logging-cw/src/main/java/io/pratik/services/AccountService.java b/aws/structured-logging-cw/src/main/java/io/pratik/services/AccountService.java
new file mode 100644
index 000000000..c9d07e465
--- /dev/null
+++ b/aws/structured-logging-cw/src/main/java/io/pratik/services/AccountService.java
@@ -0,0 +1,28 @@
+package io.pratik.services;
+
+import io.pratik.models.AccountDetail;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+@Service
+public class AccountService {
+ private static final Logger LOG = LogManager.getLogger(AccountService.class);
+
+ public Optional getAccount(final String accountNo) {
+ // simulating an account not exists scenario
+ if(accountNo.endsWith("000")){
+ LOG.error("Account not found:: {}", accountNo);
+ return Optional.empty();
+ }
+ return Optional.ofNullable(AccountDetail.builder().accountHolder("Jack Melon")
+ .accountNo("GWR" + accountNo)
+ .balance(19000.89)
+ .currency("USD")
+ .openingDate("12/01/2015")
+ .build());
+
+ }
+}
diff --git a/aws/structured-logging-cw/src/main/resources/application.properties b/aws/structured-logging-cw/src/main/resources/application.properties
new file mode 100644
index 000000000..257b30648
--- /dev/null
+++ b/aws/structured-logging-cw/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.profiles.active=dev
\ No newline at end of file
diff --git a/aws/structured-logging-cw/src/main/resources/log4j2.xml b/aws/structured-logging-cw/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..418d02d79
--- /dev/null
+++ b/aws/structured-logging-cw/src/main/resources/log4j2.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aws/structured-logging-cw/src/main/resources/logger_layout.json b/aws/structured-logging-cw/src/main/resources/logger_layout.json
new file mode 100644
index 000000000..26fb93467
--- /dev/null
+++ b/aws/structured-logging-cw/src/main/resources/logger_layout.json
@@ -0,0 +1,44 @@
+{
+ "timestamp": {
+ "$resolver": "timestamp",
+ "pattern": {
+ "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
+ "timeZone": "UTC"
+ }
+ }, "level": {
+ "$resolver": "level",
+ "field": "name"
+},
+ "contextMap": {
+ "$resolver": "mdc",
+ "stringified": true
+ },
+ "message": {
+ "$resolver": "message",
+ "stringified": true
+ },
+ "thrown": {
+ "message": {
+ "$resolver": "exception",
+ "field": "message"
+ },
+ "name": {
+ "$resolver": "exception",
+ "field": "className"
+ },
+ "extendedStackTrace": {
+ "$resolver": "exception",
+ "field": "stackTrace"
+ }
+ },
+ "source": {
+ "class": {
+ "$resolver": "source",
+ "field": "className"
+ },
+ "line": {
+ "$resolver": "source",
+ "field": "lineNumber"
+ }
+ }
+}
\ No newline at end of file
diff --git a/build-all.sh b/build-all.sh
index 56d0ea293..3c7e03954 100755
--- a/build-all.sh
+++ b/build-all.sh
@@ -11,7 +11,7 @@ build_gradle_module() {
echo "+++"
cd $MODULE_PATH && {
chmod +x gradlew
- ./gradlew clean build
+ ./gradlew build
if [ $? -ne 0 ]
then
echo ""
@@ -64,7 +64,7 @@ build_maven_module() {
echo "+++"
cd $MODULE_PATH && {
chmod +x mvnw
- ./mvnw clean package
+ ./mvnw package
if [ $? -ne 0 ]
then
echo ""
@@ -82,10 +82,70 @@ build_maven_module() {
}
}
-if [[ "$MODULE" == "module5" ]]
+
+if [[ "$MODULE" == "module7" ]]
then
# ADD NEW MODULES HERE
# (add new modules above the rest so you get quicker feedback if it fails)
+ build maven_module "aws/spring-cloud-aws-s3"
+ build maven_module "aws/spring-cloud-sns-sqs-pubsub"
+ build maven_module "apache-http-client"
+ build maven_module "archunit"
+ build maven_module "aws/structured-logging-cw"
+ build_gradle_module "kotlin/coroutines"
+ build_maven_module "core-java/streams/data-streams"
+ build maven_module "aws/kinesis"
+ build maven_module "aws/sqs"
+ build_maven_module "core-java/annotation-processing/introduction-to-annotations"
+
+ echo ""
+ echo "+++"
+ echo "+++ MODULE 7 SUCCESSFUL"
+ echo "+++"
+fi
+
+
+if [[ "$MODULE" == "module6" ]]
+then
+ build maven_module "core-java/records"
+ build_maven_module "spring-boot/spring-boot-app-info"
+ build_maven_module "spring-boot/spring-boot-null-safe-annotations"
+ build maven_module "aws/cdkv2"
+ build_maven_module "immutables"
+ build maven_module "core-java/collectionops"
+ build maven_module "spring-boot/resttemplate"
+ build_maven_module "spring-cloud/tracing"
+ build_maven_module "core-java/versions"
+ build maven_module "java-hashes"
+ build maven_module "http-clients"
+ build maven_module "spring-boot/spring-boot-i18n"
+ build_maven_module "testing/assertJ"
+ build maven_module "spring-boot/spring-boot-scheduler"
+ build maven_module "aws/springcloudwatch"
+ build maven_module "aws/springcloudses"
+ build maven_module "spring-boot/spring-boot-camel"
+ build_maven_module "logging/structured-logging"
+ build_maven_module "spring-boot/zero-downtime"
+ build_maven_module "resilience4j/springboot-resilience4j"
+ build_maven_module "spring-boot/feature-flags"
+ build_gradle_module "aws/spring-cloud-caching-redis"
+ build_maven_module "logging/spring-boot"
+ build_maven_module "logging/logback"
+ build_maven_module "logging/log4j"
+
+ echo ""
+ echo "+++"
+ echo "+++ MODULE 6 SUCCESSFUL"
+ echo "+++"
+fi
+
+if [[ "$MODULE" == "module5" ]]
+then
+ build_maven_module "spring-boot/beginners-guide"
+ build_maven_module "aws/aws-dynamodb"
+ build_maven_module "spring-boot/spring-boot-testconfiguration"
+ build_maven_module "aws/springcloudrds"
+ build_maven_module "aws/springcloudsqs"
build_maven_module "spring-boot/spring-boot-actuator"
build_maven_module "mockito"
build_maven_module "core-java/service-provider-interface"
@@ -147,9 +207,12 @@ then
build_maven_module "resilience4j/timelimiter"
build_maven_module "resilience4j/bulkhead"
build_maven_module "resilience4j/circuitbreaker"
+ build_maven_module "openfeign/openfeign-client-intro"
build_gradle_module "spring-data/spring-data-jdbc-converter"
build_gradle_module "reactive"
build_gradle_module "junit/assumptions"
+ build_maven_module "junit/junit5/junit5"
+ build_maven_module "junit/junit5/functional-interfaces"
build_gradle_module "logging"
build_gradle_module "pact/pact-feign-consumer"
@@ -181,7 +244,6 @@ fi
if [[ "$MODULE" == "module4" ]]
then
- build_maven_module "core-java/threaddump"
build_gradle_module "spring-boot/mocking"
build_gradle_module "spring-boot/modular"
build_gradle_module "spring-boot/paging"
diff --git a/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/MavenWrapperDownloader.java b/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/maven-wrapper.jar b/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/maven-wrapper.properties b/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/core-java/annotation-processing/introduction-to-annotations/README.md b/core-java/annotation-processing/introduction-to-annotations/README.md
new file mode 100644
index 000000000..c39850536
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/README.md
@@ -0,0 +1,3 @@
+# Introduction to Annotation Processing
+
+Blog article: [An Introduction to Annotations and Annotation Processing in Java](https://reflectoring.io/java-annotation-processing)
diff --git a/core-java/annotation-processing/introduction-to-annotations/mvnw b/core-java/annotation-processing/introduction-to-annotations/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/core-java/annotation-processing/introduction-to-annotations/mvnw.cmd b/core-java/annotation-processing/introduction-to-annotations/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/core-java/annotation-processing/introduction-to-annotations/pom.xml b/core-java/annotation-processing/introduction-to-annotations/pom.xml
new file mode 100644
index 000000000..c76727fe9
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+ org.example
+ annotations-demo
+ 1.0-SNAPSHOT
+
+
+ 11
+ 11
+
+
+
\ No newline at end of file
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/AnnotatedMethods.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/AnnotatedMethods.java
new file mode 100644
index 000000000..9828f7eb4
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/AnnotatedMethods.java
@@ -0,0 +1,15 @@
+package com.reflectoring;
+
+public class AnnotatedMethods {
+
+ @Test
+ public void Test_1() {
+
+ System.out.println("This is the first test");
+ }
+
+ public void Test_2() {
+
+ System.out.println("This is the second test");
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/BasicAnnotationTest.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/BasicAnnotationTest.java
new file mode 100644
index 000000000..d3a1d3124
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/BasicAnnotationTest.java
@@ -0,0 +1,8 @@
+package com.reflectoring;
+
+public class BasicAnnotationTest {
+
+ public static void main(String[] args) {
+
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CSV.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CSV.java
new file mode 100644
index 000000000..9781cf4c0
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CSV.java
@@ -0,0 +1,11 @@
+package com.reflectoring;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CSV {
+}
\ No newline at end of file
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/ClassRetention.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/ClassRetention.java
new file mode 100644
index 000000000..c6f2aec15
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/ClassRetention.java
@@ -0,0 +1,11 @@
+package com.reflectoring;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS)
+public @interface ClassRetention {
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Company.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Company.java
new file mode 100644
index 000000000..07ce3bc43
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Company.java
@@ -0,0 +1,12 @@
+package com.reflectoring;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Company{
+ String name() default "ABC";
+ String city() default "XYZ";
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CustomAnnotatedEmployee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CustomAnnotatedEmployee.java
new file mode 100644
index 000000000..a73f8d053
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CustomAnnotatedEmployee.java
@@ -0,0 +1,19 @@
+package com.reflectoring;
+
+@Company
+public class CustomAnnotatedEmployee {
+
+ private int id;
+ private String name;
+
+ public CustomAnnotatedEmployee(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public void getEmployeeDetails(){
+
+ System.out.println("Employee Id: " + id);
+ System.out.println("Employee Name: " + name);
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CustomAnnotatedManager.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CustomAnnotatedManager.java
new file mode 100644
index 000000000..540a0e8f8
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/CustomAnnotatedManager.java
@@ -0,0 +1,8 @@
+package com.reflectoring;
+
+public class CustomAnnotatedManager extends CustomAnnotatedEmployee{
+
+ public CustomAnnotatedManager(int id, String name) {
+ super(id, name);
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/DeprecatedDemo.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/DeprecatedDemo.java
new file mode 100644
index 000000000..37588fa09
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/DeprecatedDemo.java
@@ -0,0 +1,10 @@
+package com.reflectoring;
+
+public class DeprecatedDemo {
+
+ @Deprecated(since = "4.5", forRemoval = true)
+ public void testLegacyFunction() {
+
+ System.out.println("This is a legacy function");
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/DeprecatedDemoTest.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/DeprecatedDemoTest.java
new file mode 100644
index 000000000..7065c1706
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/DeprecatedDemoTest.java
@@ -0,0 +1,10 @@
+package com.reflectoring;
+
+public class DeprecatedDemoTest {
+
+ public static void main(String[] args) {
+
+ DeprecatedDemo demo = new DeprecatedDemo();
+ demo.testLegacyFunction();
+ }
+}
\ No newline at end of file
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Employee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Employee.java
new file mode 100644
index 000000000..bc015d96d
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Employee.java
@@ -0,0 +1,10 @@
+package com.reflectoring;
+
+@Company
+public class Employee {
+
+ public void getEmployeeStatus(){
+
+ System.out.println("This is the Base Employee class");
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/EmployeeRetentionAnnotation.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/EmployeeRetentionAnnotation.java
new file mode 100644
index 000000000..f9badd672
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/EmployeeRetentionAnnotation.java
@@ -0,0 +1,7 @@
+package com.reflectoring;
+
+@SourceRetention
+@RuntimeRetention
+@ClassRetention
+public class EmployeeRetentionAnnotation {
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/FunctionalInterfaceTest.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/FunctionalInterfaceTest.java
new file mode 100644
index 000000000..20ab61579
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/FunctionalInterfaceTest.java
@@ -0,0 +1,15 @@
+package com.reflectoring;
+
+@FunctionalInterface
+interface Print {
+ void printString(String testString);
+}
+
+public class FunctionalInterfaceTest {
+
+ public static void main(String args[]) {
+
+ Print testPrint = (String testString) -> System.out.println(testString);
+ testPrint.printString("This is a String");
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Manager.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Manager.java
new file mode 100644
index 000000000..27b20e5a6
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Manager.java
@@ -0,0 +1,10 @@
+package com.reflectoring;
+
+public class Manager extends Employee {
+
+ @Override
+ public void getEmployeeStatus(){
+
+ System.out.println("This is the Manager class");
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/MultiValueAnnotatedEmployee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/MultiValueAnnotatedEmployee.java
new file mode 100644
index 000000000..a0d8a6c4d
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/MultiValueAnnotatedEmployee.java
@@ -0,0 +1,6 @@
+package com.reflectoring;
+
+@Company(name = "AAA", city = "ZZZ")
+public class MultiValueAnnotatedEmployee {
+
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/OverrideTest.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/OverrideTest.java
new file mode 100644
index 000000000..4c5626fff
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/OverrideTest.java
@@ -0,0 +1,10 @@
+package com.reflectoring;
+
+public class OverrideTest {
+
+ public static void main(String[] args) {
+
+ Manager manager = new Manager();
+ manager.getEmployeeStatus();
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatableCompanies.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatableCompanies.java
new file mode 100644
index 000000000..2237a7399
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatableCompanies.java
@@ -0,0 +1,9 @@
+package com.reflectoring;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RepeatableCompanies {
+ RepeatableCompany[] value() default{};
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatableCompany.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatableCompany.java
new file mode 100644
index 000000000..d0b8e3583
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatableCompany.java
@@ -0,0 +1,11 @@
+package com.reflectoring;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Repeatable(RepeatableCompanies.class)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RepeatableCompany {
+ String name() default "Name_1";
+ String city() default "City_1";
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatedAnnotatedEmployee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatedAnnotatedEmployee.java
new file mode 100644
index 000000000..ff8acb11c
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RepeatedAnnotatedEmployee.java
@@ -0,0 +1,6 @@
+package com.reflectoring;
+
+@RepeatableCompany
+@RepeatableCompany(name = "Name_2", city = "City_2")
+public class RepeatedAnnotatedEmployee {
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RetentionTest.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RetentionTest.java
new file mode 100644
index 000000000..a2a4b1447
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RetentionTest.java
@@ -0,0 +1,16 @@
+package com.reflectoring;
+
+public class RetentionTest {
+
+ public static void main(String[] args) {
+
+ SourceRetention[] sourceRetention = new EmployeeRetentionAnnotation().getClass().getAnnotationsByType(SourceRetention.class);
+ System.out.println("Source Retentions at run-time: " + sourceRetention.length);
+
+ RuntimeRetention[] runtimeRetention = new EmployeeRetentionAnnotation().getClass().getAnnotationsByType(RuntimeRetention.class);
+ System.out.println("Run-time Retentions at run-time: " + runtimeRetention.length);
+
+ ClassRetention[] classRetention = new EmployeeRetentionAnnotation().getClass().getAnnotationsByType(ClassRetention.class);
+ System.out.println("Class Retentions at run-time: " + classRetention.length);
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RuntimeRetention.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RuntimeRetention.java
new file mode 100644
index 000000000..d6063af2f
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/RuntimeRetention.java
@@ -0,0 +1,11 @@
+package com.reflectoring;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RuntimeRetention {
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SafeVarargsTest.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SafeVarargsTest.java
new file mode 100644
index 000000000..727325032
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SafeVarargsTest.java
@@ -0,0 +1,57 @@
+package com.reflectoring;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SafeVarargsTest {
+
+ private void printString(String test1) {
+
+ System.out.println(test1);
+ }
+
+ private void printString(String test1, String test2) {
+
+ System.out.println(test1);
+ System.out.println(test2);
+ }
+
+ private void printStringVarargs(String... tests) {
+
+ for (String test : tests) {
+
+ System.out.println(test);
+ }
+ }
+
+ @SafeVarargs
+ private void printStringSafeVarargs(List... testStringLists) {
+
+ for (List testStringList : testStringLists) {
+
+ for (String testString : testStringList) {
+
+ System.out.println(testString);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+
+ SafeVarargsTest test = new SafeVarargsTest();
+
+ test.printString("String1");
+ test.printString("*******");
+
+ test.printString("String1", "String2");
+ test.printString("*******");
+
+ test.printStringVarargs("String1", "String2");
+ test.printString("*******");
+
+ List testStringList1 = Arrays.asList("One", "Two");
+ List testStringList2 = Arrays.asList("Three", "Four");
+
+ test.printStringSafeVarargs(testStringList1, testStringList2);
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SingleValueAnnotatedEmployee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SingleValueAnnotatedEmployee.java
new file mode 100644
index 000000000..b480b9d06
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SingleValueAnnotatedEmployee.java
@@ -0,0 +1,19 @@
+package com.reflectoring;
+
+@SingleValueAnnotationCompany("XYZ")
+public class SingleValueAnnotatedEmployee {
+
+ private int id;
+ private String name;
+
+ public SingleValueAnnotatedEmployee(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public void getEmployeeDetails(){
+
+ System.out.println("Employee Id: " + id);
+ System.out.println("Employee Name: " + name);
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SingleValueAnnotationCompany.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SingleValueAnnotationCompany.java
new file mode 100644
index 000000000..2d249357a
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SingleValueAnnotationCompany.java
@@ -0,0 +1,9 @@
+package com.reflectoring;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SingleValueAnnotationCompany {
+ String value() default "ABC";
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SourceRetention.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SourceRetention.java
new file mode 100644
index 000000000..a120ac0f0
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SourceRetention.java
@@ -0,0 +1,8 @@
+package com.reflectoring;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+public @interface SourceRetention {
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SuppressWarningsDemo.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SuppressWarningsDemo.java
new file mode 100644
index 000000000..1a81f1b93
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/SuppressWarningsDemo.java
@@ -0,0 +1,22 @@
+package com.reflectoring;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class SuppressWarningsDemo {
+
+ public static void main(String[] args) {
+
+ SuppressWarningsDemo swDemo = new SuppressWarningsDemo();
+ swDemo.testSuppressWarning();
+ }
+
+ public void testSuppressWarning() {
+
+ Map testMap = new HashMap();
+ testMap.put(1, "Item_1");
+ testMap.put(2, "Item_2");
+ testMap.put(3, "Item_3");
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Test.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Test.java
new file mode 100644
index 000000000..111e8e981
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/Test.java
@@ -0,0 +1,11 @@
+package com.reflectoring;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Test {
+}
\ No newline at end of file
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestAnnotatedMethods.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestAnnotatedMethods.java
new file mode 100644
index 000000000..ba44ea803
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestAnnotatedMethods.java
@@ -0,0 +1,31 @@
+package com.reflectoring;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+public class TestAnnotatedMethods {
+
+ public static void main(String[] args) throws Exception {
+
+ Class annotatedMethodsClass = AnnotatedMethods.class;
+
+ for (Method method : annotatedMethodsClass.getDeclaredMethods()) {
+
+ Annotation annotation = method.getAnnotation(Test.class);
+ Test test = (Test) annotation;
+
+ // If the annotation is not null
+ if (test != null) {
+
+ try {
+ method.invoke(annotatedMethodsClass.getDeclaredConstructor().newInstance());
+ } catch (Throwable ex) {
+ System.out.println(ex.getCause());
+ }
+
+ }
+ }
+ }
+}
+
+
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestCustomAnnotatedEmployee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestCustomAnnotatedEmployee.java
new file mode 100644
index 000000000..24bc2c6f3
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestCustomAnnotatedEmployee.java
@@ -0,0 +1,18 @@
+package com.reflectoring;
+
+import java.lang.annotation.Annotation;
+
+public class TestCustomAnnotatedEmployee {
+
+ public static void main(String[] args) {
+
+ CustomAnnotatedEmployee employee = new CustomAnnotatedEmployee(1, "John Doe");
+ employee.getEmployeeDetails();
+
+ Annotation companyAnnotation = employee.getClass().getAnnotation(Company.class);
+ Company company = (Company)companyAnnotation;
+
+ System.out.println("Company Name: " + company.name());
+ System.out.println("Company City: " + company.city());
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestCustomAnnotatedManager.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestCustomAnnotatedManager.java
new file mode 100644
index 000000000..34d56bdf8
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestCustomAnnotatedManager.java
@@ -0,0 +1,18 @@
+package com.reflectoring;
+
+import java.lang.annotation.Annotation;
+
+public class TestCustomAnnotatedManager {
+
+ public static void main(String[] args) {
+
+ CustomAnnotatedManager manager = new CustomAnnotatedManager(1, "John Doe");
+ manager.getEmployeeDetails();
+
+ Annotation companyAnnotation = manager.getClass().getAnnotation(Company.class);
+ Company company = (Company)companyAnnotation;
+
+ System.out.println("Company Name: " + company.name());
+ System.out.println("Company City: " + company.city());
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestMarkerAnnotation.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestMarkerAnnotation.java
new file mode 100644
index 000000000..01f9bc568
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestMarkerAnnotation.java
@@ -0,0 +1,16 @@
+package com.reflectoring;
+
+public class TestMarkerAnnotation {
+
+ public static void main(String[] args) {
+
+ XYZClient client = new XYZClient();
+ Class clientClass = client.getClass();
+
+ if (clientClass.isAnnotationPresent(CSV.class)){
+ System.out.println("Write client data to CSV.");
+ } else {
+ System.out.println("Write client data to Excel file.");
+ }
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestMultiValueAnnotatedEmployee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestMultiValueAnnotatedEmployee.java
new file mode 100644
index 000000000..f5fb3743b
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestMultiValueAnnotatedEmployee.java
@@ -0,0 +1,17 @@
+package com.reflectoring;
+
+import java.lang.annotation.Annotation;
+
+public class TestMultiValueAnnotatedEmployee {
+
+ public static void main(String[] args) {
+
+ MultiValueAnnotatedEmployee employee = new MultiValueAnnotatedEmployee();
+
+ Annotation companyAnnotation = employee.getClass().getAnnotation(Company.class);
+ Company company = (Company)companyAnnotation;
+
+ System.out.println("Company Name: " + company.name());
+ System.out.println("Company City: " + company.city());
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestRepeatedAnnotation.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestRepeatedAnnotation.java
new file mode 100644
index 000000000..2948d0c4e
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestRepeatedAnnotation.java
@@ -0,0 +1,14 @@
+package com.reflectoring;
+
+public class TestRepeatedAnnotation {
+
+ public static void main(String[] args) {
+
+ RepeatableCompany[] repeatableCompanies = RepeatedAnnotatedEmployee.class.getAnnotationsByType(RepeatableCompany.class);
+ for (RepeatableCompany repeatableCompany : repeatableCompanies) {
+
+ System.out.println("Name: " + repeatableCompany.name());
+ System.out.println("City: " + repeatableCompany.city());
+ }
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestSingleValueAnnotatedEmployee.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestSingleValueAnnotatedEmployee.java
new file mode 100644
index 000000000..7449b3d84
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/TestSingleValueAnnotatedEmployee.java
@@ -0,0 +1,17 @@
+package com.reflectoring;
+
+import java.lang.annotation.Annotation;
+
+public class TestSingleValueAnnotatedEmployee {
+
+ public static void main(String[] args) {
+
+ SingleValueAnnotatedEmployee employee = new SingleValueAnnotatedEmployee(1, "John Doe");
+ employee.getEmployeeDetails();
+
+ Annotation companyAnnotation = employee.getClass().getAnnotation(SingleValueAnnotationCompany.class);
+ SingleValueAnnotationCompany company = (SingleValueAnnotationCompany)companyAnnotation;
+
+ System.out.println("Company Name: " + company.value());
+ }
+}
diff --git a/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/XYZClient.java b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/XYZClient.java
new file mode 100644
index 000000000..a84d07c8d
--- /dev/null
+++ b/core-java/annotation-processing/introduction-to-annotations/src/main/java/com/reflectoring/XYZClient.java
@@ -0,0 +1,6 @@
+package com.reflectoring;
+
+@CSV
+public class XYZClient {
+
+}
\ No newline at end of file
diff --git a/core-java/collectionops/.mvn/wrapper/MavenWrapperDownloader.java b/core-java/collectionops/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/core-java/collectionops/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/core-java/collectionops/.mvn/wrapper/maven-wrapper.jar b/core-java/collectionops/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/core-java/collectionops/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/core-java/collectionops/.mvn/wrapper/maven-wrapper.properties b/core-java/collectionops/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/core-java/collectionops/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/core-java/collectionops/README.md b/core-java/collectionops/README.md
new file mode 100644
index 000000000..ffca4ff76
--- /dev/null
+++ b/core-java/collectionops/README.md
@@ -0,0 +1,3 @@
+# Related Blog Posts
+
+* [Logical Operations Between Java Collections](https://reflectoring.io/logical-ops-on-java-collections/)
diff --git a/core-java/collectionops/mvnw b/core-java/collectionops/mvnw
new file mode 100755
index 000000000..41c0f0c23
--- /dev/null
+++ b/core-java/collectionops/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/core-java/collectionops/mvnw.cmd b/core-java/collectionops/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/core-java/collectionops/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/core-java/collectionops/pom.xml b/core-java/collectionops/pom.xml
new file mode 100644
index 000000000..22758b46d
--- /dev/null
+++ b/core-java/collectionops/pom.xml
@@ -0,0 +1,24 @@
+
+ 4.0.0
+ io.pratik
+ logicalops
+ 0.0.1-SNAPSHOT
+
+
+
+
+ org.apache.commons
+ commons-collections4
+ 4.4
+
+
+ com.google.guava
+ guava
+ 31.0.1-jre
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java/collectionops/src/main/java/io/pratik/CollectionHelper.java b/core-java/collectionops/src/main/java/io/pratik/CollectionHelper.java
new file mode 100644
index 000000000..62357c090
--- /dev/null
+++ b/core-java/collectionops/src/main/java/io/pratik/CollectionHelper.java
@@ -0,0 +1,135 @@
+/**
+ *
+ */
+package io.pratik;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import com.google.common.collect.Lists;
+
+/**
+ * @author pratikdas
+ *
+ */
+public class CollectionHelper {
+
+ public List[] split(List listToSplit){
+ // determine the endpoints to use in `list.subList()` method
+ int[] endpoints = {0, (listToSplit.size() + 1)/2, listToSplit.size()};
+
+
+ List> sublists =
+ IntStream.rangeClosed(0, 1)
+ .mapToObj(i -> listToSplit.subList(endpoints[i], endpoints[i + 1]))
+ .collect(Collectors.toList());
+
+ // return an array containing both lists
+ return new List[] {sublists.get(0), sublists.get(1)};
+ }
+
+ public List add(final List collA, final List collB){
+
+ return Stream.concat(collA.stream(),
+ collB.stream())
+ .collect(Collectors.toList());
+
+
+ }
+
+ public List addWithFilter(final List collA, final List collB){
+
+ return Stream.concat(collA.stream(),
+ collB.stream())
+ .filter(element -> element > 2 )
+ .collect(Collectors.toList());
+ }
+
+ public List union(final List collA, final List collB){
+ Set set = new LinkedHashSet<>();
+ set.addAll(collA);
+ set.addAll(collB);
+
+ return new ArrayList<>(set);
+
+ }
+
+ public List intersection(final List collA, final List collB){
+ List intersectElements = collA.stream()
+ .filter(collB :: contains)
+ .collect(Collectors.toList());
+
+ if(!intersectElements.isEmpty()) {
+ return intersectElements;
+ }else {
+ return Collections.emptyList();
+ }
+
+ }
+
+ public Collection> partition(final List collA, final int chunkSize){
+ final AtomicInteger counter = new AtomicInteger();
+
+ final Collection> result = collA.stream()
+ .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize))
+ .values();
+
+ return result;
+
+ }
+
+
+ public List removeDuplicates(final List collA){
+ List listWithoutDuplicates = new ArrayList<>(
+ new LinkedHashSet<>(collA));
+
+ return listWithoutDuplicates;
+ }
+
+ public List xor(final List collA, final List collB){
+
+ List listOfAnotInB = collA.stream().filter(element->{
+ return !collB.contains(element);
+ }).collect(Collectors.toList());
+
+ List listOfBnotInA = collB.stream().filter(element->{
+ return !collA.contains(element);
+ }).collect(Collectors.toList());
+
+ return Stream.concat(listOfAnotInB.stream(),
+ listOfBnotInA.stream())
+ .collect(Collectors.toList());
+ }
+
+ public List not(final List collA, final List collB){
+
+ List notList = collA.stream().filter(element->{
+ return !collB.contains(element);
+ }).collect(Collectors.toList());
+
+ return notList;
+ }
+
+ public List subtract(final List collA, final List collB){
+ List intersectElements = intersection(collA,collB);
+
+ List subtractedElements = collA.stream().filter(element->!intersectElements.contains(element)).collect(Collectors.toList());
+
+ if(!subtractedElements.isEmpty()) {
+ return subtractedElements;
+ }else {
+ return Collections.emptyList();
+ }
+
+ }
+
+}
diff --git a/core-java/collectionops/src/test/java/io/pratik/tests/CollectionHelperTest.java b/core-java/collectionops/src/test/java/io/pratik/tests/CollectionHelperTest.java
new file mode 100644
index 000000000..a906d4e12
--- /dev/null
+++ b/core-java/collectionops/src/test/java/io/pratik/tests/CollectionHelperTest.java
@@ -0,0 +1,178 @@
+/**
+ *
+ */
+package io.pratik.tests;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import io.pratik.CollectionHelper;
+
+/**
+ * @author pratikdas
+ *
+ */
+class CollectionHelperTest {
+
+ private CollectionHelper collectionHelper;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeEach
+ void setUp() throws Exception {
+ collectionHelper = new CollectionHelper();
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @AfterEach
+ void tearDown() throws Exception {
+ }
+
+ @Test
+ void testUnion() {
+ List union = collectionHelper.union(
+ List.of(9, 8, 5, 4, 7),
+ List.of(1, 3, 99, 4, 7));
+
+
+ Assertions.assertArrayEquals(
+ List.of(9, 8, 5, 4, 7, 1, 3, 99).toArray(),
+ union.toArray());
+
+ }
+
+ @Test
+ void testIntersection() {
+ List intersection = collectionHelper.intersection(
+ List.of(9,8,5,4,7, 15, 15),
+ List.of(1,3,99,4,7));
+
+ Assertions.assertArrayEquals(
+ List.of(4,7).toArray(),
+ intersection.toArray());
+ }
+
+ @Test
+ void testXOR() {
+ List xorList = collectionHelper.xor(
+ List.of(9, 8, 5, 4, 7),
+ List.of(1, 99, 4, 7));
+
+ Assertions.assertArrayEquals(
+ List.of(9, 8, 5, 1, 99).toArray(),
+ xorList.toArray());
+ }
+
+ @Test
+ void testNOT() {
+ List xorList = collectionHelper.not(
+ List.of(9,8,5,4,7),
+ List.of(1,99,4,7));
+
+ Assertions.assertArrayEquals(
+ List.of(9,8,5).toArray(),
+ xorList.toArray());
+ }
+
+ @Test
+ void testAddition() {
+ List sub = collectionHelper.add(
+ List.of(9,8,5,4),
+ List.of(1,3,99,4,7));
+
+
+ Assertions.assertArrayEquals(
+ List.of(9,8,5,4,1,3,99,4,7).toArray(),
+ sub.toArray());
+ }
+
+ @Test
+ void testAdditionWithFilter() {
+ List list = collectionHelper.addWithFilter(
+ List.of(9,8,5,4),
+ List.of(1,3,99,4,7));
+
+
+ Assertions.assertArrayEquals(
+ List.of(9,8,5,4,3,99,4,7).toArray(),
+ list.toArray());
+ }
+
+
+ @Test
+ void testSubtraction() {
+ List sub = collectionHelper.subtract(
+ List.of(9,8,5,4,7, 15, 15),
+ List.of(1,3,99,4,7));
+
+
+ Assertions.assertArrayEquals(
+ List.of(9,8,5,15,15).toArray(),
+ sub.toArray());
+ }
+
+ @Test
+ void testPartition() {
+ Collection> partitions = collectionHelper.partition(
+ List.of(9, 8, 5, 4, 7, 15, 15), 2);
+
+ Iterator> iter = partitions.iterator();
+
+ int loop = 0;
+ while(iter.hasNext()) {
+ List element = iter.next();
+ System.out.println(element);
+ if(loop == 0)
+ assertArrayEquals(List.of(9, 8).toArray(),element.toArray());
+ else if(loop == 1)
+ assertArrayEquals(List.of(5, 4).toArray(),element.toArray());
+ else if(loop == 2)
+ assertArrayEquals(List.of(7, 15).toArray(),element.toArray());
+ else if(loop == 3)
+ assertArrayEquals(List.of(15).toArray(),element.toArray());
+
+ ++loop;
+ }
+
+
+ }
+
+ @Test
+ void testRemoveDuplicates() {
+ List uniqueElements = collectionHelper.removeDuplicates(
+ List.of(9, 8, 5, 4, 4, 7, 15, 15));
+
+
+
+ Assertions.assertArrayEquals(
+ List.of(9, 8, 5, 4, 7, 15).toArray(),
+ uniqueElements.toArray());
+ }
+
+ @Test
+ void testSplit() {
+ List[] subLists = collectionHelper.split(
+ List.of(9, 8, 5, 4, 7, 15, 15));
+
+
+ Assertions.assertArrayEquals(
+ List.of(9,8,5,4).toArray(),
+ subLists[0].toArray());
+
+ Assertions.assertArrayEquals(
+ List.of(7,15,15).toArray(),
+ subLists[1].toArray());
+ }
+
+}
diff --git a/core-java/functional-programming/functional-interfaces/.gitignore b/core-java/functional-programming/functional-interfaces/.gitignore
new file mode 100644
index 000000000..3aff99610
--- /dev/null
+++ b/core-java/functional-programming/functional-interfaces/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+target/*
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
\ No newline at end of file
diff --git a/core-java/functional-programming/functional-interfaces/.mvn/wrapper/MavenWrapperDownloader.java b/core-java/functional-programming/functional-interfaces/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/core-java/functional-programming/functional-interfaces/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/core-java/functional-programming/functional-interfaces/.mvn/wrapper/maven-wrapper.jar b/core-java/functional-programming/functional-interfaces/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..2cc7d4a55
Binary files /dev/null and b/core-java/functional-programming/functional-interfaces/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/core-java/functional-programming/functional-interfaces/.mvn/wrapper/maven-wrapper.properties b/core-java/functional-programming/functional-interfaces/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/core-java/functional-programming/functional-interfaces/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/core-java/functional-programming/functional-interfaces/README.md b/core-java/functional-programming/functional-interfaces/README.md
new file mode 100644
index 000000000..5247c8abc
--- /dev/null
+++ b/core-java/functional-programming/functional-interfaces/README.md
@@ -0,0 +1,3 @@
+# Related Blog Posts
+
+* [One Stop Guide to Java Functional Interfaces](https://reflectoring.io/one-stop-guide-to-java-functional-interfaces/)
diff --git a/core-java/functional-programming/functional-interfaces/mvnw b/core-java/functional-programming/functional-interfaces/mvnw
new file mode 100644
index 000000000..41c0f0c23
--- /dev/null
+++ b/core-java/functional-programming/functional-interfaces/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/core-java/functional-programming/functional-interfaces/mvnw.cmd b/core-java/functional-programming/functional-interfaces/mvnw.cmd
new file mode 100644
index 000000000..86115719e
--- /dev/null
+++ b/core-java/functional-programming/functional-interfaces/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/core-java/functional-programming/functional-interfaces/pom.xml b/core-java/functional-programming/functional-interfaces/pom.xml
new file mode 100644
index 000000000..a871d179b
--- /dev/null
+++ b/core-java/functional-programming/functional-interfaces/pom.xml
@@ -0,0 +1,85 @@
+
+
+
+ 4.0.0
+
+ io.reflectoring
+ functional-interfaces
+ 1.0-SNAPSHOT
+
+ Java Functional Interfaces
+ https://reflectoring.io
+
+
+ UTF-8
+ 17
+ 17
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.10.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.10.0
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.24.2
+ test
+
+
+
+
+ org.slf4j
+ slf4j-simple
+ 2.0.9
+ test
+
+
+
+ org.slf4j
+ slf4j-api
+ 2.0.9
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.28
+
+
+
+ jakarta.validation
+ jakarta.validation-api
+ 3.0.2
+
+
+
+ org.hibernate.validator
+ hibernate-validator
+ 8.0.1.Final
+
+
+
+
+
+
+