Páginas filhas
  • 3.2 Adapters de Recebimento

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

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.

O diagrama abaixo apresenta de forma macro a série de eventos que ocorrem durante o processamento de uma mensagem recebida, exemplificando com a chamada a um Module, mas também se aplica ao consumo de DataServers, Subscribers ou qualquer outro objeto de negócio.

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNameAdapterReceive
simpleViewerfalse
width
diagramWidth608
revision1

Principais funções do adapter de recebimento


  1. Gerar o conteúdo de negócio da mensagem a enviar (BusinessContent).
    1. O adapter é responsável por implementar os padrões apresentados anteriormente, transformando o formato do dado original, enriquecendo ou empobrecendo o mesmo, além de realizar as validações necessárias.
    2. Após o adapter encaminhar ao EAI o dado de negócio (BusinessContent), todo o fluxo de envelopamento, salvamento na fila de mensagens e envio ao destinatário é de responsabilidade do EAI.
  2. Transformar e/ou processar as informações de negócio da resposta (ReturnContent).
    1. Em integrações para consulta de dados a mensagem de resposta deve ser transformada do formato da Mensagem Padronizada TOTVS para o modelo de retorno, esperado pelo módulo que originou a mensagem.
      1. Ex.: Mensagens de consulta de informações devem transformar o dado recebido antes de encaminhar para o módulo de consulta.
    2. Caso a mensagem trafegada demande algum processamento de responsabilidade da camada de integração, este deve ser implementado no método correspondente do adapter.
      1. Ex.: Mensagens de cadastro devem ter o De-Para armazenado na base de dados.
      2. Ex2.: Mensagens assíncronas que devam desbloquear o registro no momento do retorno de sucesso.

03. Implementação de um adapter de envio

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

Pré-requisitos

  1. Implementar a interface IAdapterSend, 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. CanExecute - Método que permite ao adapter realizar verificações e informar se a mensagem deve ser processada, ignorada ou gerar exceção.

    3. Prepare - Método responsável por retornar ao EAI o BusinessContent a ser enviado ao destinatário, juntamente com outras demandas específicas de negócio.

    4. ProcessResponseMessage - Método responsável por processar os dados retornados pelo aplicativo integrado, como atualizar algum campo de controle ou transformar o dado em caso de consultas, como esta mensagem.

  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

Deck of Cards
startHiddenfalse
historyfalse
idCodigoSemClasseBase

using

RM.Eai.TotvsMessage.Intf;

using

RM.Eai.TotvsMessage.IService;


using

RM.Eai.TotvsMessage.Lib;


using

RM.Lib;


using

System

.Collections

.

Generic; using System.

Data;



namespace

RM.Eai.TotvsMessage.Adapter


{


[AdapterAttr(typeof(Properties.Resources),nameof(Properties.Resources.sEaiCaptionWhoIs),

"WHOIS",

"1.000",

SubTypeEnum.teRequest)]


public

class

WhoIs_

Send

Receive_1000

: IAdapterSend { #region Properties private EAIAdapterContext AdapterContext { get; set; } #endregion /// <summary> /// Método de inicialização do Adapter. /// </summary> /// <param

_WithoutBase : IAdapterReceive
{
#region Propriedades
EAIAdapterContext AdapterContext { get; set; }
#endregion

/// <summary>
/// Método de inicialização do adapter
/// </summary>
/// <param name="adapterContext">Contexto

de

execução do Adapter</param> public void

execução da mensagem</param>
public void InitializeAdapter(EAIAdapterContext

adapterContext)

{ AdapterContext = adapterContext; }


{
AdapterContext = adapterContext;
}

///

<summary>


///

Método

responsável

por informar ao EAI se a mensagem deve ser processada, ignorada ou gerar exceção.

por processar os dados recebidos.
///

</summary>


///

<param

name="parms"

>Parametros<

>Parâmetros de entrada</param>


///

<returns>Retorno<

<returns>Resultado do processamento dos dados recebidos</returns>

public EAICanExecuteSendResult CanExecute(EAICanExecuteSendParams parms) { //Não existe condicional, sempre permitindo enviar. return new EAICanExecuteSendResult() { CanExecute = EAICanExecuteEnum.csEnviar }; } /// <summary> /// Método responsável por transformar os parâmetros de entrada no BusinessContent a ser enviado /// </summary> /// <param


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

originais<

de entrada</param>


///

<returns>Resultado

do método de preparação,

com

o

Objeto BusinessContent<

ReturnContent</returns>

public EAIPrepareSendResult Prepare(EAIPrepareSendParms parms) { EAIPrepareSendResult result = new EAIPrepareSendResult(); //A mensagem de WhoIs não possui dados no BusinessContent result.BusinessContent = new WhoIsModel_V1_BusinessContent(); return result; } /// <summary> /// Processa ReturnContent recebido, transformando no objeto no formato esperado pelo método chamador. /// </summary> /// <param name="parms">Parâmetros de entrada</param> /// <returns>Resultado</returns> public EAIProcessResponseMessageSendResult ProcessResponseMessage(EAIProcessResponseMessageSendParams parms) { EAIProcessResponseMessageSendResult result = new EAIProcessResponseMessageSendResult(parms.ResponseMessageItem); //Obtém o ReturnContent deserializado para o tipo definido WhoIsModel_V1_ReturnContent returnContent = (WhoIsModel_V1_ReturnContent)parms.ResponseMessageItem.ResponseMessage.ReturnContent.ReturnContentObj; //Converte lista de transações no tipo de retorno. EAIWhoIsResult listaTransacoes = new EAIWhoIsResult(AdapterContext.ContextItem.CurrentRoute.IdApp); //Percorre todas as transações foreach (WhoIsModel_V1_EnabledTransaction enabledTransaction in returnContent.EnabledTransactions) { EAIWhoIsTransaction transacao = new EAIWhoIsTransaction() { ModoHabilitado = ConvertModoHabilitado(RMSConvert.ToString(enabledTransaction.Mode)),//DONOTLOCALIZE NomeMensagem = RMSConvert.ToString(enabledTransaction.Name),//DONOTLOCALIZE Versao = RMSConvert.ToString(enabledTransaction.Version)//DONOTLOCALIZE }; listaTransacoes.Add(transacao); } //Obtém o UUID da mensagem original listaTransacoes.BusinessMessageUUID = this.AdapterContext.ContextItem.Message.UUID; //Obtém o UUID da mensagem de resposta listaTransacoes.ResponseMessageUUID = parms.ResponseMessageItem.MessageInformation.UUID; //Adiciona no objeto de retorno result.Data = listaTransacoes; //Retorna o dado processado, no tipo de retorno esperado. return result; } private EnabledModeEnum ConvertModoHabilitado(string Mode) { switch (Mode.ToUpperInvariant()) { case "SEND_ENABLED"://DONOTLOCALIZE return EnabledModeEnum.emSend; case "RECEIVE_ENABLED"://DONOTLOCALIZE return EnabledModeEnum.emReceive; case "BOTH_ENABLED"://DONOTLOCALIZE return EnabledModeEnum.emBoth; default:


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,

Mode

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 0;//EnabledModeEnum } } } }


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

Card
defaulttrue
idAdapter
labelAdapter
titleAdapter
Bloco de código
languagec#
firstline1
linenumberstrue
Card
idBusinessContentModel
labelBusinessContent Model
titleBusinessContent Model
Bloco de código
languagec#
firstline1
linenumberstrue
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.
  }
}
Card
idReturnContentModel
labelReturnContent Model
titleReturnContent Model
Bloco de código
languagec#
firstline1
linenumberstrue
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 - Adapter.

04. Assuntos Relacionados