Consumindo API usando http

Utilizando comunicação síncrona via HTTP para comunicação entre dois microsserviços

Esse contexto será desenvolvido utilizando um microsserviços chamado “ms-order” e outro chamado “ms-delivery”. O primeiro exporá as API’s e o segundo microsserviços efetuará as requisições via HTTP para obtenção dos detalhes de um pedido no “ms-order”.

Prepare o ambiente inicial com o Docker

Este exemplo utilizará o MongoDB como banco de dados e o RabbitMQ como fila no ambiente local do Docker. Certifique-se de ter o Docker em excursão com os containers do MongoDB e RabbitMQ ativos. Entre no tópico do RabbitMQ para aprender como criar a exchange “Devprime” e as filas orderevents e deliveryevents.

Criando o microsserviços “ms-order”

Nesse microsserviço utilizaremos um exemplo de negócio do marketplace ‘order’. Abaixo execute o Devprime CLI.

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

Ao finalizar o primeiro microsserviço estará pronto para produção e com as API’s construidas pelo acelerador do Devprime CLI. Execute o microsserviços “ms-order”
.\run.ps1 ou ./run.sh (Linux, macOS)

Abra o microsserviço “ms-order” navegador na url “https://localhost:5001 ou http://localhost:5000” e efetue um post na API para criar um pedido.

Criando o microsserviços “ms-delivery”

Agora criaremos o ms-delivery e adicinaremos na sequência um aggregate root chamado “Delivery”.
dp new ms-delivery --state mongodb --stream rabbitmq

Entre na pasta ms-delivery e adicione um Aggregate Root
dp add aggregate Delivery

Após executar os comandos abra o arquivo “Delivery.cs” na pasta ms-delivery/src/Core/Domain/Aggregates/Delivery e adicione o código abaixo no aggregate root “Delivery"para complementar a funcionalidade necessária a nossa implementação.
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;}      
    }

Após adicionar o código execute o acelerador do Devprime CLI para construir as implementações básicas do microsserviço “ms-delivery”
dp init

Ao final você já terá o microsserviço “ms-delivery” pronto para utilizarmos. Para atender o nosso cenário faremos algumas customizações. No primeiro momento é importante lembrar de alterar as portas no Adapter de Web no arquivo de configuração ms-delivery/src/App/appsettings.json para 5002 e 5003 para evitar conflito com o “ms-order” quando em excursão.
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"
},

Após alterar pode executar o projeto e confirmar a mudança de portal pelo log do Devprime. É importante reforçar a presença o log automático fornecido pelo adapter de Observability. Finalize o projeto e siga os próximos passos.

Criando um DomainEvent e um DTO

Nós vamos agora criar um evento de dominío ‘DeliveryGetOrder’ e um Handler para implementarmos a chamada de acesso externo utilizando http. O Devprime CLI oferece um acelerador para adicionar eventos de dominíos.

Nós precisaremos de um Data Transfer Object (DTO) para converter o resultado da API “ms-order”. O primeiro passo será criar a pasta src/Core/Application/EventHandlers/Delivery/Model caso não exista e adicionar um novo arquivo “OrderCreated.cs” com o texto abaixo.

Abra o arquivo pelo Visual Studio Code (vscode).
code src/Core/Application/EventHandlers/Delivery/Model/OrderCreated.cs

Adicione o código e salve.

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

Agora que você já tem um Data Transfer Object (DTO) nós vamos adicionar um evento de domínio. E para facilitar o processo utilizaremos um acelerador do Devprime CLI.
dp add domainevent DeliveryGetOrder -agg Delivery

Após confirmar abra o arquivo “DeliveryGetOrderEventHandler.cs” na pasta /src/Core/Application/EventHandlers/Delivery e implememte a consulta ao serviço externo utilizando o Adapter Services pelo comando “Dp.Services.HTTP.DpGet”.

Abra o arquivo pelo Visual Studio Code (vscode).
code src/Core/Application/EventHandlers/Delivery/DeliveryGetOrderEventHandler.cs

Altere o código para avaliarmos o retorno “result”. Em caso de sucesso com o código “200” nós retornaremos o valor do pedido.

 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;
    }
}

Ness exemplo o Adapter de Services acessará uma API baseada no Devprime via HTTP e utilizando o comando “DpGet” especifico para API’s baseadas no Devprime. Ao utilizar o DpGet ele já identifica o resultado e converte no formato “OrderCreated” automatiamente simplificando o processo.

Adicionando um DomainEvent no Aggretate

A última etapa é modificar o método “Add()” presente no Aggretate root “Delivery”. Adicione a implementação para emitir o evento “DeliveryGetOrder()” que será interceptado pelo Handler “DeliveryGetOrderEventHandler” implementado anteriormente.
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");
              }            
          });
}

Se conseguirmos obter o valor do pedido nós vamos atualizar o aggregate e emitir o evento “DeliveryCreated” propagando o fato de negócio. Em caso negativo nós emitiremos um PublicException
que retornará ao chamador dessa API uma informação de falha no processo.

Demonstrando o cenário de Delivery

Para inicia a demonstração do cenário é necessário executar o microsserviços “ms-order” e “ms-delivery” ao mesmo tempo. Como estão em portas diferentes nós conseguiremos demonstrar o cenário com tranquilidade.

microsserviços: Order

  1. Abra o navegador na API do microsserviços “ms-order” em [http://localhost:5000 ou https://localhost:5001]
  2. Efetue um post na API ‘/v1/order” colocando preenchendo o customerName e 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. Faça um get na API ‘/v1/order’ e localize o código do pedido ‘id’

microsserviços: Delivery

  1. Abra o navegador na API do microsserviços “ms-order” em [http://localhost:5002 ou https://localhost:5003]
  2. Efetue um post na API ‘/v1/delivery’ informando o código do pedido em ‘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. O microsserviços “ms-delivery” irá consultar a API order utilizando o Adapter Services e retornar o valor total do pedido. O próximo passo é criar um registro no microsserviço de delivery e emitir um evento no Stream
1
2
3
{
  "success": true
}

Devprime Version

Você também consegue acompanhar do lado do microsserviço Order a solicitação ‘GET’

Devprime Version

  1. Nesse novo cenário gere uma GUID com orderID inexistente e efetue um post na 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. Ao consultar o microsserviço “Order” sobre um pedido inexistente a API de Delivery retorna um erro.
 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"
    ]
  }
}

Parabéns 🚀🚀🚀.

Última modificação September 2, 2023 (710d0ffd)