Running the Services Together

Start Each Service

Example

Open one terminal per service (or run both from your IDE). Start the service that others depend on first:

# terminal 1
cd product-service && ./mvnw spring-boot:run

# terminal 2
cd order-service && ./mvnw spring-boot:run

# check both are healthy
curl localhost:8081/actuator/health
curl localhost:8082/actuator/health

Example output

... Tomcat started on port 8081 (http) ... Started ProductServiceApplication in 3.1 seconds
... Tomcat started on port 8082 (http) ... Started OrderServiceApplication in 3.4 seconds

{"status":"UP"}
{"status":"UP"}

Or Use Docker Compose

Build each service into an image, then start the whole system with one command. Service names become host names on the Compose network (Docker basics are in the Docker material):

services:
  product-service:
    build: ./product-service
    ports: ["8081:8081"]

  order-service:
    build: ./order-service
    ports: ["8082:8082"]
    environment:
      PRODUCT_SERVICE_URL: http://product-service:8081
    depends_on:
      - product-service

Run it

docker compose up --build -d
docker compose ps

Example output

NAME                        SERVICE           STATUS         PORTS
shopease-product-service-1  product-service   Up 12 seconds  0.0.0.0:8081->8081/tcp
shopease-order-service-1    order-service     Up 11 seconds  0.0.0.0:8082->8082/tcp

End-to-End Check

curl POST :8082/api/orders
        |
        v
+---------------+   POST /api/products/1/reserve   +-----------------+
| order-service | -------------------------------> | product-service |
|    :8082      | <------------------------------- |     :8081       |
+-------+-------+   200 {"id":1,"price":1499.00}   +--------+--------+
        |                                                   |
    order_db  (INSERT orders, order_items)          product_db (UPDATE stock)
        |
        v
201 Created {"id":1,"status":"CREATED","total":2998.00}

Example

Verify stock went down in product-service:

curl localhost:8081/api/products/1

Example output

{"id":1,"name":"boAt Rockerz 450","price":1499.00,"stock":118,"category":"Electronics"}

Practice

Exercise: Add user-service on port 8083 with GET /api/users/{id}. Change order-service so it rejects orders from unknown users with 400 Bad Request. Which files change in order-service?

Show answer
order-service changes:
1. application.yml
     shopease.services.user-url: ${USER_SERVICE_URL:http://localhost:8083}
2. ServiceUrls record: add  String userUrl
3. New client/UserClient.java
     public record UserResponse(Long id, String name, String email) {}
     public boolean exists(Long id) {
         return restClient.get().uri("/api/users/{id}", id)
             .retrieve()
             .onStatus(s -> s.value() == 404, (req, res) -> { throw new UnknownUserException(id); })
             .toBodilessEntity()
             .getStatusCode().is2xxSuccessful();
     }
4. OrderService.place(): call userClient.exists(req.userId()) first
5. OrderErrors: @ExceptionHandler(UnknownUserException.class) -> 400 ProblemDetail
6. docker-compose.yml: add user-service and USER_SERVICE_URL for order-service