Consuming API using http

Using synchronous communication over HTTP for communication between two microservices

This context will be developed using a microservice called “ms-order” and another called “ms-delivery”. The first will expose the API’s and the second microservices will make the requests via HTTP to obtain the details of a request in the “ms-order”.

Prepare the initial environment with docker

This example will use MongoDB as the database and RabbitMQ as the queue in the local docker environment. Make sure you have docker on tour with MongoDB and RabbitMQ containers active. /../../../quick-start/docker/). Enter the RabbitMQ thread to learn how to create the “Devprime” exchange and the orderevents and deliveryevents queues.

Creating “ms-order” microservices

In this microservice we will use an example of a marketplace business ‘order’. Below run the Devprime CLI.

dp new ms-order --state mongodb --stream rabbitmq --marketplace order --init

When finished, the first microservice will be ready for production and with the API’s built by the Devprime CLI accelerator. Run “ms-order” microservices
.\run.ps1 ou ./run.sh (Linux, macOS)

Open the “ms-order” browser microservice at the “https://localhost:5001 or http://localhost:5000” url and make a post to the API to create an order.

Creating “ms-delivery” microservices

Now we will create the ms-delivery and add an aggregate root called “Delivery”.
dp new ms-delivery --state mongodb --stream rabbitmq

Enter the ms-delivery folder and add an Aggregate Root
dp add aggregate Delivery

After executing the commands, open the “Delivery.cs” file in the ms-delivery/src/Core/Domain/Aggregates/Delivery folder and add the code below to the “Delivery” root aggregate to complement the functionality required by our implementation.
code src/Core/Domain/Aggregates/Delivery/Delivery.cs

1
2
3
4
5
6
7
8
namespace Domain.Aggregates.Delivery;
    public class Delivery : AggRoot
    {
       public DateTime Started { get; private set;}
       public DateTime Finished { get; private set;}
       public Guid OrderID { get; private set;}
       public double Total { get; private set;}      
    }

After adding the code, run the Devprime CLI to build the basic implementations of the “ms-delivery” microservice
dp init

By the end you will have the “ms-delivery” microservice ready for us to use. To meet our scenario we will make some customizations. At first it is important to remember to change the ports on the Web Adapter in the configuration file ms-delivery/src/App/appsettings.json to 5002 and 5003 to avoid conflict with the “ms-order” when on tour.
code src/App/appsettings.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
"Devprime_Web": {
    "url": "https://localhost:5003;http://localhost:5002",
    "enable": "true",
    "enableswagger": "true",
    "PostSuccess": "201",
    "PostFailure": "500",
    "GetSuccess": "200",
    "GetFailure": "500",
    "PatchSuccess": "200",
    "PatchFailure": "500",
    "PutSuccess": "200",
    "PutFailure": "500",
    "DeleteSuccess": "200",
    "DeleteFailure": "500"
},

After you change you can run the project and confirm the portal change from the Devprime log. It is important to enforce the presence of the automatic logging provided by the Observability adapter. Finalize the project and follow the next steps.

Creating a DomainEvent and DTO

We will now create a domain event ‘DeliveryGetOrder’ and a Handler to implement the external access call using http. The Devprime CLI offers an accelerator for adding domain events.

We will need a Data Transfer Object (DTO) to convert the result from the “ms-order” API. The first step will be to create the src/Core/Application/EventHandlers/Delivery/Model folder if it doesn’t exist and add a new “OrderCreated.cs” file with the text below.

Open the file via Visual Studio Code (vscode).
code src/Core/Application/EventHandlers/Delivery/Model/OrderCreated.cs

Add the code and save.

1
2
3
4
5
namespace Application.EventHandlers.Delivery.Model;
    public class OrderCreated: ServicesResult
    {
        public double Total { get; set; }
    }

Now that you have a Data Transfer Object (DTO) we’re going to add a domain event. And to make the process easier, we’ll use an accelerator from the Devprime CLI.
dp add domainevent DeliveryGetOrder -agg Delivery

After confirming, open the “DeliveryGetOrderEventHandler.cs” file in the /src/Core/Application/EventHandlers/Delivery folder and implement the query to the external service using Adapter Services by the command “Dp.Services.HTTP.DpGet”.

Open the file via Visual Studio Code (vscode).
code src/Core/Application/EventHandlers/Delivery/DeliveryGetOrderEventHandler.cs

Change the code to evaluate the “result” return. In case of success with the code “200” we will refund the order amount.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using Application.EventHandlers.Delivery.Model;
namespace Application.EventHandlers.Delivery;


public class DeliveryGetOrderEventHandler : EventHandler<DeliveryGetOrder,
 IDeliveryState>
{
    public DeliveryGetOrderEventHandler(IDeliveryState state,
     IDp dp) : base(state, dp)
    {
    }

    public override dynamic Handle(DeliveryGetOrder domainEvent)
    {
        // Aggregate Root
        var delivery = domainEvent.Get<Domain.Aggregates.Delivery.Delivery>();

        // External http request using Services Adapter
        var url = $"https://localhost:5001/v1/order/{delivery.OrderID}";

        // Executando o request externo usando http 
        var result = Dp.Services.HTTP.DpGet<OrderCreated>(url);

        // Analisando o resultado da consulta externa
        if (result.Dp.Status.Equals(200)|| result.Dp.Status.Equals(201))
            return result.Total;
        else
            return null;
    }
}

In this example, the Services Adapter will access a Devprime-based API via HTTP and using the “DpGet” command specific to Devprime-based APIs. By using DpGet, it already identifies the result and converts it into the “OrderCreated” format, automatically simplifying the process.

Adding a DomainEvent in Aggretate

The last step is to modify the “Add()” method present in the Aggretate root “Delivery”. Add the implementation to emit the “DeliveryGetOrder()” event that will be intercepted by the previously implemented “DeliveryGetOrderEventHandler” Handler.
code src/Core/Domain/Aggregates/Delivery/Delivery.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public virtual void Add()
{
          Dp.Pipeline(Execute: () =>
          {
            ValidFields();
              ID = Guid.NewGuid();

              var ordertotal = Dp.ProcessEvent(new DeliveryGetOrder());
              if (ordertotal > 0)
              {

                  Total = ordertotal;
                  Dp.ProcessEvent(new DeliveryCreated());
              }
              else
              {
                  throw new PublicException("Can not confirm order");
              }            
          });
}

If we manage to get the order value, we will update the aggregate and emit the “DeliveryCreated” event, propagating the business fact. If not, we will issue a PublicException
that will return to the caller of that API a failure information in the process.

Demonstrating the Delivery scenario

To start demonstrating the scenario, you need to run the “ms-order” and “ms-delivery” microservices at the same time. As they are at different doors, we will be able to demonstrate the scenario with tranquility.

microservices: Order

  1. Open the browser in the microservices API “ms-order” at [http://localhost:5000 or https://localhost:5001]
  2. Make a post to the API ‘/v1/order" by filling in the customerName and total.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "customerName": "Bill",
  "customerTaxID": "string",
  "itens": [
    {
      "description": "string",
      "amount": 0,
      "sku": "string",
      "price": 0
    }
  ],
  "total": 1000
}
  1. Do a get in the ‘/v1/order’ API and locate the order code ‘id’

microservices: Delivery

  1. Open the browser in the “ms-order” microservices API at [http://localhost:5002 or https://localhost:5003]
  2. Make a post to the ‘/v1/delivery’ API by entering the order code in ‘orderID’.
1
2
3
4
5
6
{
  "started": "2022-03-07T17:54:41.920Z",
  "finished": "2022-03-07T17:54:41.920Z",
  "orderID": "",
  "total": 0
}
  1. The “ms-delivery” microservices will query the order API using Adapter Services and return the total value of the order. The next step is to create a record in the delivery microservice and emit an event in the Stream
1
2
3
{
  "success": true
}

Devprime Version

You can also track the ‘GET’ request on the Order microservice side

Devprime Version

  1. In this new scenario generate a GUID with non-existent orderID and post to the ‘/v1/delivery’ API.
1
2
3
4
5
6
{
  "started": "2022-03-07T17:54:41.920Z",
  "finished": "2022-03-07T17:54:41.920Z",
  "orderID": "a316f224-c8fd-4d4d-8495-600f9fea7aaa",
  "total": 0
}
  1. When querying the “Order” microservice about a non-existent order, the Delivery API returns an error.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "success": false,
  "error": {
    "type": "Public",
    "trace": "05d359f0-f99a-4f63-8f89-0ac87ac36edd",
    "exceptions": [
      "Can not confirm order"
    ]
  }
}

Congratulations 🚀🚀🚀.

Last modified August 20, 2024 (2f9802da)