diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9865181 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: maven + directory: / + schedule: + interval: daily + + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily \ No newline at end of file diff --git a/assets/order-service-ecosystem.png b/assets/order-service-ecosystem.png index 860e890..3384329 100644 Binary files a/assets/order-service-ecosystem.png and b/assets/order-service-ecosystem.png differ diff --git a/pom.xml b/pom.xml index 0ed460b..1627dd3 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ io.github.microcks microcks-testcontainers - 0.2.5 + 0.2.6 test diff --git a/src/test/java/org/acme/order/ContainersConfiguration.java b/src/test/java/org/acme/order/ContainersConfiguration.java index efd1a51..2b0442b 100644 --- a/src/test/java/org/acme/order/ContainersConfiguration.java +++ b/src/test/java/org/acme/order/ContainersConfiguration.java @@ -31,12 +31,11 @@ KafkaContainer kafkaContainer() { @Bean MicrocksContainersEnsemble microcksEnsemble(DynamicPropertyRegistry registry) { - /* - DockerImageName nativeImage = DockerImageName.parse("quay.io/microcks/microcks-uber:nightly-native") - .asCompatibleSubstituteFor("quay.io/microcks/microcks-uber:1.8.1"); - - MicrocksContainersEnsemble ensemble = new MicrocksContainersEnsemble(network, nativeImage) - */ + // Uncomment these lines (36-38) if you want to use the native image of Microcks + // and comment the next MicrocksContainersEnsemble declaration line (40). +// DockerImageName nativeImage = DockerImageName.parse("quay.io/microcks/microcks-uber:1.9.0-native") +// .asCompatibleSubstituteFor("quay.io/microcks/microcks-uber:1.9.0"); +// MicrocksContainersEnsemble ensemble = new MicrocksContainersEnsemble(network, nativeImage) MicrocksContainersEnsemble ensemble = new MicrocksContainersEnsemble(network, "quay.io/microcks/microcks-uber:1.9.0") .withPostman() // We need this to do contract-testing with Postman collection diff --git a/step-1-getting-started.md b/step-1-getting-started.md index eaceba7..6b87e10 100644 --- a/step-1-getting-started.md +++ b/step-1-getting-started.md @@ -13,31 +13,30 @@ We would recommend using [SDKMAN](https://sdkman.io/) to install Java on your ma ### Install Docker -You need to have a Docker environment to use Testcontainers. +You need to have a [Docker](https://docs.docker.com/get-docker/) or [Podman](https://podman.io/) environment to use Testcontainers. ```shell $ docker version Client: - Cloud integration: v1.0.35 - Version: 24.0.2 - API version: 1.43 - Go version: go1.20.4 - Git commit: cb74dfc - Built: Thu May 25 21:51:16 2023 + Cloud integration: v1.0.35+desktop.10 + Version: 25.0.3 + API version: 1.44 + Go version: go1.21.6 + Git commit: 4debf41 + Built: Tue Feb 6 21:13:26 2024 OS/Arch: darwin/arm64 Context: desktop-linux -Server: Docker Desktop 4.21.1 (114176) +Server: Docker Desktop 4.27.2 (137060) Engine: - Version: 24.0.2 - API version: 1.43 (minimum version 1.12) - Go version: go1.20.4 - Git commit: 659604f - Built: Thu May 25 21:50:59 2023 + Version: 25.0.3 + API version: 1.44 (minimum version 1.24) + Go version: go1.21.6 + Git commit: f417435e5f6216828dec57958c490c4f8bae4f98 + Built: Wed Feb 7 00:39:16 2024 OS/Arch: linux/arm64 Experimental: false - ... ``` ## Download the project @@ -53,7 +52,7 @@ git clone https://github.com/microcks/microcks-testcontainers-java-spring-demo.g With Maven: ```shell -./mvnw compile +./mvnw clean package -DskipTests ``` ### diff --git a/step-2-exploring-the-app.md b/step-2-exploring-the-app.md index 301c9a2..2332434 100644 --- a/step-2-exploring-the-app.md +++ b/step-2-exploring-the-app.md @@ -7,11 +7,11 @@ but also relies on an existing API we have [introduced in a previous post](https ![Order Service ecosystem](./assets/order-service-ecosystem.png) The `Order Service` application has been designed around 5 main components that are directly mapped on Spring Boot components and classes: -* The `OrderController` (in package `org.acme.order.api`) is responsible for exposing an `Order API` to the outer world. -* The `OrderService` (in package `org.acme.order.service`) is responsible for implementing the business logic around the creation of orders. -* The `PastryAPIClient` (in package `org.acme.order.client`) is responsible for calling the `Pastry API` in *Product Domain* and get details or list of pastries. -* The `OrderEventPublisher` (in package `org.acme.order.service`) is responsible for publishing a message on a `Kafka` topic when a new `Order` is created. -* The `OrderEventListener` (in package `org.acme.order.service`) is responsible for consuming message on a `Kafka` topic when an `Order` has been reviewed. +* The [`OrderController`](src/main/java/org/acme/order/api/OrderController.java) (in package `org.acme.order.api`) is responsible for exposing an `Order API` to the outer world. +* The [`OrderService`](src/main/java/org/acme/order/service/OrderService.java) is responsible for implementing the business logic around the creation of orders. +* The [`PastryAPIClient`](src/main/java/org/acme/order/client/PastryAPIClient.java) is responsible for calling the `Pastry API` in *Product Domain* and get details or list of pastries. +* The [`OrderEventPublisher`](src/main/java/org/acme/order/service/OrderEventPublisher.java) is responsible for publishing a message on a `Kafka` topic when a new `Order` is created. +* The [`OrderEventListener`](src/main/java/org/acme/order/service/OrderEventListener.java) is responsible for consuming message on a `Kafka` topic when an `Order` has been reviewed. ![Order Service architecture](./assets/order-service-architecture.png) @@ -21,23 +21,24 @@ dependencies (like a `Payment Service`, a `Customer Service`, a `Shipping Servic However, this situation is complex enough to highlight the two problems we're addressing: 1) How to **efficiently set up a development environment** that depends on third-party API like the Pastry API? - You certainly want to avoid cloning this component repository, figuring out how to launch it and configure it accordingly. As a developer, developing your own mock of this service makes you also lose time and risk drifting from initial intent, + - You certainly want to avoid cloning this component repository and trying to figure out how to launch and configure it accordingly. + - As a developer, developing your own mock of this service makes you also lose time and risk drifting from initial intent, 2) How to **efficiently validate the conformance** of the `Order API` and `Order Events` against business expectations and API contracts? - Besides the core business logic, you might want to validate the network and protocol serialization layers as well as the respect of semantics. + - Besides the core business logic, you might want to validate the network and protocol serialization layers as well as the respect of semantics. ## Business logic This application must implement basic flows: -* When creating a new `Order`, the service must check that the products are available before creating and persisting an order. Otherwise, order cannot be placed. -* When the `Order` is actually created, the service must also publish an `OrderEvent` to a specific Kafka topic to propagate this information to other systems that will review the events, -* When the `OrderEvent` has been reviewed, a new message is published on another `Kafka` topic. The `OrderEventListener` must capture-it and update the corresponding `Order` status using the service. +* When creating a new [`Order`](src/main/java/org/acme/order/service/model/Order.java), the service must check that the products are available before creating and persisting an order. Otherwise, order cannot be placed. +* When the [`Order`](src/main/java/org/acme/order/service/model/Order.java) is actually created, the service must also publish an [`OrderEvent`](src/main/java/org/acme/order/service/model/OrderEvent.java) to a specific Kafka topic to propagate this information to other systems that will review the events, +* When the [`OrderEvent`](src/main/java/org/acme/order/service/model/OrderEvent.java) has been reviewed, a new message is published on another `Kafka` topic. The [`OrderEventListener`](src/main/java/org/acme/order/service/OrderEventListener.java) must capture-it and update the corresponding [`Order`](src/main/java/org/acme/order/service/model/Order.java) status using the service. ## Flows specifications All the interactions are specified using API contracts: -* The Order API is specified using the `src/main/resources/order-service-openapi.yaml` OpenAPI specification, -* The Pastry API is specified using the `src/test/resources/third-parties/apipastries-openapi.yaml` OpenAPI specification, -* The Order Events are specified using the `src/main/resources/order-events-asyncapi.yaml` AsyncAPI specification. +* The Order API is specified using the [`order-service-openapi.yaml`](src/main/resources/order-service-openapi.yaml) OpenAPI specification, +* The Pastry API is specified using the [`apipastries-openapi.yaml`](src/test/resources/third-parties/apipastries-openapi.yaml) OpenAPI specification, +* The Order Events are specified using the [`order-events-asyncapi.yaml`](src/main/resources/order-events-asyncapi.yaml) AsyncAPI specification. Those specifications will help us for two things: 1) They will be used to provide simulations (or mocks) of third-parties systems - typically the Pastry API provider and the reviewer system that provides updates on `OrderEvents`