JMS
Autoria
Autoria
Fábio Cecin (1a versão)
Versão
V3.2, junho de 2013
Referências
Referências:
The JMS Tutorial
após versão 1.4 do JEE
em capítulo do tutorial JEE da Sun
v.1.5 (JEE):
http://java.sun.com/javaee/5/docs/tutorial/doc/
até v. 1.3:
http://java.sun.com/products/jms/tutorial/
Documentação (javadoc) do pacote JMS:
http://java.sun.com/javaee/5/docs/api
Dica: utilizar estes documentos como referência de
Referências
Referências:
The JMS Tutorial
Após versão 1.4 do JEE
Em capítulos do tutorial JEE da Sun
v.1.6 (JEE):
Caps. 47 e 48
Referências
Referências:
The JMS Tutorial Até v. 1.3: http://docs.oracle.com/javaee/1.3/jms/tutorial/ http://java.sun.com/products/jms/tutorial/ Em 2012 desvia para: http://www.oracle.com/technetwork/java/jms/ index.htmlReferências
Referências:
Especificação
http://www.oracle.com/technetwork/java/ docs-136352.html
Súmula
Súmula
Visão Geral
JMS
Arquitetura
Modelo de Programação
Mecanismos de Confiabilidade
Integração com EJB
Enterprise JavaBeans
Message-Driven Beans
Visão Geral
Visão geral
JMS é uma API padrão da plataforma JEE que dá acesso a
serviços de messaging.
Messaging pode ser entendido como troca de
mensagens, similar ao sistema de correio eletrônico.
JMS é
uma API mais um serviço
para troca de mensagens entre componentes de software distribuídos
oferecendo diversas funcionalidades inexistentes em outros pacotes (bibliotecas, mws, protocolos, …)
Visão Geral
Visão geral
JMS foi originalmente desenvolvido para a integração com
MOMs (Message-Oriented Middleware)
Por exemplo, MQSeries da IBM
Permitiria comunicação entre componentes Java e não-Java
Mas pode ser usado atualmente para integração com
Sistemas de Informação (EIS: Enterprise Information Systems) existentes
A partir da versão 1.3 do padrão JEE, a API JMS tornou-se
uma solução completa, independente, para aplicações de messaging.
Procura ser ao mesmo tempo:
Visão Geral
Vantagens de JMS
Especialmente sobre alternativas mais fortemente acopladas
(RMI…):
Fácil substituição:
componentes não dependem da interface de outros componentes
Componentes que trocam mensagens via JMS não precisam
se conhecer
Comunicação entre dois componentes não requer que ambos
estejam operacionais para que a comunicação aconteça
É possível enviar uma mensagem e continuar a execução de
Visão Geral
Vantagens de JMS
Diversas opções de sincronização no recebimento
time-out
síncrona e assíncrona
2 grandes modelos
ponto a ponto
Visão Geral
JMS – versões
Segundo artigos da Oracle
v1.1: 2002 v2.0: abril 2013 Ou segundo wikipedia JMS 1.0.2b (June 25, 2001) JMS 1.1 (March 18, 2002) JMS 2.0 (May 21 2013)
Visão Geral
JMS – implementações
Em
http://en.wikipedia.org/wiki/Java_Message_Service
ActiveMQ Apache
Apache Qpid, using AMQP
http://qpid.apache.org
Oracle Weblogic (part of the Oracle Fusion Middleware|
Fusion Middleware suite) and Oracle AQ from Oracle Corporation
EMS from TIBCO
Visão Geral
JMS – implementações
JBoss Messaging and HornetQ from Jboss
JORAM from the OW2 Consortium
Open Message Queue from Oracle
OpenJMS from The OpenJMS Group
Solace JMS from Solace systems
RabbitMQ by Rabbit Technologies Ltd., acquired by
Visão Geral
JMS – implementações
SAP Process Integration ESB
SonicMQ from Progress Software
StormMQ, using AMQP
SwiftMQ
Visão Geral
JMS – implementações
Ultra Messaging from 29 West (acquired by Informatica)
webMethods from Software AG
WebSphere Application Server from IBM
which provides an inbuilt default messaging provider known as the Service Integration Bus (SIBus), or which can connect to WebSphere MQ as a JMS provider
"Choosing a messaging system: WebSphere MQ vs. the WebSphere Application Server Service Integration Bus”
http://www.ibm.com/developerworks/websphere/ library/techarticles/1109_wallis/1109_wallis.html| work=IBM developerWorks
Visão Geral
JMS - características funcionais em JEE:
EJBs, clientes e componentes web podem consumir
mensagens JMS de forma síncrona (recepção)
Permite interação com um novo (“faz tempo”) tipo de bean,
o message-driven bean:
um EJB que consome mensagens JMS de forma assíncrona.
Envio e recebimento de mensagens JMS podem participar de
Arquitetura JMS
Arquitetura JMS
Administrative Tool; Cliente JMS
Arquitetura JMS
Arquitetura JMS
Provedor de Serviço JMS:
Implementa as interfaces do JMS
Oferece recursos administrativos e de controle
JEE deve oferecer um provedor JMS
Clientes JMS:
Componentes escritos em Java
Consomem e produzem mensagens
Todo componente de uma aplicação JEE pode ser cliente
Arquitetura JMS
Arquitetura JMS
Ferramenta administrativa
cria objetos administrativos em um serviço de nomes JNDI
objetos são Connection Factories e Destinations, utilizados
Arquitetura JMS
Um provedor de serviços JMS (JEE 1.3 e mais)
suporta obrigatoriamente
tanto o domínio de comunicação ponto-a-ponto
quanto o de publicador-assinante.
Publicador-assinante Ponto-a-ponto
Modelo ponto-a-ponto
Modelo (domaine) ponto-a-ponto
abstrações
filas (queues) de mensagens
produtores de mensagens
consumidores de mensagens
cada mensagem é enviada a uma fila
fila mantém mensagens até serem consumidas ou expiradas
cada mensagem só tem um consumidor
sem dependência de tempo entre produtor e consumidor
consumidor pode consumir mensagem mesmo se não estivesse executando quando do envio da mensagem
Modelo publicador-assinante
Modelo publicador-assinante
abstrações tópicos (topics) publicadores de mensagens assinantes de mensagens clientes publicadores enviam (publicam) mensagens a um
tópico (topic)
assinantes se inscrevem como interessados em um tópico
o sistema se encarrega de distribuir as mensagens de um
tópico aos assinantes desse tópico
mensagens são mantidas até que todos os assinantes atuais as
Modelo publicador-assinante
Modelo publicador-assinante
uma mensagem pode ter vários consumidores (assinantes)
há dependência de tempo entre publicador e assinante
um assinante só pode consumir mensagens publicadas após a inscrição
subscrições duráveis
permitem contornar a dependência de tempo
oferecem mais flexibilidade e confiabilidade (como as filas)
mas preservam a relação n (> 1) consumidores para 1 mensagem
Modelos x Usos
Quando usar cada modelo?
ponto-a-ponto:
use quando cada mensagem deve ser lida por 1 cliente
publicador-assinante
use quando cada mensagem pode ser lida por zero, 1 ou vários clientes
Interfaces comuns
Interfaces comuns
envio e recepção de mensagens com o mesmo código seja
fila (ponto-a-ponto) ou topic (assinante)
as destinações indicarão se fila ou topic
Consumo de mensagens
Consumo de mensagens
Síncrono
cliente deve executar o método receive
o método receive bloqueia até:
uma mensagem chegar
ou se houver um time-out
Assíncrona
cliente registra um message-listener a um consumidor
semelhante a um event-listener
a cada nova mensagem que chega ao destino
o sistema chama o método onMessage
Modelo de Programação JMS Modelo JMS: Entidades Administrativas: - Fábricas de Conexões - Destinos Entidades de Programação: - Conexão - Sessão - Mensagem - Produtor - Consumidor
Modelo de Programação JMS
Fábricas de conexões e destinos
São criados e modificados em ferramentas administrativas,
em contraste com criação via clientes JMS.
O objetivo é manter a portabilidade da API, ao encapsular
informações específicas de conexão e de endereçamento nestes objetos.
Cada fornecedor JEE
Implementa suas próprias ferramentas administrativas.
Sun JEE: j2eeadmin (/j2ee/bin) (versão 1.3)
Clientes JMS acessam esses objetos através de interfaces
padronizadas
Modelo de Programação JMS
Fábrica de conexões (connection factory):
É o objeto utilizado pelo cliente JMS para criar uma
conexão com um serviço JMS.
Uma instalação de JMS
Deve fornecer pelo menos duas fábricas (nomes JNDI):
QueueConnectionFactory (ponto-a-ponto)
TopicConnectionFactory (publicador-assinante)
Há ainda a fábrica geral:
Modelo de Programação JMS
Exemplo:
Obtendo uma Connection Factory em uma classe cliente
@Resource(mappedName = "jms/ConnectionFactory") private static ConnectionFactory connectionFactory;
@Resource(lookup = "jms/ConnectionFactory")
Modelo de Programação JMS
Destino (Destination):
Um objeto que o cliente JMS usa como
alvo das mensagens que produz
e fonte das mensagens que consome.
Em comunicação ponto-a-ponto
um destino é chamado fila (queue)
Em comunicação publicador-assinante
um destino é chamado tópico (topic).
Uma aplicação JMS
Modelo de Programação JMS
Destino (Destination):
Objetos filas e tópicos injetados no programa só podem ser
usados como filas ou tópicos
Objetos “Destinations”
Para desenvolver componentes que manipulem filas e tópicos com o mesmo código se pode usar objetos
Destinations
O comportamento de um programa é determinado pelo tipo
de destino (fila ou tópico)
Modelo de Programação JMS
JEE Sun –
Criando destinos (filas e tópicos):
j2eeadmin -addJmsDestination <nome JNDI da fila> queue
j2eeadmin -addJmsDestination <nome JNDI do tópico> topic
Modelo de Programação JMS
Visão geral de “codificando um cliente JMS”:
Obter ConnectionFactory e Destinations via @resource na
classe cliente
Usar factory para criar uma Connection com o provedor JMS
Usar Connection para criar uma ou mais Sessions
Usar uma Session com os Destinations para criar produtores
e consumidores
Habilitar a Connection (método start) para iniciar a entrega
de Messages no cliente consumidor
Criar uma mensagem usando método específico (conforme
tipo da mensagem) de Session
Enviar mensagem com método send do produtor
Modelo de Programação JMS
JEE Sun –
Obtendo um destino no cliente, após criação:
@Resource(mappedName = "jms/Queue")
private static Queue queue
@Resource(mappedName = "jms/Topic" private static Topic topic;
@Resource(lookup = "jms/Queue")
private static Queue queue;
@Resource(lookup = "jms/Topic")
Modelo de Programação JMS
Conexões (Connections):
Conexão é um canal entre o cliente e o provedor de serviço
JMS
Após criado e obtido (@resource) um objeto fábrica de conexões, é possível criar conexões a partir do mesmo:
QueueConnection myQueueCon = myQueueFact.createQueueConnection(); TopicConnection myTopicCon = myTopicFact.createTopicConnection(); Connection connection = connectionFactory.createConnection()
A criação geral (Connection) pode ser usada para queue e
topic
queue e topic serão indicados na criação de produtores e
Modelo de Programação JMS
Conexões
Podem ser (re)iniciadas e suspensas após criação.
Não há recebimento de mensagens enquanto a conexão está
suspensa:
myQueueCon.start(); /* (re)inicia */
myQueueCon.stop(); /* suspende */
connection.start();
connection.stop();
É necessário fechar conexões após o uso:
Modelo de Programação JMS
Resumo de “codificando um cliente JMS”:
Obter ConnectionFactory e Destinations via @resource na classe cliente
Usar factory para criar uma Connection com o provedor JMS
Habilitar a Connection (método start) para iniciar a entrega de Messages
no cliente consumidor
Usar Connection para criar uma ou mais Sessions
Usar uma Session com os Destinations para criar produtores e
consumidores
Criar uma mensagem usando método específico (conforme tipo da
mensagem) de Session
Enviar mensagem com método send do produtor
Modelo de Programação JMS
Sessão (Session):
Uma sessão representa um contexto para uma thread
produzir e consumir mensagens.
Também prove um contexto de transação para um conjunto
Modelo de Programação JMS
Sessão (Session):
A partir de uma conexão é possível criar sessões (sessions):
QueueSession myQueueSession =
myQueueCon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Arg. 1: sessão sem semântica de transação.
Arg. 2: confirmação automática de recebimento de mensagens pela sessão.
Session session = connection.createSession(
false,
Modelo de Programação JMS
Resumo de “codificando um cliente JMS”:
Obter ConnectionFactory e Destinations via @resource na classe cliente
Usar factory para criar uma Connection com o provedor JMS
Habilitar a Connection (método start) para iniciar a entrega de Messages
no cliente consumidor
Usar Connection para criar uma ou mais Sessions
Usar uma Session com os Destinations para criar
produtores e consumidores
Criar uma mensagem usando método específico (conforme tipo da
mensagem) de Session
Enviar mensagem com método send do produtor
Modelo de Programação JMS
Produtor de mensagens:
É um objeto criado por uma sessão
Utilizado para enviar mensagens para um destino
especificado.
Argumento da criação do produtor
Há 3 tipos de interfaces conforme o tipo de destino
Geral: interface Producer
Para filas: interface QueueSender
Modelo de Programação JMS
Exemplo de produtor
Destination dest = queue ou topic; ...
Producer producer =
session.createProducer(dest /*destino*/ );
Message myMessage = /* … cria mensagem … */
Modelo de Programação JMS
Produtor de mensagens:
É possível não especificar o destino (null)
Nesse caso o destino será especificado pelo método de envio
Modelo de Programação JMS
Consumidor de mensagens:
Objeto criado por uma sessão para recebimento de
mensagens enviadas a um destino especificado.
Um cliente JMS
utiliza um consumidor de mensagens para registrar interesse por certos destinos hospedados em um provedor JMS.
O provedor de serviço JMS
se encarrega de transferir as mensagens de um destino para os consumidores registrados neste destino.
Modelo de Programação JMS
Consumidor de mensagens:
Geral: interface Consumer
Para filas: interface QueueReceiver
Para tópicos: interface TopicSubscriber
Exemplo com consumo síncrono:
receive ( )
parâmetro opcional timeout em milisegundos.
Consumer consumer = session.createConsumer(dest);
Modelo de Programação JMS
Resumo de “codificando um cliente JMS”:
Obter ConnectionFactory e Destinations via @resource na classe cliente
Usar factory para criar uma Connection com o provedor JMS
Usar Connection para criar uma ou mais Sessions
Habilitar a Connection (método start) para iniciar a entrega de Messages
no cliente consumidor
Usar uma Session com os Destinations para criar produtores e
consumidores
Criar uma mensagem usando método específico (conforme
tipo da mensagem) de Session
Enviar mensagem com método send do produtor
Modelo de Programação JMS
Mensagem (Message):
Objeto que representa uma mensagem
Formato permitiria uso de mensagens por aplicações não
JMS
Deve ser criado por uma sessão através de interface
Modelo de Programação JMS
Mensagem (Message):
Possui três partes:
Cabeçalho (header):
possui campos pré-definidos que devem ser
preenchidos pela aplicação ou pela implementação JMS.
tipo, destino, prioridade, time-stamp, ...
Propriedades (properties):
espaço para um header opcional, mantido pela aplicação.
Modelo de Programação JMS
Tipos de mensagens (corpo):
TextMessage: uma String
BytesMessage: uma sequência de bytes
StreamMessage: um stream de tipos primitivos Java (int,
char, byte[], String...)
ObjectMessage: objeto Java serializado
Modelo de Programação JMS
Criando e enviando uma mensagem de texto:
Consumindo a mensagem:
TextMessage message =
session.createTextMessage();
message.setText(“minha mensagem”);
producer.send(message);
Message m = consumer.receive(); if (m instanceof TextMessage) {
TextMessage message = (TextMessage)m; System.out.println(”Mensagem chegou: ”
Modelo de Programação JMS
Message listeners:
Uma classe qualquer da aplicação pode atuar como
consumidora assíncrona de mensagens
ao implementar a interface MessageListener, do padrão JMS.
Esta interface especifica o método:
void onMessage( Message )
onde Message
é a mensagem de interesse que deve ser processada pela classe.
Esse método “substitui” o “receive” da recepção síncrona
Modelo de Programação JMS
Message listeners:
A classe listener deve ser registrada junto a um consumidor
(Consumer ou QueueReceiver ou TopicSubscriber)
através do método setMessageListener( ) (do consumidor),
para receber as mensagens.
Exemplo:
myTopicSubscriber.setMessageListener( myTopicListener );
Onde myTopicListener
é instância de classe que implementa a interface MessageListener.
Modelo de Programação JMS
Message listeners:
A entrega de mensagens também deve ser ativada pelo
método “start” da sessão
Um “listener” específico pode receber mensagens de ambos
os tipos
O tipo é definido pelo consumidor ao qual o “listener”
registrado
Vários “listener” podem estar registrados em uma sessão
Os respectivos consumidores foram criados nessa sessão
Nesse caso a execução de todos os “listener” é serializada
Em JEE/EJB, um “message drive bean” é um caso especial
Modelo de Programação JMS
Filtro de mensagens:
É possível filtrar mensagens em recepção
Um seletor usa uma sintaxe baseada em SQL
A seleção só pode ser feita sobre atributos das partes
cabeçalho e propriedades da mensagem
Modelo de Programação JMS
Exceções:
JMS possui uma hierarquia de exceções, cuja raiz é
JMSException.
Portanto, é possível utilizar um tratador genérico para
qualquer exceção JMS:
Modelo de Programação JMS
Resumo de “codificando um cliente JMS”:
Obter ConnectionFactory e Destinations via @resource na
classe cliente
Usar factory para criar uma Connection com o provedor JMS
Usar Connection para criar uma ou mais Sessions
Usar uma Session com os Destinations para criar produtores
e consumidores
Habilitar a Connection (método start) para iniciar a entrega
de Messages no cliente consumidor
Criar uma mensagem usando método específico (conforme
tipo da mensagem) de Session
Confiabilidade JMS
Confiabilidade JMS
JMS possui vários mecanismos para aumento da robustez da
aplicação:
Nível de confirmação (acknowledgement)
Persistência de mensagens
Nível de prioridade da mensagem
Mensagens com tempo de vida
Criação de destinos temporários
Assinaturas duráveis (durable subscriptions)
Confiabilidade JMS
Nível de confirmação (acknowledgement)
é especificado na criação da fila ou tópico:
Session.AUTO_ACKNOWLEDGE:
mensagens automaticamente confirmadas.
Session.CLIENT_ACKNOWLEDGE:
cliente deve invocar o método acknowledge( ) da mensagem para confirmá-la.
Session.DUPS_OK_ACKNOWLEDGE:
idem a AUTO ,
porém pode resultar em entregas duplicadas de mensagens, com possível ganho em performance.
JMS 2.0
JMS 2.0
Objetivo principal
Nova API “simplified”
Permite códigos mais concisos, simples
Tem todas funcionalidades da API anterior
API 1.1 “classic”
JMS 2.0
JMS 2.0
API “simplified”
Novas interfaces:
JMSContext, JMSProducer, and JMSConsumer
JMSContext
JMS 2.0
JMS 2.0
API “simplified”
JMSProducer
Substitui MessageProducer
Oferece manipulação da mensagem
Opções de entrega
Headers
Properties
JMS 2.0
JMS 2.0
API “simplified
JMSConsumer
Substitui MessageConsumer
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Aplicação
Envio de mensagem de texto
Versão “classic”
public void sendMessageJMS11(ConnectionFactory connectionFactory,
Queue queueString text) { try { Connection connection = connectionFactory.createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Aplicação
Envio de mensagem de texto
Versão “classic”
MessageProducer messageProducer =
session.createProducer(queue);
TextMessage textMessage = session.createTextMessage(text); messageProducer.send(textMessage);
} finally {
connection.close(); }
} catch (JMSException ex) {
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Versão “simplified”
public void sendMessageJMS20(ConnectionFactory
connectionFactory, Queue queue, String text) {
try (JMSContext context = connectionFactory.createContext();) {
context.createProducer().send(queue, text);
} catch (JMSRuntimeException ex) {
// handle exception (details omitted)
} }
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Diferenças
Simplified cria um único objeto Context
E não 2: Connection e Session
Simplified tem chamada de “close” implícita
Opções de sessão
Simplified: há uma opção “default”
false e Session.AUTO_ACKNOWLEDGE
sem transação e confirmação automática de mensagens
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Diferenças
Mensagens texto (text): conteúdo passado como argumento do método send
processamento de exceções mais simples
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Aplicação
Recepção síncrona de mensagem de texto
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Versão “classic”
public String receiveMessageJMS11(ConnectionFactory connectionFactory,Queue queue) { String body=null; try { Connection connection = connectionFactory.createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer messageConsumer = session.createConsumer(queue); connection.start();
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Versão “classic” (cont.) TextMessage textMessage = (TextMessage) messageConsumer.receive(); body = textMessage.getText(); } finally { connection.close(); }
} catch (JMSException ex) {
// handle exception (details omitted)
}
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Versão “simplified” (cont.)
public String receiveMessageJMS20(
ConnectionFactory connectionFactory,Queue queue) { String body=null;
try (JMSContext context = connectionFactory.createContext() { JMSConsumer consumer =
session.createConsumer(queue);
body = consumer.receiveBody(String.class); } catch (JMSRuntimeException ex) {
// handle exception (details omitted)
}
return body; }
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Diferenças
Simplified cria um único objeto Context
E não 2: Connection e Session
Simplified tem chamada de “close” implícita
Opções de sessão
JMS 2.0
JMS 2.0
Exemplo comparando “simplified” x “classic”
Diferenças
Não é necessário ativar a recepção (método start)
Mensagens texto (text):
Recupera texto (corpo da mensagem) com receive especial (sem uso de métodos adicionais)
Resumo JMS
Resumo
JMS é uma especificação de serviços e API para troca de
mensagens Arquitetura Clientes Ferramentas Provedor (serviço) Modos Filas Tópicos (publish/subscribe)
Resumo JMS
Resumo
API Factories Destinos Connections Sessions Producers e Consumers Messages Diversas funcionalidades como
Semânticas variadas de sincronização
Time-outs
Confiabilidade JMS
Persistência de mensagens:
DeliveryMode.PERSISTENT:
instrui o provedor de serviço JMS a tomar cuidado extra com esta mensagem,
para que ela não seja perdida em caso de falhas no serviço.
DeliveryMode.NON_PERSISTENT
Esta opção pode ser especificada a cada envio de mensagem
(nos métodos send( ) e publish( ) dos produtores),
Confiabilidade JMS
Nível de prioridade da mensagem:
Entre 0 e 9 (default=4).
O provedor JMS tenta entregar mensagens de maior
prioridade primeiro.
Pode ser especificado por envio de mensagem:
myTopicPublisher.publish(message,
DeliveryMode.NON_PERSISTENT, 3);
// 3 é a prioridade
Pode ser especificado no produtor:
Confiabilidade JMS
Mensagens com tempo de vida
Por exemplo, para se criar mensagens com tempo de vida de
16 segundos:
myTopicPublisher.publish(message,
DeliveryMode.NON_PERSISTENT, 3, 16000);
myProducer.setTimeToLive( 16000 );
Confiabilidade JMS
Criação de destinos temporários:
é possível a criação programática de destinos, subordinados a
uma conexão (Connection):
TemporaryQueue myTempQueue=
queueSession.createTemporaryQueue();
TemporaryTopic myTempTopic =
topicSession.createTemporaryTopic();
O destino temporário, e todas as mensagens contidas neste,
Confiabilidade JMS
Destino temporários
Qualquer produtor pode enviar mensagens para um destino
temporário,
mas apenas consumidores criados sob a mesma conexão
podem consumir mensagens deste.
Uso comum - sistema requisição-resposta:
Cliente JMS Cabeçalho: JMSDestination = myQueue JMSReplyTo = tempQueue tempQueue myQueue Cliente JMS
Confiabilidade JMS
Assinaturas duráveis:
após criada uma assinatura durável, um ou mais assinantes
duráveis (um de cada vez) podem obter a assinatura e recuperar mensagens enviadas antes das suas criações individuais:
Confiabilidade JMS
Transações locais (local transactions):
uma sessão criada com suporte a transações disponibiliza
dois métodos adicionais:
mySession.commit( ) - efetiva a transação.
mySession.rollback( ) - desfaz operações parciais da transação.
Este suporte é simples, porém limitado
Não pode ser usado em EJBs
, que devem utilizar o
Confiabilidade JMS
Em transações
cuidado com a ordem das operações:
Somente send()s ou receive()s = OK
receive()s antes de send()s = OK
send() de uma mensagem e após, tentativa de receive() da
resposta na mesma transação = deadlock
Causa: mensagens enviadas em uma sessão transacional não são de fato enviadas até o commit( )
Confiabilidade JMS
Adicionalmente:
uma mensagem enviada em uma transação não pode ser
consumida na mesma transação.
Isto ocorre porque este suporte à transação é local ao contexto
de um cliente e um provedor JMS, que intervém entre o send e o receive:
JMS + Enterprise JavaBeans
EJB:
Qualquer tipo de enterprise bean pode atuar como um cliente
JMS:
Produzir mensagens.
Consumir mensagens de forma síncrona - Consumer.receive( );
Para evitar uso desnecessário de recursos
do servidor ( receive nunca satisfeito) utilizar receiveNoWait( ) ou receive( <timeout-ms> ):
while ( … ) {
/* retorna “null” se não há mensagem em 10ms */
JMS + Enterprise JavaBeans
Por questão de performance
recomenda-se realizar o lookup de objetos administrativos
(fábricas de conexões e destinos) apenas no método
ebjCreate( ) do bean,
ao invés de realizar o lookup cada vez em que o objeto for
necessário em um método de serviço do bean.
É recomendado
utilizar o suporte a transações distribuídas do container EJB
(container-managed transactions)
ou, em caso de requerimentos especiais da aplicação, outro
JMS + Enterprise JavaBeans
É importante
liberar os recursos JMS (sessões e conexões) quando não forem mais utilizadas.
Se um recurso for utilizado
apenas durante um método de negócio do bean, utilizar uma estrutura try-finally dentro do método:
// criação de recursos JMS
try {
// operações que podem jogar exceções…
} /* opcionalmente: catch { … } */ finally { // liberação dos recursos JMS
JMS + Enterprise JavaBeans
Se o recurso for utilizado
durante todo o tempo de vida do EJB,
é recomendável criar o recurso JMS (sessão ou conexão) no
método ejbCreate( ),
Message-Driven Beans
Message-Driven Beans -
Um MDB é um bean que pode consumir mensagens de
forma assíncrona, assim como um message listener:
O método onMessage( ) do MDB é invocado quando uma mensagem chega no destino de interesse.
O MDB pode registrar interesse em dois destinos: uma fila, ou em uma assinatura durável (tópico).
Um MDB não possui
interfaces home e remote , sendo constituído apenas de uma classe de bean.
Message-Driven Beans
MDB x Session Beans
Possui similaridades com Stateless Session Bean
Instâncias com tempo de vida curto;
Não guarda estado para um cliente específico;
Podem ser criadas previamente em uma pool para
atendimento de vários clientes;
Podem manter alguns recursos em aberto entre requisições:
Message-Driven Beans
MDB x “message listener”
Um MDB possui algumas diferenças quanto a um message
listener:
setMessageListener( ) não é invocado.
A associação do MDB com um destino e uma fábrica de
conexões é feita em tempo de deploy do bean para o container EJB.
Message-Driven Beans
MDB
Além de implementar os métodos ejbCreate( ), ejbRemove( )
e onMessage( ),
o MDB deve implementar o método:
void setMessageDrivenContext( MessageDrivenContext )
Este método será invocado
uma vez, antes de ejbCreate( ), para fornecer
um objeto MessageDrivenContext.
Message-Driven Beans
MDB
O MessageDrivenContext fornece um método útil para
utilização conjunta com container-managed transactions:
void setRollbackOnly( )
Este método marca a transação atual como falha, garantindo
que ela não receberá commit .
Ser invocado pelo MD quando uma exceção for lançada no
seu método onMessage( ),
garante o rollback da transação distribuída em que este recebimento de mensagem possa estar participando.
Message-Driven Beans
Exemplo - message-driven bean:
import javax.ejb.*;import javax.naming.*; import javax.jms.*;
public class MessageBean implements MessageDrivenBean, MessageListener {
private transient MessageDrivenContext mdc = null; private Context context;
Message-Driven Beans
Exemplo - message-driven bean:
public void setMessageDrivenContext(MessageDrivenContext mdc) { this.mdc = mdc; }
Message-Driven Beans
Exemplo - message-driven bean:
/* este MDB processa mensagens de texto */
public void onMessage(Message inMessage) { TextMessage msg = null;
try {
if (inMessage instanceof TextMessage) { msg = (TextMessage) inMessage;
System.out.println("MESSAGE BEAN: Message + "received: " + msg.getText());
} else {
System.out.println("Message of wrong type: " + inMessage.getClass().getName());
Message-Driven Beans
Exemplo - message-driven bean:
catch (JMSException e) {
System.err.println("MessageBean.onMessage: " + "JMSException: " + e.toString());
mdc.setRollbackOnly(); /* se transação: falhou */
} catch (Throwable te) {
System.err.println("MessageBean.onMessage: " + "Exception: + te.toString());
} }
JMS
Modelo de Programação JMS
Exemplo
Obtendo uma Connection Factory:
Obs.:
Invocar InitialContext( ) sem parâmetros resulta na busca
pelo arquivo jndi.properties
Context ctx = new InitialContext();
QueueConnectionFactory myQueueFact =
Modelo de Programação JMS
JEE Sun –
Criando destinos (filas e tópicos):
j2eeadmin -addJmsDestination <nome JNDI da fila> queue
j2eeadmin -addJmsDestination <nome JNDI do tópico> topic
obs.: válido para versão 1.3 (revisar nas seguintes)
Obtendo um destino no cliente, após criação:
Queue myQueue = (Queue) ctx.lookup( Nome JNDI da