Tempo aproximado para leitura: 00 min

01. Apresentação

Este documento tem por objetivo apresentar as responsabilidades dos adapters de recebimento de Mensagens Padronizadas TOTVS.

02. Responsabilidades

Os Adapters de recebimento de mensagens são responsáveis por manipular o conteúdo recebido (BusinessContent), transformando no modelo de parâmetro esperado pelo serviço interno, processando o mesmo e retornando o resultado (ReturnContent) ao EAI para que seja enviado ao aplicativo integrado.

Dentre as diversas necessidades de integração, listamos a seguir dois fluxos comuns de integração que são o de processamento e de consulta de dados.

Fluxo de mensagem de processamento

O diagrama abaixo apresenta um possível fluxo de processamento de uma mensagem síncrona recebida, exemplificando com chamada a um Module, mas também se aplica ao consumo de DataServers, Subscribers ou qualquer outro objeto de negócio. Um exemplo de processo de integração que segue este fluxo é a mensagem CancelRequest, que realiza o cancelamento de movimentos.

Fluxo de mensagem de consulta

O diagrama abaixo, de forma similar ao anterior, apresenta o fluxo de processamento de uma mensagem síncrona de consulta de dados.


Principais funções do adapter de recebimento

  1. Transformar o dado de negócio recebido (BusinessContent) e orquestrar a chamada dos objetos de negócio (Servers).
    1. O adapter é responsável por interpretar os dados recebidos e transformar no modelo esperado pela interface do Server que será consumido.
      1. Exemplo: Ao receber uma mensagem de Request, o adapter deve transcrever o BusinessContent na classe de parâmetros do Subscriber e realizar a chamada ao Módule.
  2. Interpretar o processamento e gerar o objeto com as informações negócio da resposta (ReturnContent).
    1. É responsabilidade do adapter gerar o ReturnContent que será retornado ao aplicativo integrado.
      1. Exemplo: A mensagem de consulta de saldos e custos é responsável por buscar as informações no Módule interno ao sistema e converter para o objeto no formato da Mensagem Padronizada TOTVS.
      2. Exemplo 2: A mensagem de cadastro de produtos possui em seu ReturnContent uma propriedade que trafega a lista de De-Paras, que deve ser preenchida pelo Adapter.

03. Implementação de um adapter de recebimento

Para que uma classe seja um adapter de recebimento de mensagens, deve-se atender aos pré-requisitos listados abaixo e realizar as funções de integração listadas anteriormente.

Pré-requisitos

  1. Implementar a interface IAdapterReceive, implementando em cada método a sua respectiva responsabilidade, internamente a um projeto cuja Dll gerada siga o padrão "RM.*.TotvsMessage.Adapter.dll".

    1. InitializeAdapter - Método responsável pela inicialização do Adapter, recebendo o contexto de execução por referência.

    2. ChangeRMContext - Método que deve ser utilizado para compor o RMSContext a partir dos dados recebidos.

    3. ValidateBusinessContentXsd - Método para validação do BusinessContent a partir do XSD da mensagem.

    4. ValidatedSharedMode - Método para validação do nível de compartilhamento da entidade no sistema integrado com relação ao do RM.

    5. ExecuteReceive - Método responsável pelo processamento da mensagem, a partir dos dados fornecidos no BusinessContent. 

    6. GetReturnContent - Método responsável por retornar ao EAI o ReturnContent a ser devolvido ao sistema que originou a integração.

  2. Decorar a classe do adapter com o atributo "AdapterAttr".

    1. O atributo deve receber as informações obrigatórias, como nome da mensagem, versão, descrição e tipo (event/request).

  3. Implementar as classes de modelo referentes ao BusinessContent e ao ReturnContent da Mensagem Padronizada TOTVS, que serão utilizadas na serialização e deserialização das mensagens.

  4. As classes de modelo devem ser decoradas com o atributo "MessageContentTypeAttr" informando os atributos, descritos abaixo.
    1. TransactionName - Nome da transação referente a este modelo.
    2. MajorVersion - Versão cheia da mensagem. 
      1. Exemplo: Versão 1.003 possui MajorVersion 1. 
      2. Exemplo 2: Versão 3.023 possui MajorVersion 3.
    3. MessageType -  Tipo da transação a ter seu conteúdo de negócio serializado/deserializado utilizando esta classe (BusinessMessage ou ResponseMessage).

Código Fonte

using RM.Eai.TotvsMessage.Intf;
using RM.Eai.TotvsMessage.IService;
using RM.Eai.TotvsMessage.Lib;
using RM.Lib;
using System.Data;

namespace RM.Eai.TotvsMessage.Adapter
{
  [AdapterAttr(typeof(Properties.Resources),nameof(Properties.Resources.sEaiCaptionWhoIs), "WHOIS", "1.000", SubTypeEnum.teRequest)]
  public class WhoIs_Receive_1000 : IAdapterReceive
  {
    #region Propriedades
    EAIAdapterContext AdapterContext { get; set; }
    #endregion

    /// <summary>
    /// Método de inicialização do adapter
    /// </summary>
    /// <param name="adapterContext">Contexto de execução da mensagem</param>
    public void InitializeAdapter(EAIAdapterContext adapterContext)
    {
      AdapterContext = adapterContext;
    }

    /// <summary>
    /// Método responsável por processar os dados recebidos.
    /// </summary>
    /// <param name="parms">Parâmetros de entrada</param>
    /// <returns>Resultado do processamento dos dados recebidos</returns>
    public EAIExecReceiveResult ExecuteReceive(EAIExecReceiveParams parms)
    {
      EAIExecReceiveResult result = new EAIExecReceiveResult();
      //Este adapter não executa processamento, visto seu objetivo de consulta de dados.
      return result;
    }

    /// <summary>
    /// Método responsável por criar o ReturnContent que será retornado ao aplicativo integrado
    /// </summary>
    /// <param name="parms">Parâmetros de entrada</param>
    /// <returns>Resultado com o ReturnContent</returns>
    public EAIGetReturnContentReceiveResult GetReturnContent(EAIGetReturnContentReceiveParams parms)
    {
      EAIGetReturnContentReceiveResult result = new EAIGetReturnContentReceiveResult();

      //Serviço de consulta de rotas
      IEAITransacaoAppData dataServer = RMSBroker.CreateServer<IEAITransacaoAppData>("EAITransacaoAppData");

      //Obtém tabela com rotas ativas
      DataTable dtbRotas = dataServer.GetAppRoutes(AdapterContext.ContextItem.CurrentRoute.IdApp);

      //Converte pro modelo de retorno
      WhoIsModel_V1_ReturnContent returnContentObj = new WhoIsModel_V1_ReturnContent();
      foreach (DataRow rowRota in dtbRotas.Rows)
      {
        WhoIsModel_V1_EnabledTransaction transaction = new WhoIsModel_V1_EnabledTransaction();
        transaction.Name = RMSConvert.ToString(rowRota["TRANSACAO"]);
        transaction.Version = RMSConvert.ToString(rowRota["VERSAO"]);
        transaction.Mode = ConverteModoHabilitado(RMSConvert.ToString(rowRota["MODOHABILITADO"]));

        returnContentObj.EnabledTransactions.Add(transaction);
      }

      result.ReturnContent = returnContentObj;

      return result;
    }

    private string ConverteModoHabilitado(string ModoHabilitado)
    {
      switch (EnabledMode.Enum(ModoHabilitado))
      {
        case EnabledModeEnum.emSend:
          return "SEND_ENABLED";//DONOTLOCALIZE
        case EnabledModeEnum.emReceive:
          return "RECEIVE_ENABLED";//DONOTLOCALIZE
        case EnabledModeEnum.emBoth:
          return "BOTH_ENABLED";//DONOTLOCALIZE
        default:
          RMSException.Throw(string.Format(Properties.Resources.sEaiErroWhoIsModoInvalido, ModoHabilitado));
          //O método acima gera exceção, mas o compilador não compreende.
          //A linha abaixo foi inserida para permitir compilação mas nunca será executada.
          return "";
      }
    }

    /// <summary>
    /// Método responsável por atualizar o contexto.
    /// </summary>
    /// <param name="parms"></param>
    public void ChangeRMContext(EAIChangeRMContextReceiveParms parms)
    {
      //Desnecessária alteração de contexto pois o adapter acessa somente informações globais.
    }

    /// <summary>
    /// Método para validação do BusinessContent frente ao XSD
    /// </summary>
    /// <param name="parms">Parâmetros de entrada</param>
    public void ValidateBusinessContentXsd(EAIValidateBusinessContextXsdParams parms)
    {
      //Desnecessária validação pois o adapter não possui propriedades no BusinessContent
    }

    /// <summary>
    /// Método de validação do compartilhamento por Empresa/Filial
    /// </summary>
    /// <param name="parms">Parâmetros de entrada</param>
    /// <returns>Resultado da validação</returns>
    public EAIValidatedSharedModeResult ValidatedSharedMode(EAIValidatedSharedModeParams parms)
    {
      //Desnecessária validação pois esta mensagem não possui compartilhamento por Empresa/Filial
      return new EAIValidatedSharedModeResult() { Validated = true };
    }
  }
}


using RM.Eai.TotvsMessage.IService;
using RM.Eai.TotvsMessage.Lib;
using System.Collections.Generic;

namespace RM.Eai.TotvsMessage.Adapter
{
  [System.SerializableAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  [System.Xml.Serialization.XmlRootAttribute(ElementName = "BusinessContent", IsNullable = false)]
  [MessageContentTypeAttr("WHOIS", 1, MessageTypeEnum.tmBusinessMessage)]
  public partial class WhoIsModel_V1_BusinessContent
  {
	//O BusinessContent da mensagem WhoIs não possui propriedades.
  }
}
using RM.Eai.TotvsMessage.IService;
using RM.Eai.TotvsMessage.Lib;
using System.Collections.Generic;

namespace RM.Eai.TotvsMessage.Adapter
{
  [System.SerializableAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  [System.Xml.Serialization.XmlRootAttribute(ElementName = "ReturnContent", IsNullable = false)]
  [MessageContentTypeAttr("WHOIS", 1, MessageTypeEnum.tmResponseMessage)]
  public partial class WhoIsModel_V1_ReturnContent
  {
    [System.Xml.Serialization.XmlArrayItemAttribute("Transaction", IsNullable = false)]
    public List<WhoIsModel_V1_EnabledTransaction> EnabledTransactions { get; set; } = new List<WhoIsModel_V1_EnabledTransaction>();
  }

  /// <remarks/>
  [System.SerializableAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  public partial class WhoIsModel_V1_EnabledTransaction
  {
    public string Mode { get; set; }
    public string Version { get; set; }
    public string Name { get; set; }
  }
}

Implementações de produto

Os times dos segmentos tiveram iniciativa de desenvolver classes base e auxiliares para executar ações comuns e assim aumentar a produtividade no desenvolvimento de adapters. Estas classes estão disponíveis no projeto "RM.EAI.TotvsMessage.Adapter", que mesmo estando na solution do EAI é de domínio e manutenção dos times de produto.

A forma de uso destas classes foi documentada pelo produto no link a seguir: Desenvolvimento - EAI 2.

04. Assuntos Relacionados