Consuming API using http

Using synchronous communication via 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. Join the RabbitMQ topic to learn how to create the “Devprime” exchange and the orderevents and deliveryevents queues.

Creating the “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

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

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

Creating the “ms-delivery” microservices

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

Go into 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 in the aggregate root “Delivery” to complement the functionality needed 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] accelerator(../../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 ms-delivery/src/App/appsettings.json configuration file to 5002 and 5003 to avoid conflict with the “ms-order” when on excursion.
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 the 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 log provided by the Observability adapter. Finalize the project and follow the next steps.

Creating a DomainEvent and a DTO

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

We will need a Data Transfer Object (DTO) to convert the result of 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 from 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 a [Devprime CLI] accelerator (../../cli/).
dp add domainevent DeliveryGetOrder -agg Delivery

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

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

Change the code so that we 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 to 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 can get the order value, we’ll update the aggregate and emit the “DeliveryCreated” event, propagating the business fact. If not, we will issue a PublicException
which will return to the caller of that API a process failure information.

Demonstrating the Delivery Scenario

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

microservices: Order

  1. Open the browser in the “ms-order” microservices API at [http://localhost:5000 or https://localhost:5001]
  2. Post in 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 API ‘/v1/order’ and locate the order code ‘id’

Microservices: Delivery

  1. Open the browser in the “ms-order” microservices API on [http://localhost:5002 or https://localhost:5003]
  2. Post in the API ‘/v1/delivery’ entering the order ID 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 request. The next step is to create a record in the delivery microservice and emit an event in Stream
1
2
3
{
  "success": true
}

Devprime Version

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

Devprime Version

  1. In this new scenario generate a GUID with non-existent orderID and post to the API ‘/v1/delivery’.
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 April 11, 2024 (cc33f7e6)