Skip to content

Commit 60e5bfa

Browse files
authored
Merge pull request #124 from awslabs/core
Merging for 1.0 release
2 parents fa6faeb + 650e54b commit 60e5bfa

File tree

86 files changed

+3201
-312
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+3201
-312
lines changed

CODE_OF_CONDUCT.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## Code of Conduct
2+
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3+
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4+
opensource-codeofconduct@amazon.com with any additional questions or comments.

README.md

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,22 @@ Below is the most basic AWS Lambda handler example that launches a Spring applic
1313

1414
```java
1515
public class StreamLambdaHandler implements RequestStreamHandler {
16-
private SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
17-
private Logger log = LoggerFactory.getLogger(StreamLambdaHandler.class);
16+
private static SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
17+
static {
18+
try {
19+
handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class);
20+
} catch (ContainerInitializationException e) {
21+
// if we fail here. We re-throw the exception to force another cold start
22+
e.printStackTrace();
23+
throw new RuntimeException("Could not initialize Spring framework", e);
24+
}
25+
}
1826

1927
@Override
2028
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
2129
throws IOException {
22-
if (handler == null) {
23-
try {
24-
handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class);
25-
} catch (ContainerInitializationException e) {
26-
log.error("Cannot initialize Spring container", e);
27-
outputStream.close();
28-
throw new RuntimeException(e);
29-
}
30-
}
31-
32-
AwsProxyRequest request = LambdaContainerHandler.getObjectMapper().readValue(inputStream, AwsProxyRequest.class);
33-
34-
AwsProxyResponse resp = handler.proxy(request, context);
30+
handler.proxyStream(inputStream, outputStream, context);
3531

36-
LambdaContainerHandler.getObjectMapper().writeValue(outputStream, resp);
3732
// just in case it wasn't closed by the mapper
3833
outputStream.close();
3934
}

archetypes/jersey/pom.xml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>com.amazonaws.serverless</groupId>
7+
<artifactId>aws-serverless-java-container</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
11+
<groupId>com.amazonaws.serverless.archetypes</groupId>
12+
<artifactId>aws-serverless-jersey-archetype</artifactId>
13+
<version>1.0-SNAPSHOT</version>
14+
<packaging>maven-archetype</packaging>
15+
16+
<scm>
17+
<url>https://github.com/awslabs/aws-serverless-java-container.git</url>
18+
</scm>
19+
20+
<licenses>
21+
<license>
22+
<name>The Apache Software License, Version 2.0</name>
23+
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
24+
<distribution>repo</distribution>
25+
</license>
26+
</licenses>
27+
28+
<build>
29+
<extensions>
30+
<extension>
31+
<groupId>org.apache.maven.archetype</groupId>
32+
<artifactId>archetype-packaging</artifactId>
33+
<version>3.0.1</version>
34+
</extension>
35+
</extensions>
36+
37+
<pluginManagement>
38+
<plugins>
39+
<plugin>
40+
<groupId>org.apache.maven.plugins</groupId>
41+
<artifactId>maven-archetype-plugin</artifactId>
42+
<version>3.0.1</version>
43+
</plugin>
44+
</plugins>
45+
</pluginManagement>
46+
</build>
47+
</project>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<archetype-descriptor name="aws-serverless-jersey-archetype"
2+
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd">
5+
<fileSets>
6+
<fileSet filtered="true" packaged="true">
7+
<directory>src/main/java</directory>
8+
<includes>
9+
<include>**/*.java</include>
10+
</includes>
11+
</fileSet>
12+
<fileSet filtered="true" packaged="true">
13+
<directory>src/test/java</directory>
14+
<includes>
15+
<include>**/*.java</include>
16+
</includes>
17+
</fileSet>
18+
<fileSet filtered="true">
19+
<directory></directory>
20+
<includes>
21+
<include>sam.yaml</include>
22+
<include>README.md</include>
23+
</includes>
24+
</fileSet>
25+
</fileSets>
26+
</archetype-descriptor>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#set($resourceName = $artifactId)
2+
#macro(replaceChar $originalName, $char)
3+
#if($originalName.contains($char))
4+
#set($tokens = $originalName.split($char))
5+
#set($newResourceName = "")
6+
#foreach($token in $tokens)
7+
#set($newResourceName = $newResourceName + $token.substring(0,1).toUpperCase() + $token.substring(1).toLowerCase())
8+
#end
9+
${newResourceName}
10+
#else
11+
#set($newResourceName = $originalName.substring(0,1).toUpperCase() + $originalName.substring(1))
12+
${newResourceName}
13+
#end
14+
#end
15+
#set($resourceName = "#replaceChar($resourceName, '-')")
16+
#set($resourceName = "#replaceChar($resourceName, '.')")
17+
#set($resourceName = $resourceName.replaceAll("\n", "").trim())
18+
# ${artifactId} serverless API
19+
The ${artifactId} project, created with [`aws-serverless-java-container`](https://github.com/awslabs/aws-serverless-java-container).
20+
21+
The starter project defines a simple `/ping` resource that can accept `GET` requests with its tests.
22+
23+
The project folder also includes a `sam.yaml` file. You can use this [SAM](https://github.com/awslabs/serverless-application-model) file to deploy the project to AWS Lambda and Amazon API Gateway or test in local with [SAM Local](https://github.com/awslabs/aws-sam-local).
24+
25+
## Building the project
26+
Using [Maven](https://maven.apache.org/), you can create an AWS Lambda-compatible jar file simply by running the maven package command from the projct folder.
27+
28+
```bash
29+
$ mvn archetype:generate -DartifactId=my-jersey-api -DarchetypeGroupId=com.amazonaws.serverless.archetypes -DarchetypeArtifactId=aws-serverless-jersey-archetype -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=com.sapessi.jersey -Dversion=0.1 -Dinteractive=false
30+
$ cd my-jersey-api
31+
$ mvn clean package
32+
33+
[INFO] ------------------------------------------------------------------------
34+
[INFO] BUILD SUCCESS
35+
[INFO] ------------------------------------------------------------------------
36+
[INFO] Total time: 6.546 s
37+
[INFO] Finished at: 2018-02-15T08:39:33-08:00
38+
[INFO] Final Memory: XXM/XXXM
39+
[INFO] ------------------------------------------------------------------------
40+
```
41+
42+
## Testing locally with SAM local
43+
You can use [AWS SAM Local](https://github.com/awslabs/aws-sam-local) to start your project.
44+
45+
First, install SAM local:
46+
47+
```bash
48+
$ npm install -g aws-sam-local
49+
```
50+
51+
Next, from the project root folder - where the `sam.yaml` file is located - start the API with the SAM Local CLI.
52+
53+
```bash
54+
$ sam local start-api --template sam.yaml
55+
56+
...
57+
Mounting ${groupId}.StreamLambdaHandler::handleRequest (java8) at http://127.0.0.1:3000/{proxy+} [OPTIONS GET HEAD POST PUT DELETE PATCH]
58+
...
59+
```
60+
61+
Using a new shell, you can send a test ping request to your API:
62+
63+
```bash
64+
$ curl -s http://127.0.0.1:3000/ping | python -m json.tool
65+
66+
{
67+
"pong": "Hello, World!"
68+
}
69+
```
70+
71+
## Deploying to AWS
72+
You can use the [AWS CLI](https://aws.amazon.com/cli/) to quickly deploy your application to AWS Lambda and Amazon API Gateway with your SAM template.
73+
74+
You will need an S3 bucket to store the artifacts for deployment. Once you have created the S3 bucket, run the following command from the project's root folder - where the `sam.yaml` file is located:
75+
76+
```
77+
$ aws cloudformation package --template-file sam.yaml --output-template-file output-sam.yaml --s3-bucket <YOUR S3 BUCKET NAME>
78+
Uploading to xxxxxxxxxxxxxxxxxxxxxxxxxx 6464692 / 6464692.0 (100.00%)
79+
Successfully packaged artifacts and wrote output template to file output-sam.yaml.
80+
Execute the following command to deploy the packaged template
81+
aws cloudformation deploy --template-file /your/path/output-sam.yaml --stack-name <YOUR STACK NAME>
82+
```
83+
84+
As the command output suggests, you can now use the cli to deploy the application. Choose a stack name and run the `aws cloudformation deploy` command from the output of the package command.
85+
86+
```
87+
$ aws cloudformation deploy --template-file output-sam.yaml --stack-name ServerlessJerseyApi --capabilities CAPABILITY_IAM
88+
```
89+
90+
Once the application is deployed, you can describe the stack to show the API endpoint that was created. The endpoint should be the `ServerlessJerseyApi` key of the `Outputs` property:
91+
92+
```
93+
$ aws cloudformation describe-stacks --stack-name ServerlessJerseyApi
94+
{
95+
"Stacks": [
96+
{
97+
"StackId": "arn:aws:cloudformation:us-west-2:xxxxxxxx:stack/ServerlessJerseyApi/xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx",
98+
"Description": "AWS Serverless Jersey API - ${groupId}::${artifactId}",
99+
"Tags": [],
100+
"Outputs": [
101+
{
102+
"Description": "URL for application",
103+
"ExportName": "${resourceName}Api",
104+
"OutputKey": "${resourceName}Api",
105+
"OutputValue": "https://xxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/ping"
106+
}
107+
],
108+
"CreationTime": "2016-12-13T22:59:31.552Z",
109+
"Capabilities": [
110+
"CAPABILITY_IAM"
111+
],
112+
"StackName": "ServerlessJerseyApi",
113+
"NotificationARNs": [],
114+
"StackStatus": "UPDATE_COMPLETE"
115+
}
116+
]
117+
}
118+
119+
```
120+
121+
Copy the `OutputValue` into a browser or use curl to test your first request:
122+
123+
```bash
124+
$ curl -s https://xxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/ping | python -m json.tool
125+
126+
{
127+
"pong": "Hello, World!"
128+
}
129+
```
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<groupId>${groupId}</groupId>
6+
<artifactId>${artifactId}</artifactId>
7+
<version>${version}</version>
8+
<packaging>jar</packaging>
9+
10+
<name>Serverless Jersey API</name>
11+
<url>https://github.com/awslabs/aws-serverless-java-container</url>
12+
13+
<properties>
14+
<maven.compiler.source>1.8</maven.compiler.source>
15+
<maven.compiler.target>1.8</maven.compiler.target>
16+
<jersey.version>2.26</jersey.version>
17+
</properties>
18+
19+
<dependencies>
20+
<dependency>
21+
<groupId>com.amazonaws.serverless</groupId>
22+
<artifactId>aws-serverless-java-container-jersey</artifactId>
23+
<version>1.0-SNAPSHOT</version>
24+
</dependency>
25+
26+
<dependency>
27+
<groupId>org.glassfish.jersey.media</groupId>
28+
<artifactId>jersey-media-json-jackson</artifactId>
29+
<version>${jersey.version}</version>
30+
</dependency>
31+
32+
<dependency>
33+
<groupId>org.glassfish.jersey.inject</groupId>
34+
<artifactId>jersey-hk2</artifactId>
35+
<version>${jersey.version}</version>
36+
<!-- excluding redundant javax.inject dependency -->
37+
<exclusions>
38+
<exclusion>
39+
<groupId>org.glassfish.hk2</groupId>
40+
<artifactId>hk2-api</artifactId>
41+
</exclusion>
42+
</exclusions>
43+
</dependency>
44+
45+
<dependency>
46+
<groupId>org.glassfish.hk2</groupId>
47+
<artifactId>hk2-api</artifactId>
48+
<version>2.5.0-b42</version>
49+
<!-- excluding redundant javax.inject dependency -->
50+
<exclusions>
51+
<exclusion>
52+
<groupId>javax.inject</groupId>
53+
<artifactId>javax.inject</artifactId>
54+
</exclusion>
55+
</exclusions>
56+
</dependency>
57+
58+
<dependency>
59+
<groupId>junit</groupId>
60+
<artifactId>junit</artifactId>
61+
<version>4.12</version>
62+
<scope>test</scope>
63+
</dependency>
64+
</dependencies>
65+
66+
<build>
67+
<plugins>
68+
<plugin>
69+
<groupId>org.apache.maven.plugins</groupId>
70+
<artifactId>maven-shade-plugin</artifactId>
71+
<version>2.3</version>
72+
<configuration>
73+
<createDependencyReducedPom>false</createDependencyReducedPom>
74+
</configuration>
75+
<executions>
76+
<execution>
77+
<phase>package</phase>
78+
<goals>
79+
<goal>shade</goal>
80+
</goals>
81+
</execution>
82+
</executions>
83+
</plugin>
84+
</plugins>
85+
</build>
86+
</project>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#set($resourceName = $artifactId)
2+
#macro(replaceChar $originalName, $char)
3+
#if($originalName.contains($char))
4+
#set($tokens = $originalName.split($char))
5+
#set($newResourceName = "")
6+
#foreach($token in $tokens)
7+
#set($newResourceName = $newResourceName + $token.substring(0,1).toUpperCase() + $token.substring(1).toLowerCase())
8+
#end
9+
${newResourceName}
10+
#else
11+
#set($newResourceName = $originalName.substring(0,1).toUpperCase() + $originalName.substring(1))
12+
${newResourceName}
13+
#end
14+
#end
15+
#set($resourceName = "#replaceChar($resourceName, '-')")
16+
#set($resourceName = "#replaceChar($resourceName, '.')")
17+
#set($resourceName = $resourceName.replaceAll("\n", "").trim())
18+
#macro(regionVar)
19+
AWS::Region
20+
#end
21+
#set($awsRegion = "#regionVar()")
22+
#set($awsRegion = $awsRegion.replaceAll("\n", "").trim())
23+
AWSTemplateFormatVersion: '2010-09-09'
24+
Transform: AWS::Serverless-2016-10-31
25+
Description: AWS Serverless Jersey API - ${groupId}::${artifactId}
26+
Resources:
27+
${resourceName}Function:
28+
Type: AWS::Serverless::Function
29+
Properties:
30+
Handler: ${groupId}.StreamLambdaHandler::handleRequest
31+
Runtime: java8
32+
CodeUri: target/${artifactId}-${version}.jar
33+
MemorySize: 512
34+
Policies: AWSLambdaBasicExecutionRole
35+
Timeout: 15
36+
Events:
37+
GetResource:
38+
Type: Api
39+
Properties:
40+
Path: /{proxy+}
41+
Method: any
42+
43+
Outputs:
44+
${resourceName}Api:
45+
Description: URL for application
46+
Value: !Sub 'https://${ServerlessRestApi}.execute-api.${${awsRegion}}.amazonaws.com/Prod/ping'
47+
Export:
48+
Name: ${resourceName}Api

0 commit comments

Comments
 (0)