Artigo
· Out. 23 9min de leitura

Desenvolvendo Integrações com InterSystems IRIS - Chamada Assíncrona no BP

Projeto 6 – Chamada Assíncrona no BP

Vamos montar nossa próxima integração utilizando o adaptador SOAP Inbound Adapter chamando um BP que vai orquestrar chamadas a dois BOs em modo assíncrono.

Vamos começar criando as mensagens de Request e Response do nosso serviço:

Class ws.credito.msg.Request Extends Ens.Request
{

Property cpf As %String(PATTERN = "1N.N");

}

Class ws.credito.msg.Response Extends Ens.Response
{

Property nome As %String;

Property cpf As %String(PATTERN = "1N.N");

Property autorizado As %Boolean;

Property servico As %String;

Property status As %Boolean;

Property mensagem As %String;

Property sessionId As %Integer;

}

Agora vamos ver o nosso BS, que como mencionado acima usa o SOAP Inbound Adapter:

Class ws.credito.bs.Service Extends EnsLib.SOAP.Service
{

Parameter ADAPTER = "EnsLib.SOAP.InboundAdapter";

Parameter SERVICENAME = "credito";

Method consulta(pInput As ws.credito.msg.Request) As ws.credito.msg.Response [ WebMethod ]
{
              Set tSC=..SendRequestSync("bpCredito",pInput,.tResponse)
              Quit tResponse
}

}

Vamos agora colocar nosso BS na production. Abra o Painel de Administração e vá para a nossa production de teste. Clique no botão (+) ao lado do nome Services e preencha a tela a seguir com os dados apresentados:

 

Agora volte a production e clique no nome do nosso BS (ws.credito.bs.Service) e veja a configuração dele. Expanda a área Parâmetros de Conexão e marque a caixa Habilitar Requisições Padrão conforme a tela abaixo:

A seguir clique em Atualizar e nosso BS de teste estará pronto.

Vamos agora ver nosso BO. Desta vez vamos colocar o BO na production duas vezes, com nomes diferentes. Cada BO vai simular a chamada a um serviço de validação de crédito com tempos de retorno diferentes para cada requisição. Abaixo o código do nosso BO:

Class ws.credito.bo.Operation Extends Ens.BusinessOperation [ ProcedureBlock ]
{

Method consulta(pRequest As ws.credito.msg.Request, Output pResponse As ws.credito.msg.Response) As %Library.Status
{
 Hang $R(10)+1
 Set pResponse=##Class(ws.credito.msg.Response).%New()
 Set pResponse.nome="NOME DA PESSOA "_pRequest.cpf
 Set pResponse.cpf=pRequest.cpf
 Set pResponse.autorizado=0
 If pRequest.cpf="11111111111"
 {
               Set pResponse.nome="PESSOA NUMERO 1"
               Set pResponse.autorizado=1
 }
 If pRequest.cpf="22222222222"
 {
               Set pResponse.nome="PESSOA NUMERO 2"
               Set pResponse.autorizado=1
 }
 If pRequest.cpf="33333333333"
 {
               Set pResponse.nome="PESSOA NUMERO 3"
               Set pResponse.autorizado=1
               Set pResponse.status=1
 }
 If pRequest.cpf="44444444444"
 {
               Set pResponse.nome="PESSOA NUMERO 4"
               Set pResponse.autorizado=1
               Set pResponse.status=1
 } 
 Set pResponse.status=1
 Set pResponse.mensagem="OK"
 Set pResponse.sessionId=..%SessionId 
 Quit $$$OK
}

XData MessageMap
{
<MapItems>
              <MapItem MessageType="ws.credito.msg.Request">
                            <Method>consulta</Method>
              </MapItem>
</MapItems>
}

}

A linha Hang $R(10)+1 vai definir um tempo de espera entre 1 e 10 segundos para as requisições que o BO for atender. Isso é para simular um tempo de resposta no serviço.

Feito o código do BO vamos coloca-lo na production. Primeiro vamos colocar o BO com o nome de boConsultaCreditoABC. Para isso clique no botão de (+) ao lado do nome Operations na nossa production e preencha a tela conforme abaixo:

 

Depois repita a operação, agora incluindo o BO boConsultaCreditoXYZ:

 

Pronto. Temos os nossos dois BOs na production. Agora vamos ver o nosso BP:

O nosso BP tem agora dois BOs que estão sendo chamados sem espera e depois tem um componente SYNC que aguarda o retorno destas chamadas pelo tempo configurado. É importante verificar que nas chamadas dos BOs (componente CALL) temos que marcar a caixa informado que a chamada será ASSÍNCRONA:

 

Faça o mesmo para o boConsultaCreditoXYZ:

 

 

Agora, no nosso componente SYNC vamos dizer que devem ser esperadas as respostas dos nossos BOs e o tempo de espera:

 

Na caixa Chamadas informamos os nomes dos BOs a aguardar (boConsultaCreditoABC e boConsultaCreditoXYZ) e na caixa Timeout o tempo de espera (5 segundos). Lembre-se: um BP pode chamar outros BPs ou outros BOs.

 

O código completo do nosso BP está abaixo:

/// 
Class ws.credito.bp.Process Extends Ens.BusinessProcessBPL [ ClassType = persistent, ProcedureBlock ]
{

/// BPL Definition
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl" ]
{
<process language='objectscript' request='ws.credito.msg.Request' response='ws.credito.msg.Response' height='2000' width='2000' >
<sequence xend='200' yend='1450' >
<call name='boConsultaCreditoABC' target='boConsultaCreditoABC' async='1' xpos='200' ypos='250' >
<request type='ws.credito.msg.Request' >
<assign property="callrequest" value="request" action="set" languageOverride="" />
</request>
<response type='ws.credito.msg.Response' >
<assign property="response" value="callresponse" action="set" languageOverride="" />
</response>
</call>
<call name='boConsultaCreditoXYZ' target='boConsultaCreditoXYZ' async='1' xpos='200' ypos='350' >
<request type='ws.credito.msg.Request' >
<assign property="callrequest" value="request" action="set" languageOverride="" />
</request>
<response type='ws.credito.msg.Response' >
<assign property="response" value="callresponse" action="set" languageOverride="" />
</response>
</call>
<sync name='Aguarda Operations' calls='boConsultaCreditoABC,boConsultaCreditoXYZ' timeout='5' type='all' xpos='200' ypos='450' />
<if name='Recebeu ABC' condition='$IsObject(syncresponses.GetAt("boConsultaCreditoABC"))' xpos='200' ypos='550' xend='200' yend='1350' >
<true>
<assign name="Atribui response ABC" property="response" value="syncresponses.GetAt(&quot;boConsultaCreditoABC&quot;)" action="set" languageOverride="" xpos='200' ypos='700' />
<assign name="Atribui servico" property="response.servico" value="&quot;ABC&quot;" action="set" languageOverride="" xpos='200' ypos='800' />
</true>
<false>
<if name='Recebeu XYZ' condition='$IsObject(syncresponses.GetAt("boConsultaCreditoXYZ"))' xpos='470' ypos='700' xend='470' yend='1250' >
<true>
<assign name="Atribui response XYZ" property="response" value="syncresponses.GetAt(&quot;boConsultaCreditoXYZ&quot;)" action="set" languageOverride="" xpos='470' ypos='850' />
<assign name="Atribui servico" property="response.servico" value="&quot;XYZ&quot;" action="set" languageOverride="" xpos='470' ypos='950' />
</true>
<false>
<assign name="Atribui CPF" property="response.cpf" value="request.cpf" action="set" languageOverride="" xpos='740' ypos='850' />
<assign name="Atribui status Erro" property="response.status" value="0" action="set" languageOverride="" xpos='740' ypos='950' />
<assign name="Atribui msg Erro" property="response.mensagem" value="&quot;Sem resposta do serviço&quot;" action="set" languageOverride="" xpos='740' ypos='1050' />
<assign name="Atribui SessionID" property="response.sessionId" value="..%Process.%SessionId" action="set" languageOverride="" xpos='740' ypos='1150' />
</false>
</if>
</false>
</if>
</sequence>
</process>
}

Storage Default
{
<Type>%Storage.Persistent</Type>
}

}

 

Com nossos componentes na production clique na bola verde ao lado de bpCredito e veja as ligações dos componentes:

Vamos visualizar o WSDL do nosso serviço. Para isso abra o navegador e vá para o endereço http://localhost/iris_iss/csp/integra/ws.credito.bs.Service.cls?WSDL=1 (troque íris_iss pelo nome da sua configuração IRIS e integra pelo namespace onde você está colocando seu código). Você verá uma tela assim:

 

Abra então o SoapUI e importe o WSDL. Vá em File->New SOAP Project e na janela que será apresentada coloque o endereço do WSDL na caixa Initial WSDL e a seguir clique em OK:

 

 

Project Name será preenchido automaticamente. Após o OK será disponibilizada a interface de teste do serviço:

 

 

Substitua o ? no XML pelo valor do CPF a consultar. Veja no BO as opções possíveis para respostas válidas. Por exemplo, 11111111111:

 

 

Veja que recebemos um XML com a resposta do serviço, informando qual BO atendeu nossa chamada:

 

 

 

 

<?xml version="1.0" encoding="UTF-8" ?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema'>

  <SOAP-ENV:Body><consultaResponse xmlns="http://tempuri.org"><consultaResult><nome>PESSOA NUMERO 1</nome><cpf>11111111111</cpf><autorizado>true</autorizado><servico>XYZ</servico><status>true</status><mensagem>OK</mensagem><sessionId>2266</sessionId></consultaResult></consultaResponse></SOAP-ENV:Body>

</SOAP-ENV:Envelope>

 

Verificando o trace da integração de SessionID 2266 vemos o que ocorreu:

Pelo trace podemos ver que o Response do boConsultaCreditoXYZ voltou rapidamente, enquanto que o Response do BO boConsultaCreditoABC demorou e voltou apenas depois do tempo de espera do componente SYNC. Ou seja, o componente SYNC aguardou até 5 segundos pelo retorno dos BOs. Uma vez superado o tempo de espera verificamos quais os BOs que responderam e realizamos o tratamento desejado. Veja a lógica nos IFs que temos no nosso BP.

Lembre-se que podemos colocar o TCPTRACE para verificar o tráfego que ocorre entre o SoapUI e o nosso BS, o que é especialmente útil em situações de teste.

Com isso concluímos esta integração. Utilizamos em nosso teste o IRIS 2024.1 que está disponível para download na sua versão Community na internet.

Discussão (0)1
Entre ou crie uma conta para continuar