Skip to content

Commit 240dbac

Browse files
authored
Micronaut sample (#303)
* First import of micronaut native demo * Cleanup, upgrade dependencies and use latest GraalVM version * Change default shell for execution It seems, for those who don't have bash as their default shell, [[ is not valid syntax for `sh` (it did not run on my machine running Linux Mint 19 and zsh as my default, I got multiple `./docker-build.sh: 4: ./docker-build.sh: [[: not found` errors). I would propose changing this to `#!/bin/bash`, for which this is definitely valid syntax. * Further differentiates running via SAM vs AWS It wasn't initially super obvious to me how to run this locally, but I was able to figure it out. I'm hoping to make it clearer to anyone else looking at it in the future via this change. * Updated Micronaut readmes
1 parent 7dccd80 commit 240dbac

File tree

19 files changed

+552
-1
lines changed

19 files changed

+552
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ Follow the quick start guides in [our wiki](https://github.com/awslabs/aws-serve
99
* [Spring Boot 2 quick start](https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Spring-Boot2)
1010
* [Apache Struts quick start](https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Struts)
1111
* [Jersey quick start](https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Jersey)
12-
* [Spark quick start](https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Spark)
12+
* [Spark quick start](https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Spark)
13+
14+
* Micronaut [documentation](https://guides.micronaut.io/micronaut-function-aws-lambda/guide/index.html) and [demo](https://github.com/awslabs/aws-serverless-java-container/tree/master/samples/micronaut/pet-store)
1315

1416
Below is the most basic AWS Lambda handler example that launches a Spring application. You can also take a look at the [samples](https://github.com/awslabs/aws-serverless-java-container/tree/master/samples) in this repository, our main wiki page includes a [step-by-step guide](https://github.com/awslabs/aws-serverless-java-container/wiki#deploying-the-sample-applications) on how to deploy the various sample applications using Maven and [SAM](https://github.com/awslabs/serverless-application-model).
1517

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM amazonlinux:2017.03.1.20170812 as graalvm
2+
# install graal to amazon linux.
3+
ENV LANG=en_US.UTF-8
4+
5+
RUN yum install -y gcc gcc-c++ libc6-dev zlib1g-dev curl bash zlib zlib-devel zip \
6+
# && yum install -y libcxx libcxx-devel llvm-toolset-7 \
7+
&& rm -rf /var/cache/yum
8+
9+
10+
ENV GRAAL_VERSION 19.2.0.1
11+
ENV GRAAL_FILENAME graalvm-ce-linux-amd64-${GRAAL_VERSION}.tar.gz
12+
13+
RUN curl -4 -L https://github.com/oracle/graal/releases/download/vm-${GRAAL_VERSION}/graalvm-ce-linux-amd64-${GRAAL_VERSION}.tar.gz -o /tmp/${GRAAL_FILENAME}
14+
15+
RUN tar -zxvf /tmp/${GRAAL_FILENAME} -C /tmp \
16+
&& mv /tmp/graalvm-ce-${GRAAL_VERSION} /usr/lib/graalvm
17+
18+
RUN rm -rf /tmp/*
19+
RUN /usr/lib/graalvm/bin/gu install native-image
20+
ADD scripts/graalvm-build.sh /usr/local/bin/
21+
RUN chmod +x /usr/local/bin/graalvm-build.sh
22+
VOLUME ["/func"]
23+
WORKDIR /func
24+
ENTRYPOINT ["/usr/local/bin/graalvm-build.sh"]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Micronaut Native Pet store example
2+
3+
The [Micronaut framework](https://micronaut.io/) is compatible with Spring's annotations and makes it easy to use [GraalVM](https://www.graalvm.org/) to build application images into native binaries. Further, Micronaut includes builtin support for AWS Lambda.
4+
5+
This demo application shows how to use Micronaut to compile our standard pet store example, using Spring annotations, into a native binary with GraalVM and execute it in AWS Lambda. To run this demo, you will need to have [Gradle](https://gradle.org/) installed as well as [Docker](https://www.docker.com/) to run the GraalVM build.
6+
7+
With all the pre-requisites installed including:
8+
9+
* JDK 8 or above
10+
* Gradle 5.6.x
11+
12+
You should be able to build a native image of the application by running the `docker-build.sh` from the repository's root.
13+
14+
```bash
15+
$ ./docker-build.sh
16+
```
17+
18+
The build process will perform the following tasks:
19+
1. Use gradle to compile the application
20+
2. Create a `native-image` folder in the current directory
21+
3. Check if a Docker image called `graalvm-lambda-build` exists on the local machine. If not, create it using the `Dockerfile` in the root of the repository
22+
4. Run the docker image to execute the GraalVM build process
23+
24+
The output of the build is an executable file called `server` and a deployable zip called `function.zip` in the `native-image` folder:
25+
26+
```bash
27+
$ ls -lh native-image/
28+
total 75M
29+
-rwxr-xr-x 1 user user 36 Oct 1 16:01 bootstrap
30+
-rw-r--r-- 1 user user 18M Oct 1 16:01 function.zip
31+
-rwxr-xr-x 1 user user 57M Oct 1 16:01 server
32+
```
33+
34+
To run the lambda locally, you can utilize the SAM cli by running `./sam-local.sh`. This should start up the listeners in the `PetsController`, and you can test locally with your preferred http client.
35+
36+
For example, to test the GET /pets endpoint via curl:
37+
```bash
38+
curl localhost:3000/pets
39+
```
40+
41+
You should see JSON output of pets.
42+
43+
To deploy the application to AWS Lambda you can use the pre-configured `sam-native.yaml` file included in the repo. Using the AWS or SAM CLI, run the following commands:
44+
45+
```bash
46+
$ aws cloudformation package --template-file sam-native.yaml \
47+
--output-template-file packaged-sam.yaml \
48+
--s3-bucket <YOUR_S3_BUCKET>
49+
Uploading to d3e2617f3c8c2e8ca78e35a0dc856884 18553505 / 18553505.0 (100.00%)
50+
Successfully packaged artifacts and wrote output template to file packaged-sam.yaml.
51+
Execute the following command to deploy the packaged template
52+
aws cloudformation deploy --template-file /workspace/graal-spring-demo/packaged-sam.yaml --stack-name <YOUR STACK NAME>
53+
54+
55+
$ aws cloudformation deploy --template-file ./packaged-sam.yaml --stack-name MicronautGraalVmDemo --capabilities CAPABILITY_IAM
56+
57+
Waiting for changeset to be created..
58+
Waiting for stack create/update to complete
59+
Successfully created/updated stack - MicronautGraalVmDemo
60+
```
61+
62+
You can use the AWS CLI to get the API endpoint generated by the deployment process:
63+
64+
```bash
65+
aws cloudformation describe-stacks --stack-name MicronautGraalVmDemo --query Stacks[0].Outputs[0].OutputValue
66+
"https://xxxxxxxxxx.execute-api.xx-xxxx-1.amazonaws.com/Prod/pets"
67+
```
68+
69+
Make a test request to the API endpoint using curl or your preferred http client.
70+
71+
For example, to check the GET /pets endpoint via curl:
72+
```bash
73+
curl https://xxxxxxxxxx.execute-api.xx-xxxx-1.amazonaws.com/Prod/pets
74+
```
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
plugins {
2+
id "java"
3+
id "com.github.johnrengelman.shadow" version "5.0.0"
4+
id "application"
5+
id "net.ltgt.apt-eclipse" version "0.21"
6+
id "org.springframework.boot" version "2.1.8.RELEASE"
7+
id "io.spring.dependency-management" version "1.0.6.RELEASE"
8+
}
9+
10+
version "0.1"
11+
group "graal.spring.demo"
12+
13+
repositories {
14+
mavenCentral()
15+
maven { url "https://jcenter.bintray.com" }
16+
}
17+
18+
configurations {
19+
// for dependencies that are needed for development only
20+
developmentOnly
21+
}
22+
23+
dependencies {
24+
annotationProcessor platform("io.micronaut:micronaut-bom:$micronautVersion")
25+
annotationProcessor "io.micronaut:micronaut-graal"
26+
annotationProcessor "io.micronaut:micronaut-inject-java"
27+
annotationProcessor "io.micronaut:micronaut-validation"
28+
annotationProcessor "io.micronaut.spring:micronaut-spring-boot"
29+
annotationProcessor "io.micronaut.spring:micronaut-spring-boot-annotation"
30+
annotationProcessor "io.micronaut.spring:micronaut-spring-web-annotation"
31+
testAnnotationProcessor "io.micronaut.spring:micronaut-spring-web-annotation"
32+
33+
compileOnly "com.oracle.substratevm:svm"
34+
implementation platform("io.micronaut:micronaut-bom:$micronautVersion")
35+
implementation "io.micronaut:micronaut-http-client"
36+
implementation "io.micronaut:micronaut-inject"
37+
implementation "io.micronaut:micronaut-validation"
38+
implementation "io.micronaut:micronaut-runtime"
39+
implementation("io.micronaut.aws:micronaut-function-aws-custom-runtime:1.3.2") {
40+
exclude group: "com.fasterxml.jackson.module", module: "jackson-module-afterburner"
41+
}
42+
implementation("io.micronaut.aws:micronaut-function-aws-api-proxy:1.3.2") {
43+
exclude group: "com.fasterxml.jackson.module", module: "jackson-module-afterburner"
44+
}
45+
developmentOnly "io.micronaut:micronaut-http-server-netty"
46+
runtimeOnly "ch.qos.logback:logback-classic:1.2.3"
47+
testAnnotationProcessor platform("io.micronaut:micronaut-bom:$micronautVersion")
48+
testAnnotationProcessor "io.micronaut:micronaut-inject-java"
49+
testImplementation platform("io.micronaut:micronaut-bom:$micronautVersion")
50+
testImplementation "org.junit.jupiter:junit-jupiter-api"
51+
testImplementation "io.micronaut.test:micronaut-test-junit5"
52+
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
53+
54+
// spring support
55+
compile("org.springframework.boot:spring-boot-starter-web")
56+
runtime("io.micronaut.spring:micronaut-spring-boot:1.0.1")
57+
runtime("io.micronaut.spring:micronaut-spring-web:1.0.1")
58+
}
59+
60+
test.classpath += configurations.developmentOnly
61+
62+
mainClassName = "graal.spring.demo.Application"
63+
// use JUnit 5 platform
64+
test {
65+
useJUnitPlatform()
66+
}
67+
68+
shadowJar {
69+
mergeServiceFiles()
70+
}
71+
72+
run.classpath += configurations.developmentOnly
73+
run.jvmArgs('-noverify', '-XX:TieredStopAtLevel=1', '-Dcom.sun.management.jmxremote')
74+
tasks.withType(JavaCompile){
75+
options.encoding = "UTF-8"
76+
options.compilerArgs.add('-parameters')
77+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
DOCKER_IMAGE_NAME=graalvm-lambda-build
3+
4+
if [[ -d "${PWD}/native-image" ]]; then
5+
rm -rf native-image/*
6+
fi
7+
8+
gradle clean build --info
9+
10+
if [[ $? -ne 0 ]]; then
11+
echo "Gradle build failed"
12+
exit 1
13+
fi
14+
15+
mkdir -p ${PWD}/native-image
16+
17+
if [[ "$(docker images -q ${DOCKER_IMAGE_NAME} 2> /dev/null)" == "" ]]; then
18+
docker build . -t ${DOCKER_IMAGE_NAME}
19+
fi
20+
21+
docker run --rm -v ${PWD}:/func ${DOCKER_IMAGE_NAME}
22+
23+
if [[ -f "${PWD}/native-image/function.zip" ]]; then
24+
echo "The function is ready to deploy in the ./native-image/function.zip file. Use the sam-native.yaml template to set up your Lambda function and API"
25+
fi
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
micronautVersion=1.2.3
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
profile: service
2+
defaultPackage: com.amazonaws.micronaut.demo
3+
---
4+
testFramework: junit
5+
sourceLanguage: java
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
3+
./docker-build.sh
4+
sam local start-api -t sam-native.yaml
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Transform: AWS::Serverless-2016-10-31
3+
Description: AWS Serverless Micronaut API - graal.spring.demo::graal-spring-demo
4+
Globals:
5+
Api:
6+
EndpointConfiguration: REGIONAL
7+
Resources:
8+
GraalVMApiService:
9+
Type: AWS::Serverless::Function
10+
Properties:
11+
Handler: not.used.in.provided.runtime
12+
Runtime: provided
13+
CodeUri: native-image/function.zip
14+
MemorySize: 512
15+
Policies: AWSLambdaBasicExecutionRole
16+
Tracing: Active
17+
Timeout: 15
18+
Events:
19+
GetResource:
20+
Type: Api
21+
Properties:
22+
Path: /{proxy+}
23+
Method: any
24+
25+
Outputs:
26+
MicronautNativeServiceApi:
27+
Description: URL for application
28+
Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/pets'
29+
Export:
30+
Name: MicronautNativeServiceApi
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
set -euo pipefail
3+
./server

0 commit comments

Comments
 (0)