diff --git a/deploy/docker-compose/docker-compose.yml b/deploy/docker-compose/docker-compose.yml index 664335653..f7df10bf9 100644 --- a/deploy/docker-compose/docker-compose.yml +++ b/deploy/docker-compose/docker-compose.yml @@ -14,7 +14,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -version: '2' +version: "2" services: ui: @@ -87,7 +87,7 @@ services: environment: - JAVA_OPTS=-XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/urandom - SERVER_TOMCAT_ACCESSLOG_ENABLED=true - - SPRING_PROFILES_ACTIVE=rabbitmq + - RETAIL_ORDERS_MESSAGING_PROVIDER=rabbitmq - SPRING_DATASOURCE_URL=jdbc:postgresql://orders-db:5432/orders - SPRING_DATASOURCE_USERNAME=orders_user - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD} @@ -108,7 +108,7 @@ services: - POSTGRES_DB=orders - POSTGRES_USER=orders_user healthcheck: - test: [ "CMD-SHELL", "pg_isready -d orders -U orders_user" ] + test: ["CMD-SHELL", "pg_isready -d orders -U orders_user"] interval: 10s timeout: 5s retries: 30 diff --git a/deploy/terraform/lib/apprunner/orders.tf b/deploy/terraform/lib/apprunner/orders.tf index c3501984b..ff2937cec 100644 --- a/deploy/terraform/lib/apprunner/orders.tf +++ b/deploy/terraform/lib/apprunner/orders.tf @@ -20,7 +20,7 @@ resource "aws_apprunner_service" "orders" { SPRING_RABBITMQ_PASSWORD = "${aws_secretsmanager_secret.mq.arn}:password::" } runtime_environment_variables = { - SPRING_PROFILES_ACTIVE = "rabbitmq" + RETAIL_ORDERS_MESSAGING_PROVIDER = "rabbitmq" } } image_identifier = module.container_images.result.orders.url diff --git a/deploy/terraform/lib/ecs/orders.tf b/deploy/terraform/lib/ecs/orders.tf index 4f3dbce4b..c4c143937 100644 --- a/deploy/terraform/lib/ecs/orders.tf +++ b/deploy/terraform/lib/ecs/orders.tf @@ -15,7 +15,7 @@ module "orders_service" { healthcheck_path = "/actuator/health" environment_variables = { - SPRING_PROFILES_ACTIVE = "rabbitmq" + RETAIL_ORDERS_MESSAGING_PROVIDER = "rabbitmq" } secrets = { diff --git a/src/orders/README.md b/src/orders/README.md index 11ba5027e..e152fc933 100644 --- a/src/orders/README.md +++ b/src/orders/README.md @@ -8,17 +8,13 @@ This service provides an API for storing orders. Data is stored in MySQL. ## Configuration -The following Spring profiles are available: - -- `default`: Uses an in-memory implementation for messaging which logs the payload and discards the message -- `sqs`: Publishes messages to an SQS topic configured with `MESSAGING_SQS_TOPIC` variable -- `rabbitmq`: Publishes messages to a RabbitMQ topic configured with the `SPRING_RABBITMQ_` variables - The following environment variables are available for configuring the service: | Name | Description | Default | | ----------------------------------- | --------------------------------------------------------------------------------------------------------- | ------- | | `PORT` | The port which the server will listen on | `8080` | +| `RETAIL_ORDERS_MESSAGING_PROVIDER` | The messaging provider to use to publish events (`in-memory`, `sqs`, `rabbitmq`) | `""` | +| `RETAIL_ORDERS_MESSAGING_SQS_TOPIC` | The name of the SQS topic to publish events to (SQS messaging provider) | `""` | | `SPRING_DATASOURCE_WRITER_URL` | The URL for the MySQL database writer endpoint. Uses the format `jdbc:mariadb://:/` | `""` | | `SPRING_DATASOURCE_WRITER_USERNAME` | The username for the MySQL database writer endpoint. | `""` | | `SPRING_DATASOURCE_WRITER_PASSWORD` | The password for the MySQL database writer endpoint. | `""` | @@ -26,7 +22,6 @@ The following environment variables are available for configuring the service: | `SPRING_DATASOURCE_READER_USERNAME` | The username for the MySQL database reader endpoint. | `""` | | `SPRING_DATASOURCE_READER_PASSWORD` | The password for the MySQL database reader endpoint. | `""` | | `SPRING_RABBITMQ_ADDRESSES` | The address of the RabbitMQ endpoints. Uses the format `amqp://:` | `""` | -| `MESSAGING_SQS_TOPIC` | The name of the SQS topic to publish events to. | `""` | ## Running diff --git a/src/orders/docker-compose.yml b/src/orders/docker-compose.yml index 0bb8d6af1..a2cdf83f1 100644 --- a/src/orders/docker-compose.yml +++ b/src/orders/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.4' +version: "3.4" services: orders: @@ -22,7 +22,7 @@ services: environment: - reschedule=on-node-failure - SERVER_TOMCAT_ACCESSLOG_ENABLED=true - - SPRING_PROFILES_ACTIVE=rabbitmq + - RETAIL_ORDERS_MESSAGING_PROVIDER=rabbitmq - SPRING_DATASOURCE_URL=jdbc:postgresql://orders-db:5432/orders - SPRING_DATASOURCE_USERNAME=orders_user - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD} @@ -31,10 +31,7 @@ services: - "8083:8080" healthcheck: test: - [ - "CMD-SHELL", - "curl -f http://localhost:8080/actuator/health || exit 1" - ] + ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"] interval: 10s timeout: 10s retries: 3 @@ -55,7 +52,7 @@ services: ports: - "5432:5432" healthcheck: - test: [ "CMD-SHELL", "pg_isready -d orders -U orders_user" ] + test: ["CMD-SHELL", "pg_isready -d orders -U orders_user"] interval: 10s timeout: 5s retries: 30 diff --git a/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/InMemoryMessagingConfig.java b/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/InMemoryMessagingConfig.java index 2378d80fd..113e272ba 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/InMemoryMessagingConfig.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/InMemoryMessagingConfig.java @@ -20,15 +20,21 @@ import com.amazon.sample.orders.messaging.MessagingProvider; import com.amazon.sample.orders.messaging.inmemory.InMemoryMessagingProvider; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; @Configuration -@Profile({"!rabbitmq", "!sqs"}) +@Slf4j +@ConditionalOnProperty(prefix = "retail.orders.messaging", name = "provider", havingValue = "in-memory") public class InMemoryMessagingConfig { @Bean public MessagingProvider messagingProvider() { + log.warn("Creating in-memory messaging provider"); + return new InMemoryMessagingProvider(); } } diff --git a/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/RabbitMQMessagingConfig.java b/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/RabbitMQMessagingConfig.java index 5cd768434..38c431af3 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/RabbitMQMessagingConfig.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/RabbitMQMessagingConfig.java @@ -20,6 +20,9 @@ import com.amazon.sample.orders.messaging.MessagingProvider; import com.amazon.sample.orders.messaging.rabbitmq.RabbitMQMessagingProvider; + +import lombok.extern.slf4j.Slf4j; + import org.springframework.amqp.core.*; import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer; import org.springframework.amqp.rabbit.connection.ConnectionFactory; @@ -27,16 +30,17 @@ import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.Profile; import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory; import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory; @Configuration -@Profile("rabbitmq") +@Slf4j +@ConditionalOnProperty(prefix = "retail.orders.messaging", name = "provider", havingValue = "rabbitmq") public class RabbitMQMessagingConfig extends RabbitAutoConfiguration implements RabbitListenerConfigurer { public static final String EXCHANGE_NAME = "orders-exchange"; @@ -44,6 +48,8 @@ public class RabbitMQMessagingConfig extends RabbitAutoConfiguration implements @Bean public MessagingProvider messagingProvider(RabbitTemplate template) { + log.info("Creating RabbitMQ messaging provider"); + return new RabbitMQMessagingProvider(template); } diff --git a/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/SqsMessagingConfig.java b/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/SqsMessagingConfig.java index 0d2c88c31..9c73432f9 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/SqsMessagingConfig.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/config/messaging/SqsMessagingConfig.java @@ -24,22 +24,24 @@ import io.awspring.cloud.autoconfigure.sqs.SqsAutoConfiguration; import io.awspring.cloud.autoconfigure.sqs.SqsProperties; import io.awspring.cloud.sqs.operations.SqsTemplate; +import lombok.extern.slf4j.Slf4j; import software.amazon.awssdk.services.sqs.SqsAsyncClient; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; @Configuration -@Profile("sqs") +@ConditionalOnProperty(prefix = "retail.orders.messaging", name = "provider", havingValue = "sqs") +@Slf4j public class SqsMessagingConfig extends SqsAutoConfiguration { public SqsMessagingConfig(SqsProperties sqsProperties) { super(sqsProperties); } - @Value("${messaging.sqs.topic}") + @Value("${retail.orders.messaging.sqs.topic}") private String messageQueueTopic; @Bean @@ -49,6 +51,8 @@ public SqsAsyncClient sqsQueue() { @Bean public SqsMessagingProvider messagingProvider(SqsAsyncClient amazonSqs, ObjectMapper mapper) { + log.info("Creating SQS messaging provider"); + return new SqsMessagingProvider(messageQueueTopic, SqsTemplate.newSyncTemplate(amazonSqs), mapper); } } \ No newline at end of file diff --git a/src/orders/src/main/java/com/amazon/sample/orders/messaging/inmemory/InMemoryMessagingProvider.java b/src/orders/src/main/java/com/amazon/sample/orders/messaging/inmemory/InMemoryMessagingProvider.java index b880eac61..4bc9f45a9 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/messaging/inmemory/InMemoryMessagingProvider.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/messaging/inmemory/InMemoryMessagingProvider.java @@ -24,10 +24,6 @@ @Slf4j public class InMemoryMessagingProvider implements MessagingProvider { - public InMemoryMessagingProvider() { - log.warn("Using in-memory messaging provider"); - } - @Override public void publishEvent(Object event) { log.info("Publishing event {}", event); diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java b/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java index f52d3c354..30e63668e 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java @@ -45,6 +45,8 @@ public class OrderController { @PostMapping @Operation(summary = "Create an order", operationId = "createOrder") public ExistingOrder order(@RequestBody Order orderRequest) { + log.debug("Creating order {}", orderRequest); + return this.orderMapper.toExistingOrder(this.service.create(this.orderMapper.toOrderEntity(orderRequest))); } diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java index 9a13925f2..50e4d9c81 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java @@ -21,7 +21,6 @@ import lombok.Data; import java.util.List; -import java.util.Set; @Data public class Order { diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java index e796f6bb3..f3ac57a0a 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java @@ -19,7 +19,6 @@ package com.amazon.sample.orders.web.payload; import com.amazon.sample.orders.entities.OrderEntity; -import com.amazon.sample.orders.entities.OrderItemEntity; import org.mapstruct.Mapper; @Mapper(componentModel = "spring", uses = OrderItemMapper.class) diff --git a/src/orders/src/main/resources/application.yml b/src/orders/src/main/resources/application.yml index a001c81ef..068141c42 100644 --- a/src/orders/src/main/resources/application.yml +++ b/src/orders/src/main/resources/application.yml @@ -12,3 +12,8 @@ server: port: ${port:8080} spring.flyway.baseline-on-migrate: true + +retail: + orders: + messaging: + provider: "in-memory" diff --git a/src/orders/src/test/java/com/amazon/sample/orders/OrdersApplicationTests.java b/src/orders/src/test/java/com/amazon/sample/orders/OrdersApplicationTests.java index 2f92e198f..178c62ae8 100644 --- a/src/orders/src/test/java/com/amazon/sample/orders/OrdersApplicationTests.java +++ b/src/orders/src/test/java/com/amazon/sample/orders/OrdersApplicationTests.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; @SpringBootTest class OrdersApplicationTests { diff --git a/src/orders/src/test/java/com/amazon/sample/orders/services/OrderServicePostgresTests.java b/src/orders/src/test/java/com/amazon/sample/orders/services/OrderServicePostgresTests.java index 33593a18f..246e69317 100644 --- a/src/orders/src/test/java/com/amazon/sample/orders/services/OrderServicePostgresTests.java +++ b/src/orders/src/test/java/com/amazon/sample/orders/services/OrderServicePostgresTests.java @@ -30,7 +30,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer;