26
  Enterprise JavaBeans 3.0 Parte 4: Message Driven Bean < Por: R Por: R Por: R Por: Rafael Zancan Frantz afael Zancan Frantz afael Zancan Frantz afael Zancan Frantz > ATENÇ O: Este materia l contém algumas image ns retirar das da doco mentaç ão oficial da SUN e adaptadas para este material. As mesmas podem ser encontradas no site www.sun.com . O objetivo deste material é recompilar uma série de informações existentes que possam ser utilizadas para o estudo da tecnologia EJB 3.0 pelo leitor. No final se listam as bibliografias utilizadas e sugerimos que as mesmas sejam utilizadas para aprofundar os conhecimentos nesta tecnologia.

Parte 4 Message Driven Bean

Embed Size (px)

Citation preview

Page 1: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 1/26

 

EnterpriseJavaBeans 3.0

Parte 4: Message Driven Bean

< Por: R Por: R Por: R Por: Rafael Zancan Frantzafael Zancan Frantzafael Zancan Frantzafael Zancan Frantz > 

ATENÇÃO: Este material contém algumas imagens retirardas da docomentação oficial da SUN eadaptadas para este material. As mesmas podem ser encontradas no site www.sun.com . O objetivodeste material é recompilar uma série de informações existentes que possam ser utilizadas para oestudo da tecnologia EJB 3.0 pelo leitor. No final se listam as bibliografias utilizadas e sugerimosque as mesmas sejam utilizadas para aprofundar os conhecimentos nesta tecnologia.

Page 2: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 2/26

O que é um Message Driven BeanO que é um Message Driven BeanO que é um Message Driven BeanO que é um Message Driven Bean

 Antes da versão 2.0 da especificação EJB a maioria dos consumidores de mensagensJMS (Java Message Service) foram construídos como simples programas Java fora do

container J2EE. Um programa Java era ativado e conectado a um destinatário JMS e ficavaesperando as mensagens. Embora a construção de consumidores de mensagens por meio deaplicações Java era uma das melhores soluções para o problema, esta solução gerava váriosoutros problemas, onde o maior é a escalabilidade. Quando o número de mensagens na filaaumentava consideravelmente, haveria a necessidade de se executar um programa Javamulti-threads para promover a escalabilidade da leitura destas mensagens e se este volumevariasse muito, ficaria difícil fazer um algoritmo que na medida exata consumiria asmensagens sem perda de performance com muitas threads e sem perda destas mensagensno caso de poucas threads.

Baseado nisto alguns vendedores de EJB pensaram nesta funcionalidade na versão1.1. Porém a especificação não definia este tipo de bean o que fazia com que cadavendedor tivesse um padrão.

Basicamente, beans orientados a mensagens processam alguma lógica de negóciosusando mensagens JMS enviadas para uma destinação particular, ou seja, consomemmensagens JMS através da tecnologia EJB.

 Atualmente a partir da versão 3.0 do EJB JMS pode fazer uso de anotações assimcomo os outros tipos de EJBs para facilitar a sua escrita. Mesmo tendo sido incorporado aespecificação de EJB nas versões passadas e não demandando a criação de interfaces homenem remotas ( o que os deixava mais simples de serem escritos) ainda era trabalhosoescrever um Message Driven Bean. Anotações, como já comentado, a partir da versão 3.0

da especificação facilitam mais este processo.

Os Message Driven Beans são completamente escondidos do cliente. O único meiode clientes comunicarem com os beans orientados a mensagens é enviando uma mensagempara um destinatário JMS. Veja a figura abaixo:

Figura 4-1: Funcionamento do Bean orientado a mensagens com os clientes

Page 3: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 3/26

Como podemos ver na figura acima, um cliente envia uma mensagem JMS para umdestino e o container passa esta mensagem JMS para uma instância do bean orientado amensagens que tem se registrado como um receptor de mensagens para uma destinaçãoparticular. Por usar um pool de instância de beans, o container é capaz de manipular asmensagens que chegam de uma forma muito mais eficiente e aumenta a escalabilidade dasoperações JMS. As instâncias dos beans podem ser colocadas ou retiradas do pooldependendo das necessidades do container de atender as requisições.

Os beans orientados a mensagens não possuem estado conversacional e portanto,são similares neste aspecto aos beans de sessão stateless. Isto não significa que estes beansnão podem ter variáveis de instância, somente significa que as variáveis de instância que osbeans possuírem não podem ser usadas para guardar informações de estado de um clienteparticular porque não é garantido que um mesmo bean atenda um mesmo cliente. Isto atécerto ponto é obvio porque o cliente não acessa diretamente um bean orientado amensagens. Um exemplo interessante seria quando definimos uma peça de teatro comosendo o bean de sessão, os atores o bean de entidade, e poderíamos definir os beansorientados a mensagens como aqueles scripts que ficam invisíveis ao público, não havendoiteração direta. Apagar e acender as luzes quando o ator principal chega (pela primeira vez),

seria análogo a quando chegar uma mensagem ao destino JMS, o qual processa a mesma.

Por assegurar que todas as instâncias dos beans orientados a mensagens sãoidênticas, o container é capaz de manipular um pequeno número de instâncias no pool eainda manipular uma grande carga de chamadas. Isto é porque qualquer instância livrepode ser usada para manipular qualquer requisição que chegar vindo de uma destinaçãoespecífica.

 A partir da criação do bean orientado a mensagens até a sua destruição, o container gerencia estes beans exclusivamente. Todos os serviços oferecidos para os outros dois beans(sessão e entidade), tais como segurança, suporte a transação e concorrência são, exceto as

interfaces home e remote, providos.O container interage com os beans orientados a mensagens através de um conjunto

de métodos de callback  que são implementados pelo bean orientado a mensagens. Estesmétodos são similares aos usados pelos beans de sessão e os beans de entidade. Estesmétodos avisam ao bean que determinados eventos ocorrem ou ocorreram.

Um Message Driven Bean (MDB) é, portanto, um EJB que permite que as aplicaçõesJ2EE processem mensagens de modo assíncrono. Age como um listener de mensagens JavaMessage Service (JMS), o qual é similar a um ouvinte de eventos, a não ser pelo fato de que,ao invés de receber eventos, ele recebe mensagens. As mensagens podem ser emitidas por qualquer componente de J2EE - um cliente da aplicação, um outro EJB, ou um componenteWEB -- ou por uma aplicação/sistema JMS que não usem a tecnologia J2EE.

Os MDBs atualmente processam somente mensagens de JMS, mas no futuro podemser usados para processar outros tipos de mensagens.

Page 4: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 4/26

Diferença entre MDB, Session e Entity BeanDiferença entre MDB, Session e Entity BeanDiferença entre MDB, Session e Entity BeanDiferença entre MDB, Session e Entity Bean

 A diferença mais visível entre EJBs MDB e outros EJBs é que os clientes não acessamos MDBs através das interfaces. Ao contrário de um EJB session ou entity, um MDB temsomente a classe bean.

Em diversos aspectos, um MDB assemelha-se a um EJB Session Stateless

1.  As instâncias de um MDB não retêm nenhum dado ou estado de conversação comum cliente específico.

2.  Todas as instâncias de um MDB são equivalente, permitindo que o container EJBatribua uma mensagem a toda instância de um MDB. O recipiente pode realizar umpool destes objetos para permitir que os fluxos das mensagens sejam processadossimultaneamente.

3.  Um único MDB pode processar mensagens de múltiplos clientes.

 As variáveis de instância do MDB podem manter o estado através da manipulação demensagens do cliente – por exemplo, uma conexão JMS, uma conexão com a base dedados, ou uma referência a um objeto EJB.

Quando uma mensagem chega, o container chama o método onMessage() do MDBpara processar a mensagem. O método onMessage() realiza normalmente um cast damensagem para um dos cinco tipos de mensagem JMS e manipula a mensagem de acordocom a lógica do negócio da aplicação. O método onMessage() pode chamar métodos

auxiliares (Helpers), ou pode invocar um Session Bean (muito recomendado nesse caso) ouum Entity Bean para processar a informação contida na mensagem ou para armazená-la emuma base de dados.

Uma mensagem pode ser entregue a um MDB dentro de um contexto da transação,de modo que todas as operações dentro do método onMessage() sejam parte de uma únicatransação. Se ao processar a mensagem for executado um roolback, a mensagem irá ser novamente enviada.

Page 5: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 5/26

Escrevendo um MDBEscrevendo um MDBEscrevendo um MDBEscrevendo um MDB

 Aqui vamos escrever um Message Driven Bean, porém antes em poucas linhas vamosentender alguns conceitos importantes para este estudo.

 Aplicações que utilizam JMS são chamadas de JMS Clients JMS Clients JMS Clients JMS Clients, e o sistema de mensagensque realiza o roteamento e entrega de mensagens é chamado de   JMS Provider  JMS Provider   JMS Provider  JMS Provider . Uma  JMS JMS JMS JMS

 Application Application Application Application é um sistema composto por muitos JMS Clients e, geralmente, um JMS Provider.Um JMS Client que manda mensagens é chamado de producer  producer  producer  producer , e um JMS Client que recebeuma mensagem é chamado de consumer consumer consumer consumer.... Um JMS Client pode ser ao mesmo tempo umproducer e um consumer!

 Vamos agora ver um exemplo de Message Driven Bean:

package com.ejb.mdb;

import javax.ejb.MessageDriven;import javax.jms.Message;

import javax.jms.MessageListener;

@MessageDriven

public class ExemploMDB implements MessageListener {

public void onMessage(Message message) {

...

}

}

Código 4-1: MDB simples 

Observe acima que um MDB é definido através do uso de anotações. Nesta caso éutilizada a anotação @javax.ejb.MessageDriven para anotar a classe com um MDB. TodoMDB implementa a interface javax.jms.MessageListener o que obrigará o desenvolvedor aimplementar o método onMessage() para tratar o recebimento de mensagens de um client

 producer. O código a ser executado quando o MDB receber uma mensagem é posto nométodo onMessage(). 

Um EJB pode ser um consumidor de mensagens assíncronas como o mostrado noexemplo acima ou pode ser um produtor de mensagens para que clientes JMS as recebam.

Mais adiante mostraremos como fazer isto.Todo MDB deve estar “escutando” uma fila de mensagens (QQQQueueueueueueueue) ou estar inscrito

para receber mensagens de um TTTTopicopicopicopic.

Page 6: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 6/26

TTTTopicopicopicopic

Topic é um modelo de mensagens JMS baseado na “filosofia” publish-and-subscribe.Este modelo também é conhecido com “um para muitos”. Aqui uma mensagem JMS será

enviada para um Topic do container EJB e este irá imediatamente realizar um envio de umacópia desta mensagem para todos aqueles clientes que estiverem inscritos para receber mensagens daquele tópico. Funciona semelhante a um broadcast de mensagens. Veja afigura abaixo:

Figura 4-2: Tópico MDB para EJB 

Observe na figura acima que todos os MDBs que estiverem inscritos para receber mensagens do tópico irão receber. Abaixo um código que cria um MDB para receber mensagens de um tópico:

Page 7: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 7/26

QueueQueueQueueQueue

Este modelo JMS baseado em fila (queue) permitirá um cliente enviar mensagenspara a fila de forma que outros possam consumir as mensagens da fila. Uma diferença

importante com relação ao modelo topic é que a mensagem de uma fila será consumidaapenas por um cliente e não distribuída para todos os inscritos como acontece com umtopic. Abaixo veja como fica o modelo de um queue:

Figura 4-3: Queue MDB para EJB 

Observe que somente um MDB irá consumir a mensagem. Todas asmensagens enviadas por clientes ficam na Fila aguardando alguém que as consuma. A 

decisão de qual modelo utilizar na sua aplicação irá depender em cada caso do que precisaser representado com JMS. O modelo de Queue garante que somente um cliente iráprocessar a mensagem recebida. É muitas vezes conhecido portanto com pier-to-pier (P2P).

Page 8: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 8/26

JMS Client ProducerJMS Client ProducerJMS Client ProducerJMS Client Producer

Um client epode gerar uma mensagem e enviar esta mensagem para um topic ouqueue. Veja abaixo o código onde um cliente standalone produz uma mensagem de texto e

a envia para um topic do container EJB. As mensagens pode ser de outro tipo e não somentetextuais. Podem ser mensagens contendo objetos java (java.lang.Object).

public class JMSTopicSendClient {

public static void main(String[] args) {

try {

InitialContext ctx = getInitialContext();

Topic topic = (Topic) ctx.lookup("topic/testTopic");

// Enviar mensagem para um TOPICTopicConnectionFactory factory = (TopicConnectionFactory)

ctx.lookup("TopicConnectionFactory");

TopicConnection connection = factory.createTopicConnection();

TopicSession session = connection.createTopicSession( false,

QueueSession.AUTO_ACKNOWLEDGE);

MessageProducer producer = session.createProducer(topic);

TextMessage textMsg = session.createTextMessage();

textMsg.setText("Olá clientes do topic! ");

producer.send(textMsg);

connection.start();

connection.close();

System.out.println("Mensagem enviada para topic:

"+topic.getTopicName()+ " pelo client!");

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

Código 4-2: Cliente JMS para Topic 

Observe que o programa acima envia uma mensagem para um tópico de nome“topic/testTopic” do container EJB. Para realizar este envio são necessários alguns objetos osquais são apresentados abaixo:

 javax.jms.MessageProducer

Interface utilizada para representar um objeto com o qual é possível enviar mensagenspara um determinado tópico. Observe que ao criar o MessageProducer é passado o tópicocorrespondente.

Page 9: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 9/26

 

 javax.jms.TopicSession

Interface utilizada para representar a sessão do cliente com o tópico no container EJB.Esta sessão é semelhante as sessões web que estamos acostumados.

 javax.jms.TextMessage

Mensagem textual criada através de um objeto session e que pode ser populada comstrings para ser enviada pelo MessageProducer para o topic.

 javax.jms.Topic

Representa o topico retornado pelo lookup no JNDI ENC.

 javax.jms.TopicConnection

Conexão com o topic do container. Esta conexão é utilizada para criar a sessão com otópico.

 javax.jms.TopicConnectionFactory 

Fábrica de tópicos utilizada para criar TopicConnection. Esta fabrica de tópicos éretornado através de um lookup no JNDI ENC do container.

Page 10: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 10/26

@MessageDriven e @ActivationConfigProperty

 Ao definir um Message Driven Bean com a anotação @MessageDrivern é necessáriofornecer mais algumas informações sobre este bean. O bean que esta sendo definido precisasaber se será um listener de um Topic ou Queue. Isto é feito através da anotação@ActivationConfigProperty.  Abaixo um código que mostra como isto pode ser feito.

package com.ejb.mdb;

import javax.ejb.ActivationConfigProperty;

import javax.ejb.MessageDriven;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageListener;

import javax.jms.TextMessage;

@MessageDriven(activationConfig = {@ActivationConfigProperty(propertyName="acknowledgeMode",

propertyValue="Auto-acknowledge"),

@ActivationConfigProperty(propertyName="destinationType",

 propertyValue="javax.jms.Topic"),@ActivationConfigProperty(propertyName="destination",

 propertyValue="topic/testTopic"),

@ActivationConfigProperty(propertyName=

connectionFactoryJndiName",

propertyValue="TopicConnectionFactory")

}

)

public class MDBTopicSample implements MessageListener {

public void onMessage(Message message) {

try {

System.out.println("Message Driven Bean-Topic-[ onMessage() ] ...");

TextMessage textMsg = (TextMessage)message;

System.out.println("Message: "+ textMsg.getText() );

} catch (JMSException ex) {

System.out.println("Erro ao pegar a mensagem: "+ex.getMessage() );

}

}

}

Código 4-3: EJB MDB tratando mensagens 

Observe acima que o atributo activationConfig() de @MessageDriven recebe umarray de anotações @ActivationConfigProperty. Estas anotações são um par de nome/valor que descrevem a configuração do MDB.

 Acknowled Acknowled Acknowled  Acknowledge modege modege modege mode é utilizado pelos clientes que recebem a mensagem paracomunicar o JMS provider de que a mensagem foi recebida e processada. Caso não sejacomunicado o provider isto poderá fazer com que o mesmo reenvie a mensagem fazendoassim com que o cliente receba duas ou mais vezes a mesma mensagem. Acknowledgemode aceita dois possíveis valores: Auto-acknowledge e Dups-ok-acknowledge. Auto Auto Auto Auto----

Page 11: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 11/26

acknowledgeacknowledgeacknowledgeacknowledge irá fazer com que o cliente mande o aviso de recebimento da mensagem parao provider logo após o MDB ter recebido a mensagem para processar. DupsDupsDupsDups----ok ok ok ok----acknowledgeacknowledgeacknowledgeacknowledgefará com que o container não precise mandar o aviso de recebimento imediantamente apósreceber a mensagem. O aviso poderá ser enviado a qualquer momento após ter dado aoMDB a mensagem. Isto pode faze com que o provider assuma que a mensagem não foirecebida e a envie novamente. O uso de Dups-ok-acknowledge faz com que a rede sejapoupada e tenha um menor trafego. Mas na prática o consumo de rede é tão pequeno

tornando o Dups-ok-acknowledge não muito utilizado.

DestinationDestinationDestinationDestination ttttypeypeypeype é, como o próprio nome já sugere o tipo de JMS de destino. Nestecaso podemos espeficicar se será topic ou queue com os respectivos valores: javax.jms.Topic ou javax.jms.Queue.

DestinationDestinationDestinationDestination representa o nome do topic ou queue registrado no container EJB. Noexemplo acima utilizamos um topic já registrado no JBoss, o topic/testTopic.

Connection Factory Jndi NameConnection Factory Jndi NameConnection Factory Jndi NameConnection Factory Jndi Name especifica o nome da fábrica que será utilizada para acriação de topic ou queue. No exemplo acima utilizamos um connection factory para topicchamado TopicConnectionFactory.

Outro @ActivationConfigProperty que pode ser utilizado em alguns casos é o“Subscription Durability Subscription Durability Subscription Durability Subscription Durability”. Este atributo é utilizado com topic e serve para dizer se asmensagens enviadas para o tópico serão duráveis ou não. Em caso de serem duráveis(Durable) se o EJB contatiner sofre alguma falha como por exemplo reiniciar ou desconectar do JMS provider, as mensagens enviadas para o provider não serão perdidas pois serãosalvas pelo JMS provider até que o EJB container volte a fncionar. Quando o container voltar e reconectar ao provider então as mensagens são enviadas para o container e este as enviapara os MDBs. A outra possibilidade que temos é não armazenar as mensagens comomensagens duráveis ( NonDurable). Isto deixa levemetne mais rápido o JMS provider, masdiminui a sua confiabilidade. Veja abaixo como definir este atributo.

@MessageDriven( activationConfig = {

@ActivationConfigProperty(

propertyName="subscriptionDurability",

propertyValue="Durable"

)

}

)

public class MDBTopicSample implements MessageListener {

...

}

Código 4-4: Configurando um MDB com anotações 

Page 12: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 12/26

EJB como JMS producerEJB como JMS producerEJB como JMS producerEJB como JMS producer

Um EJB Session também pode ser um produtor de mensagens para um topic. Nestecaso o EJB ao executar deve criar uma sessão com o topic e enviar a ele uma mensagem.

Nos exemplo que havíamos mostrdo até então era um cliente standalone que enviavamensagens para o topic e como inscritos para o topic tínhamos MDBs. Abaixo mostramos ocódigo de um EJB Session que envia uma mensagem para um topic.

@Stateless

public class TopicProducerEJB implements TopicProducerRemote {

@Resource(mappedName="TopicConnectionFactory")

private TopicConnectionFactory connectionFactory;

@Resource(mappedName="topic/testTopic")

private Topic topic;

public void logar(String nome) {try {

// Enviar mensagem para um TOPIC

TopicConnection connect = connectionFactory.createTopicConnection();

TopicSession session = connect.createTopicSession(true, 0 );

MessageProducer producer = session.createProducer(topic);

TextMessage textMsg = session.createTextMessage();

textMsg.setText(nome+" logou no sistema!! ");

producer.send(textMsg);

connect.start();

connect.close();

System.out.println("Mensagem enviada para topic:"+topic.getTopicName() );

} catch (JMSException ex) {

ex.printStackTrace();

}

}

}

Código 4-5: EJB podutor de mensagens 

Observe no código acima como um EJB pode receber através de anotações uma

referência para o TopicConnectionFactory e para o Topic. Utilizando a anotaçã[email protected], injetamos no EJB as referências. O código que temos dentrodo MDB é um método definido nas interfaces deste EJB para que ao ser chamadoremotamente possa produzir uma mensagem e enviar a mesma ao topic.

Como invertemos os papéis e criamos acima um EJB para produzir uma mensagem eenviar ao topic, vamos agora ver como podemos escrever um cliente que standalone queatravés de JMS possa consumir mensagens de um topic. Abaixo o código que realiza estatarefa:

Page 13: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 13/26

 public class JMSTopicClient implements MessageListener {

public JMSTopicClient() {

try {

InitialContext ctx = getInitialContext();

Topic topic = (Topic)ctx.lookup("topic/testTopic");

TopicConnectionFactory factory = (TopicConnectionFactory)ctx.lookup("TopicConnectionFactory");

TopicConnection connect = factory.createTopicConnection();

TopicSession session = connect.createTopicSession( false,

Session.AUTO_ACKNOWLEDGE );

 MessageConsumer consumer = session.createConsumer( topic );

consumer.setMessageListener(this);

connect.start();

} catch (Exception ex) {

ex.printStackTrace();

}

}

public void onMessage(Message message) {

try {

TextMessage textMsg = (TextMessage)message;

String text = textMsg.getText();

System.out.println("Mensagem recebida: "+ text );

} catch (JMSException ex) {

ex.printStackTrace();

}

}

}

Código 4-6: Cliente EJB MDB 

  A classe acima define um cliente que pode ser executado em outra JVM que nãodentro de um EJB Container. Observe que esta classe implementa a interfaceMessageListener o que fará com que na classe tenhamos método onMessage(Message

message) e então quando uma mensagem chegar o mesmo ser executado.

Observe que através da sessão criamos um MessageConsumer que é um objeto pararegistrar um listener (assim como fazíamos no curso de Java Avançado para as interfacesgráficas) que tratará com o método onMessage() o recebimento da mensagem. Lembre-seque podemos ter vários clientes consumidores registrados/inscritos a um topic.

Page 14: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 14/26

Um client producer para um Q Um client producer para um Q Um client producer para um Q Um client producer para um Queueueueueueueue

  Agora veremos como é possível um cliente produzir uma mensagem e enviar parauma fila de um JMS provider. Veja o código abaixo:

public class JMSQueueSendClient {

public static void main(String[] args) {

try {

InitialContext ctx = getInitialContext();

Queue queue = (Queue) ctx.lookup("queue/MyQueue");

QueueConnectionFactory factory = (QueueConnectionFactory)

ctx.lookup("QueueConnectionFactory");

QueueConnection connection = factory.createQueueConnection();

QueueSession session = connection.createQueueSession( false,

QueueSession.AUTO_ACKNOWLEDGE);

TextMessage msg = session.createTextMessage(" Olá fila queue! ");

QueueSender sender = session.createSender(queue);

sender.send(msg);

connection.close();

System.out.println("Mensagem enviada para queue:

"+queue.getQueueName()+ " pelo client!");

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

Código 4-7: Cliente standalone para queue 

Observe que no código acima é feito um lookup na queue/MyQueue para ter acesso afila e poder enviar mensagens.

Page 15: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 15/26

CicloCicloCicloCiclo de vida de um MDBde vida de um MDBde vida de um MDBde vida de um MDB

Os beans orientados a mensagens são normalmente criados quando ocontainer inicializa. O descritor de configuração pode dar ao publicador ou o assembler dobean a habilidade para especificar quantos beans orientados a mensagens estarãodisponíveis na inicialização e também qual é o máximo de beans que podem ser criados. Éfunção do container garantir que as instâncias do bean no pool estarão disponíveis antes dasmensagens JMS chegarem.

O container primeiro chama um construtor com nenhum argumento para o bean,construtor default, logo em seguinda serão injetadas as anotações. Após isto o container chama o método anotado com @javax.annotation.PostConstruct na instância do beanrecém criado. Neste ponto pode-se colocar códigos de inicialização se seu bean necessita dedeterminados recursos para completar a lógica de negócios. Estes recursos poderiam ser uma sessão Java Mail ou uma conexão JDBC. O nome do método não é importante, uma

vez que a anotação é que dará o sentido do método.

 A figura abaixo ilustra os estágios do ciclo de vida de um message-driven bean. O EJBcontainer frequentemente cria um pool de instâncias de message-driven beans. Para cadainstância, o EJB container instancia o bean e faz as seguintes tarefas:

1-  Chama o método construtor 2-  Injeta as anotações se houverem3-  Chama o método anotado com @javax.annotation.PostConstruct 

4-  Chama o método onMessage() 

Figura 4-4: Ciclo de vida para um Message-Driven Bean

Como um stateless session bean, um message-driven bean não é nunca colocado noestado de passivo, e possui somente os estados mostradoa acima: não existente e prontopara receber mensagens.

Page 16: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 16/26

No final do ciclo de vida, o container chama o método anotado [email protected]. A instância do bean está então pronta para ser coletadapelo garbage collector. 

 Abaixo mostramos um exemplo completo de um Message Driven Bean inscrito paraum topic contendo os métodos do ciclo de vida.

package com.ejb.mdb;

import javax.annotation.PostConstruct;

import javax.annotation.PreDestroy;

import javax.ejb.ActivationConfigProperty;

import javax.ejb.MessageDriven;

import javax.jms.Message;

import javax.jms.MessageListener;

@MessageDriven(mappedName = "jms/MDBCicloVida",

activationConfig = {

@ActivationConfigProperty(propertyName = "acknowledgeMode",

propertyValue = "Auto-acknowledge"),

@ActivationConfigProperty(propertyName = "destinationType",

propertyValue = "javax.jms.Topic"),

@ActivationConfigProperty(propertyName = "subscriptionDurability",

propertyValue = "Durable"),

@ActivationConfigProperty(propertyName = "destination",

propertyValue = "topic/testTopic"),

@ActivationConfigProperty(propertyName = "connectionFactoryJndiName",

propertyValue = "TopicConnectionFactory")

}

)

public class MDBCicloVida implements MessageListener {

public MDBCicloVida() {

}

public void onMessage(Message message) {

System.out.println("onMessage() do MDBCicloVida executado!");

}

// Métodos do ciclo de vida

@PostConstruct

public void initialize() {

System.out.println("MDB criado! @PostConstruct executado! ");

}

@PreDestroy

public void exit() {

System.out.println("MDB será destruido! @PreDestroy executado! ");

}

}

Código 4-8: EJB MDB com ciclo de vida 

Page 17: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 17/26

Quando utilizar um MDB?Quando utilizar um MDB?Quando utilizar um MDB?Quando utilizar um MDB?

Os Session Beans e os Entity Beans permitem que você emita mensagens JMS e asreceba de modo síncrono, mas não assíncrono. Para evitar desperdiçar recursos de servidor,

você pode preferir não usar um bloqueio de execução síncrono em um componente noservidor. Para receber mensagens assíncronas, use um Message-Driven Bean.

Page 18: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 18/26

ExemploExemploExemploExemplo de um EJB MDB para JMS Queuede um EJB MDB para JMS Queuede um EJB MDB para JMS Queuede um EJB MDB para JMS Queue

Nesta sessão vamos mostrar um exemplo completo de um MDB que interage comuma fila Queue. Apresentamos inicialemnte um MDB consumidor de mensagens JMS para

uma Queue, logo em seguida apresentamos um cliente standalone capaz de enviar mensagens para uma Queue que será, então, consumida pelo MDB.

MDB como cliente de uma queue

package com.ejb.mdb;

import javax.ejb.ActivationConfigProperty;

import javax.ejb.MessageDriven;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageListener;

import javax.jms.TextMessage;

@MessageDriven(activationConfig = {

@ActivationConfigProperty(propertyName = "acknowledgeMode",

propertyValue = "Auto-acknowledge"),

@ActivationConfigProperty(propertyName = "destinationType",

propertyValue = "javax.jms.Queue"),

@ActivationConfigProperty(propertyName = "destination",

propertyValue = "queue/MyQueue"),

@ActivationConfigProperty(propertyName = "connectionFactoryJndiName",

propertyValue = "QueueConnectionFactory")

}

)public class MDBQueueSample implements MessageListener {

public void onMessage(Message message) {

try {

System.out.println("MDB - Queue - [ onMessage() ] ...");

TextMessage textMsg = (TextMessage)message;

System.out.println("Message: "+ textMsg.getText() );

} catch (JMSException ex) {

System.out.println("Erro ao pegar a mensagem: "+ex.getMessage() );

}

}

}

Código 4-9: EJB exemplo

O MDB acima é um bean consumidor de mensagens da fila “queue/MyQueue”. Abaixo ocliente que pode enviar mensagens JMS para esta queue:

Page 19: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 19/26

Cliente standalone produtor de mensagens JMS para queue

package com.jms.queue;

import java.util.Properties;

import javax.jms.Queue;

import javax.jms.QueueConnection;import javax.jms.QueueConnectionFactory;

import javax.jms.QueueSender;

import javax.jms.QueueSession;

import javax.jms.TextMessage;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.swing.JOptionPane;

public class JMSQueueSendClient {

public static void main(String[] args) {

try {

InitialContext ctx = getInitialContext();

Queue queue = (Queue) ctx.lookup("queue/MyQueue");

QueueConnectionFactory factory = (QueueConnectionFactory)

ctx.lookup("QueueConnectionFactory");

QueueConnection connection = factory.createQueueConnection();

QueueSession session = connection.createQueueSession( false,

QueueSession.AUTO_ACKNOWLEDGE);

TextMessage msg = session.createTextMessage(" Olá fila queue! ");

QueueSender sender = session.createSender(queue);

sender.send(msg);

connection.close();

System.out.println("Mensagem enviada para queue:

"+queue.getQueueName()+ " pelo client!");

} catch (Exception ex) {

ex.printStackTrace();

}

}

public static InitialContext getInitialContext() throws NamingException {

Properties env = new Properties();

env.put(Context.SECURITY_PRINCIPAL, "guest" );

env.put(Context.SECURITY_CREDENTIALS, "guest" );

env.put(Context.INITIAL_CONTEXT_FACTORY,

"org.jboss.security.jndi.JndiLoginInitialContextFactory");env.put(Context.PROVIDER_URL, "jnp://10.1.1.3:1099");

return new InitialContext(env);

}

}

Código 4-10: Cliente JMS standalone produtor  

Na seqüência apresentamos um cliente standalone que ao invés de produzir mensagens JMS será um consumidor de mensagens JMS.

Page 20: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 20/26

Cliente standalone para consumir mensagens JMS queue

package com.jms.queue;

import java.util.Properties;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.MessageListener;

import javax.jms.Queue;

import javax.jms.QueueConnection;

import javax.jms.QueueConnectionFactory;

import javax.jms.QueueSession;

import javax.jms.Session;

import javax.jms.TextMessage;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class JMSQueueReceiveClient implements MessageListener {

public JMSQueueReceiveClient() {

try {

InitialContext ctx = getInitialContext();

QueueConnectionFactory factory = (QueueConnectionFactory)

ctx.lookup("QueueConnectionFactory");

Queue queue = (Queue)ctx.lookup("queue/MyQueue");

QueueConnection connect = factory.createQueueConnection();

QueueSession session = connect.createQueueSession( false,

Session.AUTO_ACKNOWLEDGE );

MessageConsumer consumer = session.createConsumer( queue );

consumer.setMessageListener(this);

connect.start();

} catch (Exception ex) {ex.printStackTrace();

}

}

public static void main(String[] args) throws Exception {

JMSQueueReceiveClient client = new JMSQueueReceiveClient();

int i = 0;

while(true) {

Thread.sleep(10000);

i++;

System.out.println("["+i+"] Checando queue ...");

}

}

<< Continua na página seguinte >>

Page 21: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 21/26

public static InitialContext getInitialContext() throws NamingException {

Properties env = new Properties();

env.put(Context.SECURITY_PRINCIPAL, "guest" );

env.put(Context.SECURITY_CREDENTIALS, "guest" );

env.put(Context.INITIAL_CONTEXT_FACTORY,

"org.jboss.security.jndi.JndiLoginInitialContextFactory");

env.put(Context.PROVIDER_URL, "jnp://10.1.1.3:1099");

return new InitialContext(env);

}

public void onMessage(Message message) {

try {

TextMessage textMsg = (TextMessage)message;

String text = textMsg.getText();

System.out.println("Mensagem recebida: "+ text );

} catch (JMSException ex) {

ex.printStackTrace();

}

}

}

Código 4-11: Cliente JMS standalone consumidor  

Page 22: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 22/26

Exemplo de um EJB MDB para JMS TopicExemplo de um EJB MDB para JMS TopicExemplo de um EJB MDB para JMS TopicExemplo de um EJB MDB para JMS Topic

Semelhante ao que apresentamos sobre Queue vamos agora apresentar sobre o usode topic. Abaixo serão mostrados três códigos, um para um MDB inscrito em um topic, outro

para um cliente standalone que envia mensagens agindo como produtor para um topic e por fim um cliente standalone que atua como um consumidor inscrito em um topic. Veja abaixoo MDB:

MDB como cliente de um topic

package com.ejb.mdb;

import javax.ejb.ActivationConfigProperty;

import javax.ejb.MessageDriven;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageListener;

import javax.jms.TextMessage;

@MessageDriven(

activationConfig = {

@ActivationConfigProperty(propertyName = "acknowledgeMode",

propertyValue = "Auto-acknowledge"),

@ActivationConfigProperty(propertyName = "destinationType",

propertyValue = "javax.jms.Topic"),

@ActivationConfigProperty(propertyName = "destination",

propertyValue = "topic/testTopic"),

@ActivationConfigProperty(propertyName = "connectionFactoryJndiName",

propertyValue = "TopicConnectionFactory")

}

)public class MDBTopicSample implements MessageListener {

public void onMessage(Message message) {

try {

System.out.println("MDB - Topic - [ onMessage() ] ...");

TextMessage textMsg = (TextMessage)message;

System.out.println("Message: "+ textMsg.getText() );

} catch (JMSException ex) {

System.out.println("Erro ao pegar a mensagem: "+ex.getMessage() );

}

}

}Código 4-12: MDB cliente para topic 

Page 23: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 23/26

Cliente standalone para envio de mensagens JMS a um topic

 Abaixo o cliente standalone para enviar mesnagens para um topic:

package com.jms.topic;

import java.util.Properties;import javax.jms.MessageProducer;

import javax.jms.QueueSession;

import javax.jms.TextMessage;

import javax.jms.Topic;

import javax.jms.TopicConnection;

import javax.jms.TopicConnectionFactory;

import javax.jms.TopicSession;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class JMSTopicSendClient {

public static void main(String[] args) {

try {

InitialContext ctx = getInitialContext();

Topic topic = (Topic) ctx.lookup("topic/testTopic");

// Enviar mensagem para um TOPIC

TopicConnectionFactory factory = (TopicConnectionFactory)

ctx.lookup("TopicConnectionFactory");

TopicConnection connection = factory.createTopicConnection();

TopicSession session = connection.createTopicSession( false,

TopicSession.AUTO_ACKNOWLEDGE);

MessageProducer producer = session.createProducer(topic);

TextMessage textMsg = session.createTextMessage();textMsg.setText("Olá fila topic! ");

producer.send(textMsg);

connection.start();

connection.close();

System.out.println("Mensagem enviada para topic:

"+topic.getTopicName()+ " pelo client!");

} catch (Exception ex) {

ex.printStackTrace();

}

}

public static InitialContext getInitialContext() throws NamingException {

Properties env = new Properties();

env.put(Context.SECURITY_PRINCIPAL, "guest" );

env.put(Context.SECURITY_CREDENTIALS, "guest" );

env.put(Context.INITIAL_CONTEXT_FACTORY,

"org.jboss.security.jndi.JndiLoginInitialContextFactory");

env.put(Context.PROVIDER_URL, "jnp://10.1.1.3:1099");

return new InitialContext(env);

}

}

Código 4-13: Cliente standalone produtor para topic 

Page 24: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 24/26

Cliente standalone consumidor de mensagens JMS do topic

Por fim mostramos um clietne standalone receptor de mensagens de um topic:

package com.jms.topic;

import java.util.Properties;

import javax.jms.JMSException;import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.MessageListener;

import javax.jms.Session;

import javax.jms.TextMessage;

import javax.jms.Topic;

import javax.jms.TopicConnection;

import javax.jms.TopicConnectionFactory;

import javax.jms.TopicSession;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class JMSTopicReceiveClient implements MessageListener {

public JMSTopicReceiveClient() {

try {

InitialContext ctx = getInitialContext();

Topic topic = (Topic)ctx.lookup("topic/testTopic");

TopicConnectionFactory factory = (TopicConnectionFactory)

ctx.lookup("TopicConnectionFactory");

TopicConnection connect = factory.createTopicConnection();

TopicSession session = connect.createTopicSession( false,

Session.AUTO_ACKNOWLEDGE );

MessageConsumer consumer = session.createConsumer( topic );

consumer.setMessageListener(this);

connect.start();

} catch (Exception ex) {

ex.printStackTrace();

}

}

public static void main(String[] args) throws Exception {

JMSTopicReceiveClient client = new JMSTopicReceiveClient();

int i = 0;

while(true) {

Thread.sleep(10000);

i++;

System.out.println("["+i+"] Checando topic ...");}

}

<< Continua na página seguinte >>

Page 25: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 25/26

public static InitialContext getInitialContext() throws NamingException {

Properties env = new Properties();

env.put(Context.SECURITY_PRINCIPAL, "guest" );

env.put(Context.SECURITY_CREDENTIALS, "guest" );

env.put(Context.INITIAL_CONTEXT_FACTORY,

"org.jboss.security.jndi.JndiLoginInitialContextFactory");

env.put(Context.PROVIDER_URL, "jnp://10.1.1.3:1099");

return new InitialContext(env);

}

public void onMessage(Message message) {

try {

TextMessage textMsg = (TextMessage)message;

String text = textMsg.getText();

System.out.println("Mensagem recebida: "+ text );

} catch (JMSException ex) {

ex.printStackTrace();

}

}

}

Código 4-14: Cliente standalone consumidor para topic 

Page 26: Parte 4 Message Driven Bean

5/9/2018 Parte 4 Message Driven Bean - slidepdf.com

http://slidepdf.com/reader/full/parte-4-message-driven-bean-559ca103d14f3 26/26

BibliografiaBibliografiaBibliografiaBibliografia

1 - BURKE, Bill and MONSON-HAEFEL, Richard. "Enterprise JavaBeans 3.0". O'Reilly. 5 ed. 2006. 760 p.

2 - JENDROCK, Eric et al. "The Java EE 5 Tutorial". (http://java.sun.com/javaee/5/docs /tutorial/doc) Consultado em16/04/2007.

3 - JBoss Web Site: http://labs.jboss.com/portal/jbossejb3. Consultado em 15/04/2007.