diff --git a/.sdkmanrc b/.sdkmanrc index 727932c..7512a8b 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -1,3 +1,3 @@ -java=17.0.4-tem -gradle=8.1.1 +java=17.0.8-tem +gradle=8.5 maven=3.8.6 \ No newline at end of file diff --git a/build.gradle b/build.gradle index c678bd3..a3abd21 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,8 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.1.2' - id 'io.spring.dependency-management' version '1.1.2' - id 'com.diffplug.spotless' version "6.18.0" + id 'org.springframework.boot' version '3.2.0' + id 'io.spring.dependency-management' version '1.1.4' + id 'com.diffplug.spotless' version "6.23.0" } group = 'com.testcontainers' @@ -20,8 +20,8 @@ repositories { } ext { - set('testcontainers.version', "1.18.3") - set('awspringVersion', "3.0.1") + set('testcontainers.version', "1.19.3") + set('awspringVersion', "3.0.3") } dependencies { @@ -56,7 +56,13 @@ spotless { java { importOrder() removeUnusedImports() - palantirJavaFormat("2.30.0") + prettier(['prettier': '3.0.3', 'prettier-plugin-java': '2.3.0']) + .config([ + 'parser': 'java', + 'tabWidth': 2, + 'printWidth': 80, + 'plugins': ['prettier-plugin-java'] + ]) formatAnnotations() } } diff --git a/guide/testing-aws-service-integrations-using-localstack/index.adoc b/guide/testing-aws-service-integrations-using-localstack/index.adoc index bbfaf49..50dd8ce 100644 --- a/guide/testing-aws-service-integrations-using-localstack/index.adoc +++ b/guide/testing-aws-service-integrations-using-localstack/index.adoc @@ -52,7 +52,7 @@ If you are using *Gradle* as your build tool, you should have the dependencies c [source,groovy,indent=0] ---- -include::{codebase}/build.gradle[lines="22..42"] +include::{codebase}/build.gradle[lines="22..44"] ---- For the complete code, please refer to the GitHub repository @@ -138,7 +138,7 @@ configure the Spring Cloud AWS properties as follows: [source,java] ---- -include::{codebase}/src/test/java/com/testcontainers/demo/MessageListenerTest.java[lines="22..45,76"] +include::{codebase}/src/test/java/com/testcontainers/demo/MessageListenerTest.java[lines="22..58,98"] ---- We have used Testcontainers JUnit 5 Extension annotations *@Testcontainers* and *@Container* @@ -152,7 +152,7 @@ method to create the necessary resources (S3 buckets or SQS queues etc) by using [source,java,indent=0] ---- -include::{codebase}/src/test/java/com/testcontainers/demo/MessageListenerTest.java[lines="47..51"] +include::{codebase}/src/test/java/com/testcontainers/demo/MessageListenerTest.java[lines="60..70"] ---- We have used *localStack.execInContainer()* API to run commands inside the container and used *awslocal* CLI tool, diff --git a/pom.xml b/pom.xml index d619b24..b3072e5 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.2 + 3.2.0 com.testcontainers @@ -17,8 +17,8 @@ UTF-8 17 - 1.18.3 - 3.0.1 + 1.19.3 + 3.0.3 @@ -87,14 +87,23 @@ com.diffplug.spotless spotless-maven-plugin - 2.36.0 + 2.41.0 - - 2.30.0 - + + + 3.0.3 + 2.3.0 + + + java + 2 + 80 + prettier-plugin-java + + diff --git a/src/main/java/com/testcontainers/demo/Application.java b/src/main/java/com/testcontainers/demo/Application.java index c7a010e..4de1e16 100644 --- a/src/main/java/com/testcontainers/demo/Application.java +++ b/src/main/java/com/testcontainers/demo/Application.java @@ -8,7 +8,7 @@ @ConfigurationPropertiesScan public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/src/main/java/com/testcontainers/demo/MessageController.java b/src/main/java/com/testcontainers/demo/MessageController.java index 8f5d436..574a0f1 100644 --- a/src/main/java/com/testcontainers/demo/MessageController.java +++ b/src/main/java/com/testcontainers/demo/MessageController.java @@ -10,27 +10,30 @@ @RestController public class MessageController { - private final MessageSender messageSender; - private final StorageService storageService; - private final ApplicationProperties properties; - MessageController(MessageSender messageSender, StorageService storageService, ApplicationProperties properties) { - this.messageSender = messageSender; - this.storageService = storageService; - this.properties = properties; - } + private final MessageSender messageSender; + private final StorageService storageService; + private final ApplicationProperties properties; - @PostMapping("/api/messages") - public Map create(@RequestBody Message message) { - messageSender.publish(properties.queue(), message); - return Map.of("uuid", message.uuid().toString()); - } + MessageController( + MessageSender messageSender, + StorageService storageService, + ApplicationProperties properties + ) { + this.messageSender = messageSender; + this.storageService = storageService; + this.properties = properties; + } - @GetMapping("/api/messages/{uuid}") - public Map get(@PathVariable String uuid) throws IOException { - String content = storageService.downloadAsString(properties.bucket(), uuid); - return Map.of( - "uuid", uuid, - "content", content); - } + @PostMapping("/api/messages") + public Map create(@RequestBody Message message) { + messageSender.publish(properties.queue(), message); + return Map.of("uuid", message.uuid().toString()); + } + + @GetMapping("/api/messages/{uuid}") + public Map get(@PathVariable String uuid) throws IOException { + String content = storageService.downloadAsString(properties.bucket(), uuid); + return Map.of("uuid", uuid, "content", content); + } } diff --git a/src/main/java/com/testcontainers/demo/MessageListener.java b/src/main/java/com/testcontainers/demo/MessageListener.java index 9e2def7..be6f95a 100644 --- a/src/main/java/com/testcontainers/demo/MessageListener.java +++ b/src/main/java/com/testcontainers/demo/MessageListener.java @@ -7,19 +7,25 @@ @Service public class MessageListener { - private final StorageService storageService; - private final ApplicationProperties properties; - public MessageListener(StorageService storageService, ApplicationProperties properties) { - this.storageService = storageService; - this.properties = properties; - } + private final StorageService storageService; + private final ApplicationProperties 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); - } + 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); + } } diff --git a/src/main/java/com/testcontainers/demo/MessageSender.java b/src/main/java/com/testcontainers/demo/MessageSender.java index cfd1a0c..9e16c8a 100644 --- a/src/main/java/com/testcontainers/demo/MessageSender.java +++ b/src/main/java/com/testcontainers/demo/MessageSender.java @@ -5,13 +5,14 @@ @Service public class MessageSender { - private final SqsTemplate sqsTemplate; - public MessageSender(SqsTemplate sqsTemplate) { - this.sqsTemplate = sqsTemplate; - } + private final SqsTemplate sqsTemplate; - public void publish(String queueName, Message message) { - sqsTemplate.send(to -> to.queue(queueName).payload(message)); - } + public MessageSender(SqsTemplate sqsTemplate) { + this.sqsTemplate = sqsTemplate; + } + + public void publish(String queueName, Message message) { + sqsTemplate.send(to -> to.queue(queueName).payload(message)); + } } diff --git a/src/main/java/com/testcontainers/demo/StorageService.java b/src/main/java/com/testcontainers/demo/StorageService.java index a0270f8..27fccea 100644 --- a/src/main/java/com/testcontainers/demo/StorageService.java +++ b/src/main/java/com/testcontainers/demo/StorageService.java @@ -7,23 +7,26 @@ @Service public class StorageService { - private final S3Template s3Template; - public StorageService(S3Template s3Template) { - this.s3Template = s3Template; - } + private final S3Template s3Template; - public void upload(String bucketName, String key, InputStream stream) { - this.s3Template.upload(bucketName, key, stream); - } + public StorageService(S3Template s3Template) { + this.s3Template = s3Template; + } - public InputStream download(String bucketName, String key) throws IOException { - return this.s3Template.download(bucketName, key).getInputStream(); - } + 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()); - } + public String downloadAsString(String bucketName, String key) + throws IOException { + try (InputStream is = this.download(bucketName, key)) { + return new String(is.readAllBytes()); } + } } diff --git a/src/test/java/com/testcontainers/demo/MessageListenerTest.java b/src/test/java/com/testcontainers/demo/MessageListenerTest.java index 901f77d..f46aa2d 100644 --- a/src/test/java/com/testcontainers/demo/MessageListenerTest.java +++ b/src/test/java/com/testcontainers/demo/MessageListenerTest.java @@ -23,54 +23,76 @@ @Testcontainers class MessageListenerTest { - @Container - static LocalStackContainer localStack = new LocalStackContainer(DockerImageName.parse("localstack/localstack:2.0")); + @Container + static LocalStackContainer localStack = new LocalStackContainer( + DockerImageName.parse("localstack/localstack:3.0") + ); - static final String BUCKET_NAME = UUID.randomUUID().toString(); - static final String QUEUE_NAME = UUID.randomUUID().toString(); + static final String BUCKET_NAME = UUID.randomUUID().toString(); + static final String QUEUE_NAME = UUID.randomUUID().toString(); - @DynamicPropertySource - static void overrideProperties(DynamicPropertyRegistry registry) { - registry.add("app.bucket", () -> BUCKET_NAME); - registry.add("app.queue", () -> QUEUE_NAME); - registry.add("spring.cloud.aws.region.static", () -> localStack.getRegion()); - registry.add("spring.cloud.aws.credentials.access-key", () -> localStack.getAccessKey()); - registry.add("spring.cloud.aws.credentials.secret-key", () -> localStack.getSecretKey()); - registry.add( - "spring.cloud.aws.s3.endpoint", - () -> localStack.getEndpointOverride(S3).toString()); - registry.add( - "spring.cloud.aws.sqs.endpoint", - () -> localStack.getEndpointOverride(SQS).toString()); - } + @DynamicPropertySource + static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("app.bucket", () -> BUCKET_NAME); + registry.add("app.queue", () -> QUEUE_NAME); + registry.add( + "spring.cloud.aws.region.static", + () -> localStack.getRegion() + ); + registry.add( + "spring.cloud.aws.credentials.access-key", + () -> localStack.getAccessKey() + ); + registry.add( + "spring.cloud.aws.credentials.secret-key", + () -> localStack.getSecretKey() + ); + registry.add( + "spring.cloud.aws.s3.endpoint", + () -> localStack.getEndpointOverride(S3).toString() + ); + registry.add( + "spring.cloud.aws.sqs.endpoint", + () -> localStack.getEndpointOverride(SQS).toString() + ); + } - @BeforeAll - static void beforeAll() throws IOException, InterruptedException { - localStack.execInContainer("awslocal", "s3", "mb", "s3://" + BUCKET_NAME); - localStack.execInContainer("awslocal", "sqs", "create-queue", "--queue-name", QUEUE_NAME); - } + @BeforeAll + static void beforeAll() throws IOException, InterruptedException { + localStack.execInContainer("awslocal", "s3", "mb", "s3://" + BUCKET_NAME); + localStack.execInContainer( + "awslocal", + "sqs", + "create-queue", + "--queue-name", + QUEUE_NAME + ); + } - @Autowired - StorageService storageService; + @Autowired + StorageService storageService; - @Autowired - MessageSender publisher; + @Autowired + MessageSender publisher; - @Autowired - ApplicationProperties properties; + @Autowired + ApplicationProperties properties; - @Test - void shouldHandleMessageSuccessfully() { - Message message = new Message(UUID.randomUUID(), "Hello World"); - publisher.publish(properties.queue(), message); + @Test + void shouldHandleMessageSuccessfully() { + Message message = new Message(UUID.randomUUID(), "Hello World"); + publisher.publish(properties.queue(), message); - await().pollInterval(Duration.ofSeconds(2)) - .atMost(Duration.ofSeconds(10)) - .ignoreExceptions() - .untilAsserted(() -> { - String msg = storageService.downloadAsString( - properties.bucket(), message.uuid().toString()); - assertThat(msg).isEqualTo("Hello World"); - }); - } + await() + .pollInterval(Duration.ofSeconds(2)) + .atMost(Duration.ofSeconds(10)) + .ignoreExceptions() + .untilAsserted(() -> { + String msg = storageService.downloadAsString( + properties.bucket(), + message.uuid().toString() + ); + assertThat(msg).isEqualTo("Hello World"); + }); + } } diff --git a/src/test/java/com/testcontainers/demo/TestApplication.java b/src/test/java/com/testcontainers/demo/TestApplication.java index 6c67ae4..460d84c 100644 --- a/src/test/java/com/testcontainers/demo/TestApplication.java +++ b/src/test/java/com/testcontainers/demo/TestApplication.java @@ -7,31 +7,50 @@ public class TestApplication { - public static void main(String[] args) { - setup(); - SpringApplication.from(Application::main).run(args); - } + public static void main(String[] args) { + setup(); + SpringApplication.from(Application::main).run(args); + } - static void setup() { - try { - var container = new LocalStackContainer(DockerImageName.parse("localstack/localstack:2.0")); - container.start(); + static void setup() { + try { + var container = new LocalStackContainer( + DockerImageName.parse("localstack/localstack:3.0") + ); + container.start(); - String BUCKET_NAME = UUID.randomUUID().toString(); - String QUEUE_NAME = UUID.randomUUID().toString(); + String BUCKET_NAME = UUID.randomUUID().toString(); + String QUEUE_NAME = UUID.randomUUID().toString(); - container.execInContainer("awslocal", "s3", "mb", "s3://" + BUCKET_NAME); - container.execInContainer("awslocal", "sqs", "create-queue", "--queue-name", QUEUE_NAME); + container.execInContainer("awslocal", "s3", "mb", "s3://" + BUCKET_NAME); + container.execInContainer( + "awslocal", + "sqs", + "create-queue", + "--queue-name", + QUEUE_NAME + ); - System.setProperty("app.bucket", BUCKET_NAME); - System.setProperty("app.queue", QUEUE_NAME); - System.setProperty("spring.cloud.aws.region.static", container.getRegion()); - System.setProperty("spring.cloud.aws.credentials.access-key", container.getAccessKey()); - System.setProperty("spring.cloud.aws.credentials.secret-key", container.getSecretKey()); - System.setProperty( - "spring.cloud.aws.endpoint", container.getEndpoint().toString()); - } catch (Exception e) { - throw new RuntimeException(e); - } + System.setProperty("app.bucket", BUCKET_NAME); + System.setProperty("app.queue", QUEUE_NAME); + System.setProperty( + "spring.cloud.aws.region.static", + container.getRegion() + ); + System.setProperty( + "spring.cloud.aws.credentials.access-key", + container.getAccessKey() + ); + System.setProperty( + "spring.cloud.aws.credentials.secret-key", + container.getSecretKey() + ); + System.setProperty( + "spring.cloud.aws.endpoint", + container.getEndpoint().toString() + ); + } catch (Exception e) { + throw new RuntimeException(e); } + } }