Hydra

Componente que oferece estrutura para permitir integração entre sistemas, utiliza scripts para que as especificidades de cada integração (que geralmente são extremamente voláteis) fiquem isoladas da aplicação.

Integração de Sistemas

Quando criamos produtos estamos desenvolvendo soluções para problemas dos nossos clientes, problemas que geralmente são complexos. A forma natural de se resolver algo complexo é: dividir em pedaços menores e mais fáceis de gerenciar que, quando juntos, resolvem algo maior. O problema de criar sistemas de sistemas é que eles precisam trocar informações, sincronizar ações, e muitas vezes os pontos intermediários são extremamente frágeis (por exemplo, sistemas legados dos nossos próprios clientes), sem falar do fator externo, em que muitas vezes as informações que recebemos dos nossos clientes se revelam incorretas e isso só é descoberto quando já é tarde demais.

A imagem abaixo exemplifica a dinâmica que geralmente encontramos em sistemas de sistemas:

../../_images/Hydra_esquema_sistema.png

Esta é, claro, uma simplificação. Nos clientes este panorama pode englobar dezenas de componentes, todos interligados e vivos. Idealmente, quando um falha, os outros deveriam continuar funcionando, mas sem a solução correta não é isto o que acontece. Além da própria complexidade da integração, ainda podemos encontrar diversos fatores que influenciam em sua instabilidade:

  • Documentação Desatualizada
  • Sistemas Externos voláteis e pouco confiáveis
  • Difícil comunicação com o cliente
  • Integração com linguagens arcanas
  • Problemas frequentes de encoding
  • Problemas frequentes com formas de transmissão

Hydra

O Hydra surgiu desta necessidade de flexibilidade nas integrações de nossas soluções com outros produtos da própria MAPS ou com legados de clientes e tem como base as seguintes linhas:

  • Capacidade de lidar com qualquer sistema externo
  • Suporte a qualquer encoding
  • Suporte a qualquer forma de transmissão
  • Tudo seja rastreável
  • Suporte falhas externas
  • Dinamicidade

Hoje ele é um componente do [[JMine_tec_component|Jmine Tec]] que permite que qualquer sistema consiga realizar integrações de forma flexível, além de separar a parte mais sensível e volátil da integração em scripts, permitindo mudanças sem a necessidade de recompilação e redeploy. Veja o exemplo anterior com o intermédio do Hydra:

../../_images/Hydra_esquema_sistema_managed.png

Estrutura

Mensagens

Sistemas integrados conversam entre si, ou seja, trocam mensagens e mantêm um contexto significativo sobre elas, assim é possível saber que uma resposta A está relacionada com uma pergunta C. Isto é realizado através da troca de Mensagens, para fins de rastreabilidade o sistema consegue agrupar mensagens em Conversas. Uma mensagem dispara ações e pode ser qualquer coisa: uma chamada de serviço, um arquivo de texto em uma pasta etc...

Mensagens e conversas são tratados através das classes HydraMessage e HydraConversation, respectivamente.

Requisições

Apesar dos sistemas conversarem entre si trocando mensagens, o Hydra conhece apenas Requisições, uma requisição possui sempre uma ação raiz, que pode chamar outras ações e assim por diante. Uma requisição pode gerar uma mensagem, e uma mensagem recebida pode gerar uma requisição, além disto, uma requisição sempre possui uma ou mais ações.

Requisições podem ser de dois tipos:

  • Envio
  • Recebimento

Além disto possuem diversos status, que podem ser acompanhados via tela de sistema para ajustes ou qualquer tipo de diagnóstico:

  • Inicializado: status inicial
  • Sucesso: todas as ações foram executadas com sucesso
  • Falha: caso ocorra alguma falha de sistema grave
  • Pendente: houve problema com alguma ação, está aguardando intervenção manual
  • Resolvido: ações pendentes foram marcadas como resolvidas pelo usuário via tela

HydraRequest é uma das entidades do componente, e é através dela que você pode obter o status das mensagens do sistema.

Cadastros Básicos

O Hydra oferece uma estrutura bastante flexível que cuida da parte mais comum de uma integração, deixando a cargo do desenvolvedor fornecer suas especificidades. Para usar a estrutura oferecida, é necessário cadastrar primeiramente um Sistema Integrado e quais são suas Formas de Ativação. Isto equivale a dizer ao Hydra quais sistemas externos ele deve cuidar e o que ele deve tentar fazer quando uma mensagem for gerada (recebida ou enviada).

../../_images/Estrutura_sistema.png

As entidades HydraSystem e HydraActivation também fazem parte da estrutura básica do componente e dificilmente você precisará lidar diretamente com elas, seu cadastro ocorre através de postscript.

Especificações

Quando necessário, o sistema verifica a mensagem (recebida ou enviada) e encontra a forma de ativação equivalente. Cada forma possui um script atrelado que verifica uma mensagem e decide o que fazer com ela. De uma forma geral funciona como um switch, e escolhe um conjunto de outros scripts que ficarão responsáveis pelo processamento, este conjunto de scripts e conhecido como uma “Especificação”.

Os componentes de uma especificação mudam de acordo com o fluxo seguido e é possível combinar especificações de envio e de recebimento em uma só, já que cada uma possui componentes distintos.

HydraSpecification também é um cadastro básico realizado através de postscript.

Fluxo de Envio

Define todo o processo que prepara uma mensagem, desde seu ‘empacotamento’ até seu envio. Podemos usar o método send(msg, activation) do HydraController para gerar a ação inicial de envio, então o script de ativação determina como tratar a mensagem que será enviada definindo qual a especificação responsável por ela, e com isto a próxima ação. Nela a mensagem passará por outros três scripts (descritos abaixo) que vão prepara-la e enviá-la.

../../_images/Fluxo_envio.png

Especificação de Envio

Cada especificação para envio de mensagens é possui três componentes:

  • Encoder: é o primeiro script executado, ele prepara o contexto da mensagem, ou seja, busca informações que serão usadas ao montá-la
  • Template: recebe as informações levantadas pelo encoder e formata de acordo com as especificações da mensagem
  • Sender: já com a mensagem em mãos, cuida da transmissão real da mensagem: gera um arquivo em um ftp, envia por email, MQ etc... Já existe um conjunto padrão de Senders disponíveis no Hydra

Fluxo de Recebimento

O fluxo de recebimento é análogo ao de envio, quando uma mensagem é recebida a forma de ativação é definida e seu script é executado. Ele define qual a especificação responsável pelo tratamento daquela mensagem e a executa. A especificação de recebimento é bem diferente da de envio, pois só possui um componente. É o script responsável pela decodificação da mensagem recebida e pelo encaminhamento dela para a mídia responsável.

../../_images/Fluxo_recebimento.png

Especificações de Recebimento

As especificações de recebimento possuem apenas um componente:

  • Decoder: sabe decodificar os bytes de mensagem recebidos e encaminha aos serviços responsáveis pelo seu processamento

Filtros de Mensagens

Algumas vezes é necessário alterar mensagens, seja para tentar resolver algum problema ou como parte de algum passo para integração com um sistema externo. Para isto existem os “Filtros”, que são ações adicionais geradas a cada envio ou recebimento, possuem um script e podem ser de dois tipos:

  • Filtros de Saída: afetam todas as mensagens que são enviadas
  • Filtros de Entrada: afetam todas as mensagens que são recebidas

Os filtros trabalham a nível do Sistema, então afetará TODAS as mensagens processadas que estejam relacionadas com seu tipo.

Rastreabilidade

Como já citado neste e em outros artigos, uma das bases do [[Jmine]] é a rastreabilidade de toda e qualquer operação, no Hydra não é diferente, e por possuir uma estrutura genérica é o desenvolvedor quem precisa dizer como fazer isto. Fica a cargo do desenvolvedor definir como atrelar corretamente mensagens a sua respectiva conversa, durante a fase de ativação do Hydra. Além disto, caso seja necessário atrelar mensagens a objetos de negócio, também fica por conta dele associá-los corretamente (por exemplo, associar uma conversa gerada por uma TED a um pagamento de título).

Exemplo de Uso

Vamos exemplificar o processo de implementação de um sistema externo utilizando o Hydra, ele não será detalhado e nem excessivamente técnico, pois tem o objetivo de transmitir a ideia geral do componente e servir como guia inicial para novos desenvolvedores.

Precisamos integrar nosso sistema com o de um cliente, é o Sistema Clavell de Pagamentos, e a integração funcionará da seguinte forma:

  • Toda vez que um título for vendido, é necessário enviar uma mensagem ao Clavell avisando, o pedido só será liberado após confirmação do nosso sistema legado
  • Quando recebermos uma confirmação, a venda será aprovada e processada normalmente

Cadastrando o Sistema

Antes de tudo é necessário informar para o Hydra que nosso sistema se comunicará com um legado chamado Clavell, para isto utilizamos postscript:

<service name="HydraSystem" action="INCLUIR">
  <param name="Database ID">1</param>
  <param name="Identificador">$clavell</param>
  <param name="Mnemônico">CLAVELL</param>
</service>

Cadastrando as Ativações

Agora é necessário cadastrar as formas de ativação do nosso sistema:

<service name="HydraActivation" action="INCLUIR">
  <param name="Database ID">1000</param>
  <param name="Sistema">$clavell</param>
  <param name="Mnemônico">CLAVELL</param>
  <param name="Script">CLAVELL_ACTIVATION</param>
</service>

<service name="HydraActivation" action="INCLUIR">
  <param name="Database ID">1001</param>
  <param name="Sistema">$clavell</param>
  <param name="Mnemônico">CLAVELL</param>
  <param name="Script">CONFIRMACAO_ACTIVATION</param>
</service>

Repare que no cadastro do nosso HydraActivation nós informamos que ele deve usar o script CLAVELL_ACTIVATION, este script receberá a solicitação de mensagem e decidirá o que fazer com ele. Da mesma forma quando enviarmos uma mensagem, ela será tratada pelo script CONFIRMACAO_ACTIVATION;

Especificações

Para o nosso exemplo, só teremos duas especificações disponíveis:

<service name="HydraSpecification" action="INCLUIR">
  <param name="Ação">SOLICITACAO DE COMPRA</param>
  <param name="Database ID">2001</param>
  <param name="Decode Script"></param>
  <param name="Encode Script">COMPRA01_ENCODE</param>
  <param name="Sender">$clavellSender</param>
  <param name="Sistema">$clavell</param>
  <param name="Template">COMPRA01_TEMPLATE</param>
</service>

<service name="HydraSpecification" action="INCLUIR">
  <param name="Ação">CONFIRMACAO DE COMPRA</param>
  <param name="Database ID">2002</param>
  <param name="Decode Script">COMPRA01_DECODE</param>
  <param name="Encode Script"></param>
  <param name="Sender"></param>
  <param name="Sistema">$clavell</param>
  <param name="Template"></param>
</service>

Note que informamos todos os scripts que devem ser utilizados por cada especificação:

  • COMPRA01_ENCODE: carregará todo o contexto para montagem da nossa mensagem, neste caso carregará todas as informações necessárias para colocarmos no arquivo enviado ao Clavell a solicitação de venda
  • COMPRA01_DECODE: quando o legado autorizar ou negar uma compra ele o fará através de arquivos via Sistema de Arquivos, quando isto for feito, uma requisição será disparada para o Hydra e este script será o responsável pela leitura do arquivo recebido e chamada aos serviços que vão autorizar a venda
  • COMPRA01_TEMPLATE: uma vez em posse do contexto da mensagem, formatará estas informações para envio. Neste caso, vai montar um XML com informações sobre a venda

Senders

A especificação “SOLICITACAO DE COMPRA” está usando um “Sender” que ainda não definimos:

<service name="FileSenderRegistry" action="INCLUIR">
  <param name="Caminho">/srv/ftp/clavell/send</param>
  <param name="Database ID">2002</param>
  <param name="Extensão">xml</param>
  <param name="Identificador">$clavellSender</param>
  <param name="Mnemônico">FILESENDER</param>
</service>

Note também que FILESENDER é um dos scripts que estão já disponíveis no Hydra, ele vai simplesmente pegar o conteúdo da mensagem e escrever em um arquivo com os parâmetros fornecidos.

Recebendo Mensagens

Nossa integração se dará por troca de arquivos, então toda vez que o sistema Clavell disponibilizar algo, entenderemos que recebemos uma mensagem. Para isto usamos o DirectoryChangedListener, uma das classes que o próprio Hydra nos oferece (ele também fornece a classe HydraMessageListener para lidar com MQs), toda vez que um arquivo novo for encontrado o sistema disparará um request para o Hydra tratar a mensagem. É neste momento que o script COMPRA01_DECODE será executado e transformará a mensagem em uma chamada de serviço com a liberação da venda

Enviando Mensagens

Para solicitar envios de mensagem, basta realizar uma chamada ao HydraController.send(), ele criará um request, montará a mensagem e a transmitirá, disponibilizando um arquivo na pasta indicada ao Sender.

Atrelando Conversas

Só com isto já temos o Hydra funcionando, mas há casos em que é necessário atrelar as Conversas geradas a alguma entidade do negócio, por exemplo, queremos anexar a confirmação de venda à ordem de venda emitida por um usuário. Neste caso fica a nosso cargo criar as entidades ou relacionamentos necessários para isto, ao chamar o método send nós recebemos um HydraRequest, e com ele conseguimos todas as informações necessárias.

O que falta?

Pronto, temos um sistema integrado, mas faltou algo muito importante: cadê os testes?

É importante que os desenvolvedores testem cada parte de seu sistema, isso é a garantia que realmente está funcionando e que sua manutenção não será traumática. O Hydra é estruturado de forma que seja possível testar cada componente, os scripts são a parte central de sua integração e testá-los unitariamente é possível (e extremamente recomendável) fazendo uso da classe TransientScriptRepository (disponível no pacote script-persistence), com ele é possível carregar e executar qualquer script sem a necessidade de preparar banco de dados ou bean factory.

Além disto, também é possível realizar um teste geral do sistema substituindo somente o sistema legado, simulando suas respostas e garantindo que tudo funcione em cenários controlados.