Fork me on GitHub

AWS SAM Tutorial

This tutorial demonstrates running within AWS Serverless.

Tutorial Source

AWS SAM

AWS SAM is supported by OfficeFloor through the following plugin:

		<dependency>
			<groupId>net.officefloor.server</groupId>
			<artifactId>officeserver_sam</artifactId>
		</dependency>

The only additional configuration is AWS SAM requiring the application be shaded as follows:

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-shade-plugin</artifactId>
				<configuration>
					<transformers>
						<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
					</transformers>
				</configuration>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>shade</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

Running Locally

Running the AWS SAM application locally typically requires setting up a docker network, running DynamoDB and then starting SAM locally. To ease running and testing the application, the following plugin is available:

					<plugin>
						<groupId>net.officefloor.maven</groupId>
						<artifactId>officefloor-sam-maven-plugin</artifactId>
						<configuration>
							<samPort>8381</samPort>
							<dynamodbPort>8382</dynamodbPort>
						</configuration>
						<executions>
							<execution>
								<id>start</id>
								<phase>pre-integration-test</phase>
								<goals>
									<goal>start</goal>
								</goals>
							</execution>
							<execution>
								<id>stop</id>
								<phase>post-integration-test</phase>
								<goals>
									<goal>stop</goal>
								</goals>
							</execution>
						</executions>
					</plugin>
					
					<!-- Run integration tests against locally started AWS SAM -->
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-failsafe-plugin</artifactId>
						<executions>
							<execution>
								<goals>
									<goal>integration-test</goal>
									<goal>verify</goal>
								</goals>
							</execution>
						</executions>
					</plugin>

Note that the SAM template.yaml file is created by the plugin if it does not exist. Hence, once the file is generated, it is possible to make manual alterations and check it into source control.

The application may then be manually started with the following:


    mvn officefloor-sam:run

Deploying to AWS

The AWS provided SAM CLI may be used for deploying the application to AWS. In this case:


    sam deploy --guided

Testing

The functionality can be tested just like any other Web on OfficeFloor (WoOF) application:

	public static final @Order(1) @RegisterExtension DynamoDbExtension dynamo = new DynamoDbExtension();

	public static final @Order(2) @RegisterExtension MockWoofServerExtension server = new MockWoofServerExtension();

	@Test
	public void createPost() {

		// Create the entity
		MockWoofResponse response = server
				.send(MockWoofServer.mockJsonRequest(HttpMethod.POST, "/posts", new Post("TEST")));
		PostEntity entity = response.getJson(200, PostEntity.class);

		// Ensure in store
		PostEntity stored = dynamo.getDynamoDbMapper().load(PostEntity.class, entity.getId());
		assertNotNull(stored, "Should find entity in DynamoDB " + entity.getId());
		assertEquals("TEST", stored.getMessage(), "Incorrent entity");
	}

To test within the SAM local server, use integration testing. The officefloor-sam-maven-plugin above sets up the application running within a SAM local server. It also sets up a local DynamoDB. This enables the following integration testing:

	public static final @RegisterExtension HttpClientExtension serverClient = new HttpClientExtension(false, 8381)
			.timeout(30_000);

	public static final @RegisterExtension DynamoDbConnectExtension dynamoClient = new DynamoDbConnectExtension(
			new Configuration().port(8382));

	private static final ObjectMapper mapper = new ObjectMapper();

	@Test
	public void createPost() throws IOException {

		// Create the entity
		HttpPost request = new HttpPost(serverClient.url("/posts"));
		request.setHeader("Accept", "application/json"); // Provide Accept header due to AWS SAM requiring it
		request.setHeader("Content-Type", "application/json");
		request.setEntity(new StringEntity(mapper.writeValueAsString(new Post("TEST"))));
		HttpResponse response = serverClient.execute(request);
		String responseBody = EntityUtils.toString(response.getEntity());
		assertEquals(200, response.getStatusLine().getStatusCode(), "Should be successful: " + responseBody);
		PostEntity entity = mapper.readValue(responseBody, PostEntity.class);

		// Ensure in store
		PostEntity stored = dynamoClient.getDynamoDbMapper().load(PostEntity.class, entity.getId());
		assertNotNull(stored, "Should find entity in DynamoDB " + entity.getId());
		assertEquals("TEST", stored.getMessage(), "Incorrent entity");
	}

Note that a different DynamoDB extension is used for each type of testing:

Next

The next tutorial covers the CosmosDB client.