Informações
| Tipo: | Tutorial |
|---|---|
| Data de Publicação: | 01/01/2004 |
| Revisado em: | 01/01/2004 |
Vote!
Tags Relacionadas
Comentários ( 1 )
Imprimir
Introdução a Message Driven Beans
por:
Ulisses Telemaco (ulisses@j2eebrasil.com.br)
Gleydson Lima (gleydson@jeebrasil.com.br)
Este tutorial apresentará conceitos relacionados Ao Message Drive Beans. Antes de iniciarmos nosso estudo sobre os conceitos e etapas relacionados ao desenvolvimento de componentes do tipo Message Driven Beans, vamos discutir um pouco sobre as motivações que levaram ao desenvolvimento desse tipo de componente.
1. Introdução
Os componentes EJB vistos até aqui (Session Beans) usam um protocolo de invocação remota (RMI ou RMI-IIOP) para receber solicitações de aplicações clientes. Esses protocolos exigem uma comunicação síncrona e bloqueante, ou seja, o cliente deve ficar em espera enquanto o servidor realiza o processamento e envia a resposta ao cliente.
A Figura 1 mostra a seqüência de uma comunicação síncrona.
Figura 1 - Seqüência de Comunicação Síncrona
A sequência ilustrada na Figura 1 pode ser descrita da seguinte forma:
- O cliente localiza o componente EJB no servidor;
- O cliente solicita a execução de determinado método sobre o componente;
- O componente processa, enquanto o cliente aguarda sua resposta;
- O cliente recebe a resposta e só então está liberado para seguir seu processamento.
Esse simples modelo traz duas limitações (ou desvantagens para os mais negativos): A primeira delas é o fato do cliente ter que esperar por uma resposta do componente para prosseguir sua execução. É verdade que em alguns casos esse espera é impossivel de ser evitada, por exemplo, os casos onde o cliente depende da resposta do componente para prosseguir. No entanto, existem casos em que o cliente não precisa de nenhuma resposta do componente para continuar seu serviço.
A segunda limitação está relacionada ao fato de o cliente deve conhecer a interface remota do componente para conseguir invocar algum método no EJB. Esse fato cria uma dependência entre esses dois elementos. Uma mudança da interface remota do componente deve ser refletida também na interface que o cliente conhece. O ponto negativo aqui é o acoplamento entre os clientes e os componentes.
Os componentes Message-Driven Beans surgem com uma proposta para resolver esses problemas. A idéia é fazer a comunicação entre o cliente e o componente de forma assíncrona através da troca de mensagens entre os envolvidos. Não iremos discutir de forma exaustiva os conceitos introdutórios sobre comunicação assincrona através de mensagens em Java. Para isso, sugerimos como leitura fundamental os tutoriais introdutórios de JMS (Java Message Service) providos aqui.
O modelo de troca de mensagens funciona, simplificadamente, da seguinte forma: O cliente, envia mensagens para uma estrutura que as armazena. Os componentes Message-Driven Beans processam conteúdos oriundos de uma fila de mensagens. Quando uma mensagem é recebida o Container se encarrega de entregá-la ao componente, que executa o código de negócio. A Figura 2 abaixo ilustra o funcionamento:
Figura 2 - Modelo de Troca de Mensagens
A sequência ilustrada na Figura 2 pode ser descrita da seguinte forma:
- A aplicação que deseja invocar um componente Message-Driven Bean envia uma mensagem para uma fila;
- O servidor de aplicações recebe a mensagem e repassa para o componente;
O componente processa a mensagem e nada retorna para o cliente.
Veja que esse modelo soluciona os problemas relacionados anteriormente. Agora o cliente envia a mensagem para o servidor de aplicações sem ficar bloqueado esperando alguma resposta do componente.
Além disso, os componentes Message-Driven Beans não possuem interface Home e Remote, pois nenhum protocolo de invocação remota é utilizado. Como eles processam mensagens oriundas de qualquer cliente que seja capaz de produzir uma mensagem JMS válida, existe o mínimo de dependência possível.
A função desta categoria de componente é consumir mensagens de uma fila e realizar o processamento sobre o dado consumido. Dessa forma, não faz sentido termos diversos métodos de negócio nesse componente, apenas um método de processamento de mensagens, denominado onMessage(). Esse processamento deve ser feito também de forma totalmente independente do cliente. Nenhum retorno ou exceção pode ser retornado para o cliente.
2. Desenvolvendo Message-Driven Beans
Message-Driven Beans são classes que implementam duas interfaces:
Na Listagem 1 está o código dessas duas interfaces.
public interface javax.jms.MessageListener{
public void onMessage(Message message);
}
public interface javax.ejb.MessageDrivenBean extends javax.ejb.EnterpriseBean {
public void ejbRemove() throws EJBException;
public void setMessageContext(MessageDrivenContext ctx) throws EJBException;
}
Listagem 1 - Interfaces Implementadas pelos Message-Drive Beans
A interface javax.jms.MessageListener define o método onMessage (o único método de negócio do componente Message-Driven Bean). Esse realiza o processamente das mensagens consumidas. É necessario identificar o tipo de mensagem e efetuar um cast para um dos cinco tipos de mensagens JMS. Para executar o processamento da mensagem, o MSB pode invocar outros métodos de ajuda ou mesmo um Session Bean.
A interface javax.ejb.MessageDrivenBean define outros dois métodos callback: ejbRemove, chamado quando o servidor de aplicações decidir remover o objeto em questão. O método setMessageContext, por sua vez, informa a instância do componente o contexto de execução do Message-Driven Bean.
Todas as instâncias de um MSB são equivalentes e não mantém nenhuma informação sobre o cliente ou outro contexto. Dessa forma, não é necessário fornecer métodos construtor (ejbCreate) para esse tipo de componente. A criação dos MSBs é de responsabilidade do Container.
Assim como acontece com os Session Stateless Bean, o Container pode criar um Pool de MSBs e permitir o processamento concorrente de várias mensagens.
3. Ciclo de Vida de um MDB
A Figura 3 ilustra o ciclo de vida de um MDB.
Figura 3 - Clico de Vida de um MDB
Assim como os Stateless Session Bean, os MDBs nunca são passivados e portanto possuem dois estados: "não existe" e "pronto para receber mensagens". No fim do ciclo de vida, o container chama o método ejbRemote e o componente está pronto para ser coletado pelo coletor de lixo.
4. Transações
Uma mensagem deve ser consumida dentro de uma transação. Assim, todas as operações dentro do método onMessage fazem parte de uma única transação. Se o processamento de uma mensagem for "rolled back", a mensagem será devolvida para a fila de mensagens.
5. Implementando um simples Message-Driven Bean
O código da Listagem 2 é a implementação de um Message-Driven Bean que recebe uma mensagem e imprime na tela.
package br.com.j2eebrasil.artigo.ejb;
import javax.ejb.*;
import javax.jms.*;
public class MessageBean implements MessageDrivenBean, MessageListener {
protected MessageDrivenContext contexto;
/* Chamado quando o Bean for inicializado */
public void ejbCreate() {
System.out.println("Componente Criado");
}
/* Informa o contexto a implementação do componente */
public void setMessageDrivenContext(MessageDrivenContext ctx) {
contexto = ctx;
}
/* Método da lógica de negócio */
public void onMessage(Message msg) {
if (msg instanceOf TextMessage) {
TextMessage msgTexto = (TextMessage) msg;
try {
System.out.println("O texto informado " + msg.getText() );
}
catch (JMSException e ) {
e.printStackTrace();
}
}
}
/* Remove o Bean */
public void ejbRemove() {
System.out.println("Sendo removido");
}
}
Listagem 2 - Implementação de MDB que Recebe Mensagem
O método onMessage imprime a mensagem recebida. Em situações reais esta mensagem poderia acionar um outro componente de negócio, ser armazenada em banco de dados, ou qualquer outra operação de negócio.
6. Configurando o componente
É no deployment descriptor que configuramos o componente e definimos qual será a fila que o componente irá escutar por mensagens, qual o comportamento transacional, aspectos de segurança etc. Na Listagem 3 temos o deployment descriptor do Message-Driven Bean listado anteriormente.
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <enterprise-beans> <message-driven> <!-- O nome do componente --> <ejb-name>J2EEBrasilMDB</ejb-name> <!-- Classe do componente --> <ejb-class>examples.LogBean</ejb-class> <!-- Tipo de transação --> <transaction-type>Container</transaction-type> <!-- Fila associada com o componente --> <message-driven-destination> <destination-type>javax.jms.Queue</destination-type> </message-driven-destination> </message-driven> </enterprise-beans> </ejb-jar>
Listagem 3 - Deployment Descriptor do MDB Anterior
Note que nos parâmetros configurados acima não especificamos qual será o nome da fila. Isso deve ser especificado no deployment descriptor específico do servidor de aplicações.
Isso se deve ao fato dos nomes das filas implantadas no servidor de aplicações serem específicos. Informando o nome da fila na configuração específica do servidor de aplicações tornamos o componente mais portável.
7. Conclusão
Os Message-Driven Beans possuem uma importância fundamental na arquitetura J2EE por fornecer a possibilidade de comunicação assíncrona e desacoplada entre componentes.
Os MDBs estão intimamente relacionados com a API JMS (Java Message Service). Assim, recomendamos fortemente uma leitura nos módulos introdutórios dessa tecnologia disponíveis aqui no J2EEBrasil.
O exemplo ilustrado nesse tutorial não exemplifica o desenvolvimento de um MDB em um container específico nem ilustra como enviar mensagens para serem consumidas. O próximo módulo do tutorial de MDB, no entanto, traz um exemplo mais completo envolvendo o desenvolvimento de uma pequena aplicação MOM (Message-Oriented Middleware) sendo projetada e executada no container JBoss.
Comentários (1)
- Complementando, o 'destination-type' determina em que tipo de fila as mensagens serão enviadas e isto tem uma importância significativa dependendo do que se quer com o componente. Pode ter: - javax.jms.Queue (point to point): quando uma mensagem chega ela é entregue uma de cada vez; - javax.jms.Topic (publish and subscribe): as mensagens são entregues em um 'broadcast' aos 'subscribers'; É interessante desenvolver um pouco mais este assunto. T+
- postado por José Renato em 09/04/2008 às 23:21
