Comunicação entre componentes distribuídos por mensagens assíncronas com MDB

Após um tempo estudando Enterprise JavaBeans (EJB’s) para um projeto em que estava participando, percebi que estava confuso em relação ao conceito do tipo de ambiente(arquitetura) que o Beans de Sessão(Sessions Beans) são utilizados, pois cheguei a seguinte situação; queria que meu cliente acessasse por JNDI serviços registrados em outro servidor remoto e esses me devolviam informações(objetos) de um sistema heterogêneo , sendo que o mesmo estava em uma outra rede de uma filial da empresa, interligadas por uma WAN, ou seja, queria uma interação direta e síncrona entre meus componentes. Mas essa solução não é adequada por uma serie de condições adversas tais como: Link esta fora, servidor remoto parar no meio de uma transação, pico de luz e etc. A não ser que meu cliente espere longos 30min para receber apenas um timeout como resposta de uma conexão falha, nem mesmo quando pode voltar a estabelecer uma nova conexão com esse servidor. Então, como sair dessa situação? Depois de muito queimar a ‘cuca‘, encontramos a resposta na seguinte solução:

Invocar serviços através mensagens assíncronas, monitoradas por um tipo de especial de EJB denominado Message Driven Bean (MDB). Antes de começar explicar, vou explanar alguns conceitos importantes da solução apresentada:

  • MDB: São beans consumidores de JMS dentro do container JEE.
  • Queue: Filas de mensagens onde só vai ser consumida por um único MDB.
  • Producer: Produtor de mensagens para um Provider JMS.
  • Consumer: Recebe as mensagens de uma Queue que esta ‘escutando’.
  • Provider: Ambiente responsável pela organização e entrega de JMS.

O Conceito do funcionamento de uma JMS Application pode ser muito bem ilustrada na figura abaixo:

Isso nos trouxe mais confiança à comunicação entre nossos componentes distribuídos, pois não temos que nos preocupar em “busca coisas” em serviços de um servidor remoto, pois ele se encarrega de enviá-los através de um Producer construído somente para empilhar mensagens em uma Queue, escutada pelo nosso Consumer em um servidor local. O processando das mensagens é forma ordenada e durável, ou seja, somente sai da fila quando for realmente processada na ordem de chegada. Então a disposição de comunicação de nossos componentes ficou da seguinte forma:

A grande sacada foi como um MDB acessa uma Queue remota e fazer com que minhas mensagens sejam consistentes o bastante para garantirem a entrega no meu Consumer. Para isso foi feito algumas configurações no JBoss(no meu caso v.405), primeiramente foi adicionado mais um mbean(Managed Bean) em <$JBOSS_HOME/server/<your-configuration>/deploy/jms/jms-ds.xml, que defini um Provider remoto (que pode ser gerenciado via jmx-console). Lembrando esta alteração é no container em que o MDB esta rodando. Por padrão todos os MDBs acessam o DefaultJMSProvider também declarado no arquivo como Provider.

<mbean code=“org.jboss.jms.jndi.JMSProviderLoader”

name=“jboss.mq:service=JMSProviderLoader,name=RemoteJMSProvider,server=remotehost”>

<attribute name=“ProviderName”>RemoteJMSProvider</attribute>

<attribute name=“ProviderAdapterClass”>org.jboss.jms.jndi.JNDIProviderAdapter</attribute>

<!– The connection factory –>

<attribute name=“FactoryRef”>UIL2XAConnectionFactory</attribute>

<!– The queue connection factory –>

<attribute name=“QueueFactoryRef”>UIL2XAConnectionFactory</attribute>

<!– The topic factory –>

<attribute name=“TopicFactoryRef”>UIL2XAConnectionFactory</attribute>

<!– Connect to JNDI on the host “the-remote-host-name” port 1099–>

<attribute name=“Properties”>

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.factory.url.pkgs=org.jnp.interfaces

java.naming.provider.url=the-remote-host-name:1099

</attribute>

</mbean>

Troque “the-remote-host-name” para o IP do servidor que a Queue se encontra. E para fazer com que o MDB consuma de um provider remoto é mais fácil ainda:

@MessageDriven(activateConfig =
{
@ActivationConfigProperty(propertyName=”destinationType”, propertyValue=”javax.jms.Queue”),
@ActivationConfigProperty(propertyName=”destination”, propertyValue=”queue/testQueue”),
@ActivationConfigProperty(propertyName=”providerAdapterJNDI”, propertyValue=”java:/RemoteJMSProvider”)
})
public class MDB implements MessageListener
{

}

Agora para garantir com que as mensagens fossem persistentes. Definimos o envio do nosso Producer maneira persistente:


QueueSender sender = session.createSender(myQueue);
Message message = session.createTextMessage(”hello”);
int priority = 4;
sender.send(message, DeliveryMode.PERSISTENT, priority, 0);

Fazendo isto, garantimos a entrega da mensagem para o MDB pelo menos uma vez após uma exceção, se tornar a persistir, a mensagem é levada para o DLQ (ou mais conhecida como “lixão”), mas para que isso não ocorra você pode indicar que não quer tratamento de DLQ utilizando useDQL, desta forma, sempre ira tentar entregar a mensagem sem retirar da Queue enquanto houver exceção. Outra configuração que pode fazer também é numero de vezes que ele vai tentar entregar antes de mandar para DLQ o DLQMaxResent. A configuração do MDB pode ficar da seguinte forma:


@MessageDriven(activateConfig =
{
@ActivationConfigProperty(propertyName=”destinationType”, propertyValue=”javax.jms.Queue”),
@ActivationConfigProperty(propertyName=”destination”, propertyValue=”queue/testQueue”),
@ActivationConfigProperty(propertyName=”useDLQ”, propertyValue=”true”),
@ActivationConfigProperty(propertyName=”DLQMaxResent”, propertyValue=”100″),
@ActivationConfigProperty(propertyName=”providerAdapterJNDI”, propertyValue=”java:/RemoteJMSProvider”)
})
public class MDB implements MessageListener
{

}

Fiquei muito satisfeito com a facilidade de criação de aplicações desse tipo e ainda existe uma serie de configurações que podem ser feitas customizando a utilização de um MDB aumentando ainda mais a escalabilidade de sistemas, pois de uma solução JMS não se resume apenas apresentação unilateral de comunicação entre componentes, mais de uma interação substancial de processos definidos em uma margem de requisitos do funcionamento do sistema como um todo, tornando-o como uma ferramenta essencial na aplicação de grandes projetos.

Bom, vou ficando por aqui espero ter colaborado da alguma forma para o entendimento de aplicações JMS com MDB boa sorte e ate à próxima.

0 Respostas para “Comunicação entre componentes distribuídos por mensagens assíncronas com MDB”


  1. Não Há Comentários

Deixe um comentário