Title: Introdu
1Introdução a JMS e Message-Driven Bean
Ricardo Cavalcanti roc3_at_cin.ufpe.br
Jobson Ronan jrjs_at_cin.ufpe.br
2Por que usar um MDB?
- Tipicamente devido a algumas limitações de
RMI-IIOP - Performance. Um cliente típico RMI-IIOP precisa
esperar enquanto o servidor está processando.
Apenas quando o servidor completa o trabalho e o
cliente recebe o resultado, este pode continuar
seu processamento - Garantia. Quando um cliente RMI-IIOP invoca o
servidor, este tem que restar rodando. Se o
servidor ou a rede cair o cliente não pode
efetuar a operação desejada
3Por que usar um MDB?
- Suporte para vários emissores e receptores.
RMI-IIOP se limita a comunicação de um único
cliente a um único servidor - Integração com outros sistemas MOM(Middleware
Orientado a Mensagem).
4Messaging
- Mensagens são uma alternativa a invocação de
métodos remotos. - A idéia é inserir uma camada entre o cliente e o
servidor
Invocação de método remoto
Aplicação
Aplicação
Messaging
Message Middleware
Aplicação
Aplicação
5Messaging
- Vantagens
- Processos não bloqueáveis
- Garantia de entrega
- Suporte a múltiplos emissores e receptores
6JMS Java Message Service
- JMS é um padrão para Messaging
- Tem como objetivo eliminar muitas das desvantagem
que MOMs encontraram com o passar dos anos - O Desenvolvedor aprende a usar a API de JMS e
reusa seu código com diferentes implementações
plugáveis de MOM (idéia similar APIs do J2EE,
como JNDI e JDBC)
7Domínios de Mensagens
- Publish/subscribe(pub/sub)
- Análogo a assistir televisão. Pode haver muitos
produtores de mensagens e muitos consumidores.
Consumidor 1
Produtor 1
Canal
Consumidor 2
Produtor 2
8Domínios de Mensagens
- Point-to-point(PTP)
- Múltiplos produtores podem enviar mensagens para
a fila mas cada mensagem é entregue a apenas um
consumidor
Produtor 1
Consumidor 1
Fila
Produtor 2
9Usando a API JMS
- Passos
- 1. Localizar o provedor JMS, instancia de
ConnectionFactory - 2. Criar um conexão JMS
- 3. Criar uma Sessão JMS
- 4. Localizar o destino
- 5. Criar um JMS Provider ou um JMS Consumer
- 6. Enviar ou Receber suas mensagens
102. Criar conexão
JMS Connection Factory
Fila1
3. Criar sessão
JSM Connection
Fila2
Cliente
5. Criar producer ou consumer
JMS Session
Tópico1
1. Obter o Driver JMS (ConnectionFactory)
6. Enviar ou receber mensagens
JSM Prosucer ou Consumer
Servidor JMS
4. Obter o destino JMS
Driver JMS do cliente
6. Enviar ou receber mensagens
JNDI
Serviço de nomes
11Exemplo
//..imports public class Client public
static void main (String args) throws Exception
Context ctxt new
InitialContext() TopicConnectionFactory
factory (TopicConnectionFactory)
ctxt.lookup("jms/TopicConnectionFactory")
TopicConnection connection factory.createTopic
Connection() TopicSession session
connection.createTopicSession (false,
Session.AUTO_ACKNOWLEDGE) Topic topic
(Topic) ctxt.lookup("jms/Topic")
TopicPublisher publisher session.createPublisher
(topic) TextMessage msg
session.createTextMessage()
msg.setText("This is a test message.")
publisher.publish(msg)
12Interfaces
INTERFACE PAI POINT-TO-POINT PUB/SUB
ConnectionFactory QueueConnectionFactory TopicConnectionFactory
Connection QueueConnection TopicConnection
Destination Queue Topic
Session QueueSession TopicSession
MessageProducer QueueSender TopicPublisher
MessageConsumer QueueReceiver, QueueBrowser TopicSubscriber
13Integração JMS-EJB
- Motivação
- Possuir componentes Ejbs com características como
clientes não-bloqueaveis e comunicação n-ária
14Integração JMS-EJB
- Como implementar a integração?
- Implementar objetos Java que recebem mensagens e
realizam chamadas a componentes EJBs? - Reusar um tipo existente de componente EJB para
receber Mensagens JMS?
15Messsage-Driven Beans
- O que são?
- Introduzido na especificação EJB 2.0
- São componentes EJBs especiais capazes de receber
mensagens enviadas a filas e canais JMS - Invocados pelo Container dada a chegada de um
mensagem ao destino que um MDB escuta - Não se envia uma mensagem direto a um
MDB(envia-se ao canal que o bean escuta) - Proporcionando acoplamento fraco entre cliente e
MDB (conhecimento do canal de comunicação)
16Messsage-Driven Beans
- Para efetuar a comunicação é necessário o uso de
uma API específica, como JMS
Pool de MDBs
Cliente
Destino JMS
Instancias de Message-Driven Beans
17Messsage-Driven Beans
- Características
- Não possuem interface home, local home, interface
remota, nem interface local - Possuem apenas um método que recebe qualquer tipo
de mensagem - Não têm retorno, e também não lançam exceções ao
cliente - São Stateless
- Podem ser ouvintes de uma fila, ou assinantes
durável ou não-durável de um canal(Topic)
18Implementando MDBs
- MDBs devem implementar duas interfaces
- javax.jms.MessageListener
- javax.ejb.MessageDrivenBean
- Métodos de MessageDrivenBean e da especificação
- ejbRemove() método da interface. Chamado pelo
container quando o message-driven bean está sendo
removido do pool - ejbCreate() método definido na especificação
(não está na interface). É chamado quando um novo
bean é criado pelo container - setMessageDrivenContext(MessageDrivenContext
ctx) método da interface. Chamado antes do
ejbCreate() quando o bean está sendo adicionado
ao pool
19Implementando MDBs
- Método de MessageListener
- onMessage(Message m) chamado cada vez que uma
mensagem é enviada para o canal do bean (se o
bean estiver ativado).
20Implementando MDBs
package org.citi.pec.ejbs //..imports /
_at_ejb.bean name"ExecuterSQLMessage"
display-name"Name for Executer"
description"Description for Executer"
destination-type"javax.jms.Queue"
acknowledge-mode"Auto-acknowledge"
_at_jboss.destination-jndi-name name
"queue/MyQueueMDB" / public class ExecuterBean
implements MessageDrivenBean, MessageListener
public void onMessage(Message message)
try if (message instanceof
TextMessage) TextMessage text
(TextMessage) message
System.out.println(text.getText())
catch (JMSException e) throw new
EJBException(e) public void
setMessageDrivenContext(MessageDrivenContext
ctx) throws EJBException public
void ejbCreate() throws EJBException
public void ejbRemove() throws EJBException
21Deployment Descriptors
lt?xml version"1.0" encoding"UTF-8"?gt lt!DOCTYPE
ejb-jar PUBLIC "-//Sun Microsystems,
Inc.//DTD Enterprise JavaBeans 2.0//EN
"http//java.sun.com/dtd/ejb-jar_2_0.dtd"gt ltejb-j
ar gt ltdescriptiongtlt!CDATANo
Description.gtlt/descriptiongt
ltdisplay-namegtGenerated by XDocletlt/display-namegt
ltenterprise-beansgt ltmessage-driven gt
ltdescriptiongtlt!CDATADescription for
Executergtlt/descriptiongt
ltdisplay-namegtName for Executerlt/display-namegt
ltejb-namegtExecuterSQLMessagelt/ejb-namegt
ltejb-classgtorg.citi.pec.ejbs.ExecuterBeanlt/ej
b-classgt lttransaction-typegtContainerlt/tra
nsaction-typegt ltacknowledge-modegtAuto-ac
knowledgelt/acknowledge-modegt
ltmessage-driven-destinationgt
ltdestination-typegtjavax.jms.Queuelt/destination-typ
egt lt/message-driven-destinationgt
lt/message-drivengt lt/ejb-jargt
...e se fosse Topic ???
22Deployment Descriptors
- Outras Tags
- ltmessage-selectorgt
- Usado para incluir um filtro SQL para cabeçalhos
de mensagens. Apenas mensagens que combinarem com
o filtro serão recebidas pelo bean. Exemplo - ltmessage-selectorgtlt!CDATA
- Formato LIKE 'Imagem AND JMSExpiration gt 0
- AND Valor IS NOT NULLgt
- lt/message-selectorgt
23Deployment Descriptors
lt?xml version"1.0" encoding"UTF-8"?gt lt!DOCTYPE
jboss PUBLIC "-//JBoss//DTD JBOSS 3.2//EN
"http//www.jboss.org/j2ee/dtd/jboss_3_2.dtd"gt lt
jbossgt ltenterprise-beansgt
ltmessage-drivengt ltejb-namegtExecuterSQLMes
sagelt/ejb-namegt ltdestination-jndi-namegtqu
eue/MyQueueMDBlt/destination-jndi-namegt
lt/message-drivengt lt/enterprise-beansgt
ltresource-managersgt lt/resource-managersgt lt/jbo
ssgt
24JBoss
- ...empacotar e fazer o deploy...
- Warning no deploy a fila referênciada
(queue/MyQueueMDB)não existe, o JBoss criará uma
nova fila temporária para o MDB
25JBoss
- Como a maioria das coisas no JBoss, JMS Topics e
Queues são implementadas como MBeans - Para criar uma fila permanente no JBoss, basta
adicionar uma declaração de um MBean no arquivo
jbossmq-destinations-service.xml (diretório jms
dentro do diretório deploy)
lt!-- .... --gt ltmbean code"org.jboss.mq.server.jmx
.Queue name"jboss.mq.destinationserviceQueue,
nameMyQueueMDB"gt ltdepends
optional-attribute-name"DestinationManager"gt jb
oss.mqserviceDestinationManager lt/dependsgt lt/mb
eangt lt!-- .... --gt
26Implementando cliente
- Como um cliente JMS comum
//..imports public class MDBClient public
static void main(String args) throws Exception
Properties namingProperties new
Properties() namingProperties.put(C
ontext.INITIAL_CONTEXT_FACTORY, "org.jnp.interfa
ces.NamingContextFactory")
namingProperties.put("java.naming.provider.url",
"jnp//localhost1099")
namingProperties.put("java.naming.factory.url.pkgs
", "org.jboss.naming.client")
Context ctx new InitialContext(namingProperties)
QueueConnectionFactory cf
(QueueConnectionFactory) ctx.lookup("XAConnectio
nFactory") QueueConnection conn
cf.createQueueConnection() QueueSession
session conn.createQueueSession(false, Session
.AUTO_ACKNOWLEDGE) Queue queue (Queue)
ctx.lookup("queue/MyQueueMDB")
QueueSender sender session.createSender(queue)
TextMessage message session.createTextMe
ssage() message.setText("Hello World of
Messaging!") sender.send(message)
27Exercício
- Construa um MDB simples que recebe uma mensagem
de texto e imprime seu conteúdo se a mensagem
possuir no cabeçalho a informação fonte
cliente - Construa um cliente que envia uma Mensagem a fila
na qual o MDB está escutando
28- ...mas quem pode e deve ser um cliente de um
bean - Servlets locais
- Beans locais
- Classes java remotas
- ...
29Exercício ()
- ... How the pieces fit together?
- Construa um Entity Bean CompraBean com os
segiuntes atributos - Código
- Cliente
- produtos (pode ser uma string contendo todos os
produtos) - valor total
- status da compra (um booleano que indica se a
compra foi validada ou não)
30Exercício ()
- Construa um MDB ValidadorBean que recebe uma
mensagem contendo os dados de uma compra e simula
uma verificação de perfil de compra. Em seguida
ele altera o estado do CompraBean Correspondente
para validado - você pode usar um "Thread.sleep()" para simular
um processo demorado
31Exercício ()
- Crie um ValueObject para o Bean Compra (CompraVO)
- Construa um SessionBean stateless que contém o
método efetuarCompra(CompraVO compra) que - Cria um CompraBean equicvalente ao CompraVO
passado por parametro - E em seguida envia uma mensagem ao ValidadorBean,
solicitando a validação da compra
32Exercício ()
- Crie um cliente simples que efetua uma compra
através o session Bean que você implementou - ...E...
33- Bom (resto) de fim de semana! ?