├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── event.json ├── mvnw ├── mvnw.cmd ├── pom.xml ├── src ├── main │ ├── java │ │ └── com │ │ │ └── mj │ │ │ └── aws │ │ │ └── lambda │ │ │ └── sqs │ │ │ ├── AwsLambdaSqsApplication.java │ │ │ ├── AwsLambdaSqsFunction.java │ │ │ ├── AwsLambdaSqsFunctionHandler.java │ │ │ └── config │ │ │ ├── AppConfig.java │ │ │ └── AwsClientConfig.java │ └── resources │ │ ├── application-aws.properties │ │ ├── application-local.properties │ │ └── application.properties └── test │ └── java │ └── com │ └── mj │ └── aws │ └── lambda │ └── sqs │ └── AwsLambdaSqsApplicationTests.java ├── template-sar.yaml └── template.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengjiann/aws-lambda-sqs/b6bd1f034d26aea06241ee85b2485c7222a6b6a3/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aws-lambda-sqs 2 | A sample Java AWS Lambda function to listen to AWS SQS queue and receive messages from the queue. 3 | 4 | # Guide 5 | - Create a new AWS SQS queue or use any existing queues. 6 | - Update the value for aws.sqs.queue.url in the application.properties to your queue url. 7 | - Build the project using: mvn clean install 8 | - Create and configure using the aws lambda requirement below. 9 | - Upload the jar file with suffix "-aws" to AWS lambda. 10 | - Update the handler field with: com.mj.aws.lambda.sqs.AwsLambdaSqsFunctionHandler 11 | - Trigger the Lambda function and check the log from Cloud Watch. 12 | 13 | # AWS Lambda Requirements: 14 | - 256 MB of Memory. (Can try with lower one) 15 | - Timeout 1 min. 16 | - Execution role 17 | -- Access to SQS Policy 18 | -- Access to Cloud watch for logging Policy 19 | 20 | # AWS SQS 21 | - You can choose FIFO queue. 22 | 23 | # Libraries 24 | - Spring Cloud Function: https://spring.io/blog/2017/07/05/introducing-spring-cloud-function 25 | - AWS Java SDK 26 | - Lombok 27 | - Log4j 28 | - Jackson Object Mapper 29 | - Maven 30 | 31 | # Credits 32 | Based on https://dzone.com/articles/run-code-with-spring-cloud-function-on-aws-lambda 33 | 34 | # Guide to local deployment using sam-local and localstack 35 | - Full guide: https://medium.com/@mengjiannlee/local-deployment-of-aws-lambda-spring-cloud-function-using-sam-local-and-localstack-dc7669110906 36 | - Install Docker on your machine: https://www.docker.com/get-docker 37 | - Install aws-sam-local following the guide on the github readme. 38 | - Clone the localstack repo to your machine. Then, navigate to the local branch folder to spin up the Localstack using docker-compose: TMPDIR=/private$TMPDIR docker-compose up 39 | - You should seet "localstack_1 | Ready " when the localstack container is spinned up. 40 | - Then, you should check the network created for localstack container. The default is: localstack_default. 41 | - Or you run the command: docker inspect -f "{{json .NetworkSettings.Networks }}". 42 | - Now, you will need to create messages in the queues: 43 | - Create queue: 44 | - aws --endpoint-url=http://localhost:4576 sqs create-queue --queue-name test_queue 45 | - List queue: 46 | - aws --endpoint-url=http://localhost:4576 sqs list-queues 47 | - Send message: 48 | - aws --endpoint-url=http://localhost:4576 sqs send-message --queue-url http://localhost:4576/queue/test_queue --message-body 'Test Message!' 49 | - Finally, navigate to the folder where the SAM template resides and run: 50 | - sam local invoke AwsLambdaSqsLocal --log-file ./output.log -e event.json --docker-network 51 | - Since the aws lambda function is executed in a docker container, it cant access the localstack deployed on the host machine. That is the reason you will need to deploy the container containing the lambda function to the same network as the localstack. 52 | - You can check on the output.log for debuging purpose. 53 | - There is also another way to pass trigger event to the lambda. You can read more from the sam-local github page. 54 | 55 | # Guide to deploy as SAR 56 | - Upload the sam template `template-sar.yaml` to the SAR console. 57 | - Remember to update the `CodeUri` to point to the jar in your bucket. 58 | - For the S3 bucket serving the `CodeUri`, the following is required for the bucket policy. 59 | ```` 60 | { 61 | "Version": "2012-10-17", 62 | "Statement": [ 63 | { 64 | "Effect": "Allow", 65 | "Principal": { 66 | "Service": "serverlessrepo.amazonaws.com" 67 | }, 68 | "Action": "s3:GetObject", 69 | "Resource": "arn:aws:s3:::/*" 70 | } 71 | ] 72 | } 73 | ```` 74 | 75 | 76 | # Reference: 77 | - CLI tool for local development and testing of AWS lambda: https://github.com/awslabs/aws-sam-local 78 | - For setting up local AWS cloud stack: https://github.com/localstack/localstack 79 | - Reference for command: https://lobster1234.github.io/2017/04/05/working-with-localstack-command-line/ 80 | - http://bluesock.org/~willkg/blog/dev/using_localstack_for_s3.html 81 | - http://www.frommknecht.net/spring-cloud-aws-messaging/ 82 | - https://docs.aws.amazon.com/serverlessrepo/latest/devguide/serverlessrepo-how-to-publish.html 83 | - https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md 84 | - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html 85 | - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-api-permissions-reference.html 86 | -------------------------------------------------------------------------------- /event.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.mj 7 | aws-lambda-sqs 8 | 0.0.3-SNAPSHOT 9 | jar 10 | 11 | aws-lambda-sqs 12 | Spring Cloud Function template to listen to AWS SQS queue. 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.0.RELEASE 18 | 19 | 20 | 21 | 22 | 1.8 23 | 1.0.10.RELEASE 24 | Greenwich.SR1 25 | 1.11.226 26 | 27 | 2.0.2 28 | 2.0.1.RELEASE 29 | com.mj.aws.lambda.sqs.AwsLambdaSqsApplication 30 | 31 | 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-function-context 36 | ${spring-cloud-function.version} 37 | 38 | 39 | 40 | org.springframework.cloud 41 | spring-cloud-starter-function-web 42 | ${spring-cloud-function.version} 43 | 44 | 45 | 46 | org.springframework.cloud 47 | spring-cloud-function-adapter-aws 48 | ${spring-cloud-function.version} 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | 58 | 59 | com.amazonaws 60 | aws-java-sdk-sqs 61 | ${aws.sdk.version} 62 | 63 | 64 | 65 | 66 | org.slf4j 67 | slf4j-log4j12 68 | 69 | 70 | 71 | com.amazonaws 72 | aws-lambda-java-log4j 73 | 1.0.0 74 | 75 | 76 | 77 | org.projectlombok 78 | lombok 79 | true 80 | 81 | 82 | 83 | com.fasterxml.jackson.core 84 | jackson-databind 85 | 86 | 87 | 88 | com.google.guava 89 | guava 90 | 23.3-jre 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-compiler-plugin 100 | 101 | 1.8 102 | 1.8 103 | 104 | 105 | 106 | org.springframework.boot 107 | spring-boot-maven-plugin 108 | 109 | 110 | org.springframework.boot.experimental 111 | spring-boot-thin-layout 112 | ${wrapper.version} 113 | 114 | 115 | 116 | 117 | 118 | org.apache.maven.plugins 119 | maven-shade-plugin 120 | 121 | false 122 | true 123 | aws 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | spring-snapshots 132 | Spring Snapshots 133 | https://repo.spring.io/snapshot 134 | 135 | true 136 | 137 | 138 | 139 | spring-milestones 140 | Spring Milestones 141 | https://repo.spring.io/milestone 142 | 143 | false 144 | 145 | 146 | 147 | 148 | 149 | spring-snapshots 150 | Spring Snapshots 151 | https://repo.spring.io/snapshot 152 | 153 | true 154 | 155 | 156 | 157 | spring-milestones 158 | Spring Milestones 159 | https://repo.spring.io/milestone 160 | 161 | false 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /src/main/java/com/mj/aws/lambda/sqs/AwsLambdaSqsApplication.java: -------------------------------------------------------------------------------- 1 | package com.mj.aws.lambda.sqs; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class AwsLambdaSqsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(AwsLambdaSqsApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/mj/aws/lambda/sqs/AwsLambdaSqsFunction.java: -------------------------------------------------------------------------------- 1 | package com.mj.aws.lambda.sqs; 2 | 3 | import com.amazonaws.services.sqs.AmazonSQS; 4 | import com.amazonaws.services.sqs.model.*; 5 | import com.mj.aws.lambda.sqs.config.AppConfig; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.function.Function; 13 | 14 | @Slf4j 15 | @Component("awsLambdaSqsFunction") 16 | public class AwsLambdaSqsFunction implements Function{ 17 | 18 | @Autowired 19 | private AppConfig appConfig; 20 | 21 | @Autowired 22 | private AmazonSQS amazonSqs; 23 | 24 | @Override 25 | public Void apply(Void empty) { 26 | 27 | String queueUrl = appConfig.getQueueUrl(); 28 | 29 | log.info("Retrieved queues: {}",amazonSqs.listQueues().getQueueUrls().toString()); 30 | 31 | List messageList = this.getQueueMessageByQueueUrl(queueUrl); 32 | 33 | for (Message message : messageList) { 34 | log.info("Received message: {}", message.toString()); 35 | } 36 | 37 | this.deleteMessagesByQueueUrl(messageList,queueUrl); 38 | 39 | return empty; 40 | } 41 | 42 | private void deleteMessagesByQueueUrl(List messageList, String queueUrl) { 43 | 44 | if(messageList == null || messageList.isEmpty()){ 45 | log.info("Empty list for removal"); 46 | return; 47 | } 48 | 49 | List deleteMessageEntries = new ArrayList<>(); 50 | 51 | messageList.forEach(message -> 52 | deleteMessageEntries.add( 53 | new DeleteMessageBatchRequestEntry(message.getMessageId(),message.getReceiptHandle()) 54 | )); 55 | 56 | DeleteMessageBatchRequest deleteRequest = new DeleteMessageBatchRequest(); 57 | deleteRequest.setQueueUrl(queueUrl); 58 | deleteRequest.setEntries(deleteMessageEntries); 59 | 60 | DeleteMessageBatchResult result = amazonSqs.deleteMessageBatch(deleteRequest); 61 | 62 | log.info("Successfully removed size: {}",result.getSuccessful().size()); 63 | log.error("Failed to removed size: {}",result.getFailed().size()); 64 | } 65 | 66 | private List getQueueMessageByQueueUrl(String queueUrl) { 67 | log.info("Getting messages from queue url: {}", queueUrl); 68 | 69 | ReceiveMessageRequest messageRequest = new ReceiveMessageRequest(queueUrl). 70 | withWaitTimeSeconds(5).withMaxNumberOfMessages(2); 71 | 72 | List messages = amazonSqs.receiveMessage(messageRequest).getMessages(); 73 | 74 | log.info("Received total messages size: {}", messages.size()); 75 | 76 | return messages; 77 | } 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/mj/aws/lambda/sqs/AwsLambdaSqsFunctionHandler.java: -------------------------------------------------------------------------------- 1 | package com.mj.aws.lambda.sqs; 2 | 3 | import org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler; 4 | 5 | public class AwsLambdaSqsFunctionHandler extends SpringBootRequestHandler{ 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/mj/aws/lambda/sqs/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.mj.aws.lambda.sqs.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.PropertySource; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Data 9 | @Component 10 | @PropertySource("classpath:application-${spring.profiles.active}.properties") 11 | public class AppConfig { 12 | 13 | @Value("${aws.sqs.queue.url}") 14 | private String queueUrl; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/mj/aws/lambda/sqs/config/AwsClientConfig.java: -------------------------------------------------------------------------------- 1 | package com.mj.aws.lambda.sqs.config; 2 | 3 | import com.amazonaws.client.builder.AwsClientBuilder; 4 | import com.amazonaws.services.sqs.AmazonSQS; 5 | import com.amazonaws.services.sqs.AmazonSQSClientBuilder; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Profile; 10 | 11 | 12 | @Slf4j 13 | @Configuration 14 | public class AwsClientConfig { 15 | 16 | @Bean 17 | @Profile("aws") 18 | public AmazonSQS awsSQSClient(){ 19 | return AmazonSQSClientBuilder.defaultClient(); 20 | } 21 | 22 | @Bean 23 | @Profile("local") 24 | public AmazonSQS localstackSqsClient(){ 25 | return AmazonSQSClientBuilder.standard() 26 | .withEndpointConfiguration( 27 | new AwsClientBuilder.EndpointConfiguration("http://localstack:4576","eu-west-1")) 28 | .build(); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/application-aws.properties: -------------------------------------------------------------------------------- 1 | # AWS Lambda Function 2 | function.name=awsLambdaSqsFunction 3 | spring.jmx.enabled=true 4 | 5 | # AWS SQS 6 | aws.sqs.queue.url=${QUEUE_URL:http://localhost:8080} -------------------------------------------------------------------------------- /src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | # AWS Lambda Function 2 | function.name=awsLambdaSqsFunction 3 | spring.jmx.enabled=true 4 | 5 | # AWS SQS 6 | aws.sqs.queue.url=http://localstack:4576/queue/test_queue -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Active profiles 2 | spring.profiles.active=${SPRING_PROFILES_ACTIVE:dev} -------------------------------------------------------------------------------- /src/test/java/com/mj/aws/lambda/sqs/AwsLambdaSqsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.mj.aws.lambda.sqs; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | //@RunWith(SpringRunner.class) 9 | //@SpringBootTest 10 | public class AwsLambdaSqsApplicationTests { 11 | 12 | // @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /template-sar.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Parameters: 3 | QueueName: 4 | Type: String 5 | Description: Queue name which the lambda will access 6 | QueueUrl: 7 | Type: String 8 | Description: Queue url which the lambda will access 9 | Transform: AWS::Serverless-2016-10-31 10 | Description: Spring Cloud Functions. 11 | Resources: 12 | AwsLambdaSqsLocal: 13 | Type: AWS::Serverless::Function 14 | Properties: 15 | FunctionName: aws-lambda-sqs 16 | Handler: com.mj.aws.lambda.sqs.AwsLambdaSqsFunctionHandler 17 | Description: For AWS Sqs Queue 18 | Runtime: java8 19 | CodeUri: s3://my-sar-artifact/aws-lambda-sqs/aws-lambda-sqs-0.0.4-SNAPSHOT-aws.jar 20 | MemorySize: 320 21 | Timeout: 240 22 | Policies: 23 | - AWSLambdaExecute 24 | - Version: '2012-10-17' 25 | Statement: 26 | - Effect: Allow 27 | Action: 28 | - sqs:ChangeMessageVisibility 29 | - sqs:ChangeMessageVisibilityBatch 30 | - sqs:DeleteMessage 31 | - sqs:DeleteMessageBatch 32 | - sqs:GetQueueAttributes 33 | - sqs:ReceiveMessage 34 | Resource: 35 | - Fn::Sub: 36 | - arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${queueName} 37 | - queueName: 38 | Ref: QueueName 39 | - Version: '2012-10-17' 40 | Statement: 41 | - Effect: Allow 42 | Action: 43 | - sqs:ListQueues 44 | - sqs:GetQueueAttributes 45 | - sqs:GetQueueUrl 46 | Resource: 47 | - !Sub arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:* 48 | Environment: 49 | Variables: 50 | SPRING_PROFILES_ACTIVE: aws 51 | QUEUE_URL: 52 | Ref: QueueUrl -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: Spring Cloud Functions. 4 | Resources: 5 | AwsLambdaSqsLocal: 6 | Type: AWS::Serverless::Function 7 | Properties: 8 | FunctionName: aws-lambda-sqs 9 | Handler: com.mj.aws.lambda.sqs.AwsLambdaSqsFunctionHandler 10 | Description: For AWS Sqs Queue 11 | Runtime: java8 12 | CodeUri: ./target/aws-lambda-sqs-0.0.2-SNAPSHOT-aws.jar 13 | MemorySize: 320 14 | Timeout: 120 15 | Environment: 16 | Variables: 17 | SPRING_PROFILES_ACTIVE: local 18 | --------------------------------------------------------------------------------