--- title: Create the Spring Boot project linkTitle: Create the project description: Set up a Spring Boot project with Spring Cloud AWS, S3, and SQS. weight: 10 --- ## Set up the project Create a Spring Boot project from [Spring Initializr](https://start.spring.io) by selecting the **Testcontainers** starter. Spring Cloud AWS starters are not available on Spring Initializr, so you need to add them manually. Alternatively, clone the [guide repository](https://github.com/testcontainers/tc-guide-testing-aws-service-integrations-using-localstack). Add the Spring Cloud AWS BOM to your dependency management and add the S3, SQS starters as dependencies. Testcontainers provides a [LocalStack module](https://testcontainers.com/modules/localstack/) for testing AWS service integrations. You also need [Awaitility](http://www.awaitility.org/) for testing asynchronous SQS processing. The key dependencies in `pom.xml` are: ```xml 17 2.0.4 3.0.3 org.springframework.boot spring-boot-starter-web io.awspring.cloud spring-cloud-aws-starter-s3 io.awspring.cloud spring-cloud-aws-starter-sqs org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-testcontainers test org.testcontainers testcontainers-junit-jupiter test org.testcontainers testcontainers-localstack test org.awaitility awaitility test io.awspring.cloud spring-cloud-aws-dependencies ${awspring.version} pom import ``` ## Create the configuration properties To make the SQS queue and S3 bucket names configurable, create an `ApplicationProperties` record: ```java package com.testcontainers.demo; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "app") public record ApplicationProperties(String queue, String bucket) {} ``` Then add `@ConfigurationPropertiesScan` to the main application class so that Spring automatically scans for `@ConfigurationProperties`-annotated classes and registers them as beans: ```java package com.testcontainers.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; @SpringBootApplication @ConfigurationPropertiesScan public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` ## Implement StorageService for S3 Spring Cloud AWS provides higher-level abstractions like `S3Template` with convenience methods for uploading and downloading files. Create a `StorageService` class: ```java package com.testcontainers.demo; import io.awspring.cloud.s3.S3Template; import java.io.IOException; import java.io.InputStream; import org.springframework.stereotype.Service; @Service public class StorageService { private final S3Template s3Template; public StorageService(S3Template s3Template) { this.s3Template = s3Template; } public void upload(String bucketName, String key, InputStream stream) { this.s3Template.upload(bucketName, key, stream); } public InputStream download(String bucketName, String key) throws IOException { return this.s3Template.download(bucketName, key).getInputStream(); } public String downloadAsString(String bucketName, String key) throws IOException { try (InputStream is = this.download(bucketName, key)) { return new String(is.readAllBytes()); } } } ``` ## Create the SQS message model Create a `Message` record that represents the payload you send to the SQS queue: ```java package com.testcontainers.demo; import java.util.UUID; public record Message(UUID uuid, String content) {} ``` ## Implement the message sender Create `MessageSender`, which uses `SqsTemplate` to publish messages: ```java package com.testcontainers.demo; import io.awspring.cloud.sqs.operations.SqsTemplate; import org.springframework.stereotype.Service; @Service public class MessageSender { private final SqsTemplate sqsTemplate; public MessageSender(SqsTemplate sqsTemplate) { this.sqsTemplate = sqsTemplate; } public void publish(String queueName, Message message) { sqsTemplate.send(to -> to.queue(queueName).payload(message)); } } ``` ## Implement the message listener Create `MessageListener` with a handler method annotated with `@SqsListener`. When a message arrives, the listener uploads the content to an S3 bucket using the message UUID as the key: ```java package com.testcontainers.demo; import io.awspring.cloud.sqs.annotation.SqsListener; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import org.springframework.stereotype.Service; @Service public class MessageListener { private final StorageService storageService; private final ApplicationProperties properties; public MessageListener( StorageService storageService, ApplicationProperties properties ) { this.storageService = storageService; this.properties = properties; } @SqsListener(queueNames = { "${app.queue}" }) public void handle(Message message) { String bucketName = this.properties.bucket(); String key = message.uuid().toString(); ByteArrayInputStream is = new ByteArrayInputStream( message.content().getBytes(StandardCharsets.UTF_8) ); this.storageService.upload(bucketName, key, is); } } ``` The `${app.queue}` expression reads the queue name from application configuration instead of hard-coding it.