1.
Introdução
Projetado pela Sun MicroSystems com o apoio
de empresas associadas, e lançado para
o mercado em agosto de 1998, o JMS surgiu para
permitir que os aplicativos escritos na linguagem
Java pudessem criar, receber e enviar mensagens
destinadas ou oriundas de outros aplicativos.
A principal característica deste tipo
de processamento, classificado como fracamente
acoplado, é que todas as operações
que envolvem a troca de mensagens são
feitas de forma assíncrona, fazendo com
que as aplicações participantes
não precisem ficar bloqueadas esperando
o término de alguma computação
remotamente solicitada, como ocorre naquelas
aplicações que utilizam o Remote
Procedure Call(RPC) ou mesmo o Remote Method
Invocation(RMI). [1],[2],[3]
O JMS define formalmente um grupo de interfaces
e semânticas que permitem que aplicações
escritas em Java possam acessar os serviços
de qualquer Message-Oriented Middleware(MOM).
O MOM é um middleware que promove a integração
das operações de trocas de mensagens
intra e entre corporações, possibilitando
que elementos de negócio sejam intercambiados
de forma plenamente confiável. Algumas
das soluções MOM encontradas no
mercado são: o MQSeries da IBM, o Rendezvous
da TIBCO, SonicMQ da Progress, o FioranoMQ da
Fiorano, o MSMQ da Microsoft e o Sun ONE Message
Queue da Sun. Todas são soluções
não gratuitas porém a Sun disponibiliza
uma versão não corporativa, e
de poucos recursos, sem nenhum custo. [4],[5],[6],
[7]
Como exemplo de utilização de
um aplicativo baseado em troca de mensagens
do tipo MOM, podemos citar o caso de uma montadora
de automóveis que necessita enviar uma
nova lista de preços de seus veículos
para a sua rede de empresas concessionárias.
Se estivesse utilizando um sistema do tipo RPC,
ou mesmo RMI, haveria a necessidade de a montadora
estar conectada às suas concessionárias
em pelo menos algum instante para que a nova
lista pudesse ser obtida e atualizada. Caso
fosse uma aplicação utilizando
MOM, o aplicativo na concessionária produziria
a mensagem contendo a nova lista de preços
e enviaria a mensagem para o MOM. O MOM é
que ficaria encarregado de entregar, com segurança,
esta mensagem aos aplicativos das concessionárias.
O MOM responsabiliza-se por armazenar as mensagens
que serão enviadas e verificar se os
destinatários estão disponíveis
para recebe-las. Com isto, a montadora de automóveis
poderá enviar sua lista em qualquer instante,
pois terá a certeza que ela será
recebida por toda a sua rede de concessionárias
em algum momento. Por outro lado, as concessionárias
precisam apenas desenvolver o aplicativo que
irá fazer a recepção das
mensagens oriundas da montadora, e obviamente,
realizar os procedimentos rotineiros de atualização
de suas bases de dados. As concessionárias
também podem produzir mensagens. Seria
o caso, por exemplo, de recomposição
de seus estoques. A concessionária produz
a mensagem e envia para o MOM que por sua vez
ficará encarregado de encaminhá-la
para a montadora. Ambas as operações
foram realizadas de forma totalmente assíncrona.
Tanto a montadora quanto as concessionárias
fazem o intercâmbio de suas operações
sem que haja um acoplamento forte entre seus
aplicativos.
2. Componentes e modelos de uma aplicação
JMS
Uma aplicação JMS é composta
pelas seguintes partes:
-
JMS provider
- É um sistema de mensagens que implementa
uma especificação JMS.
-
Clientes JMS
- São as aplicações
Java que enviam e recebem as mensagens.
-
Mensagens
- São os objetos que serão
enviados para as aplicações
clientes.
A figura abaixo ilustra os principais
participantes de uma aplicação
baseada em JMS. O Message Queue Client Runtime
é a interface entre a aplicação
cliente e o JMS provider. Ele suporta todas
as operações necessárias
para as aplicações clientes enviarem
e receberem as mensagens.
Uma vez que o cliente criou a conexão
com o JMS provider mensagens podem ser produzidas
e consumidas. É importante ser observado
que uma mesma aplicação pode tanto
desempenhar o papel de produtora de mensagens
quanto de consumidora.
O JMS suporta dois diferentes modelos para a
distribuição de mensagens: point-to-point
e publish-subscribe.
Point-to-point
Este modelo é similar ao envio de uma
correspondência pelo serviço postal.
A mensagem é enviada para uma fila pela
aplicação produtora e então
é distribuída para uma aplicação
consumidora que está registrada para
aquela fila específica. A fila retém
todas as mensagens recebidas até que
elas sejam consumidas, ou até que a mensagem
expire.
Publish-and-Subscribe
Este modelo é similar ao sistema de assistir
a um canal de TV por assinatura. A mensagem
é produzida pela aplicação
produtora, distribuída para determinado
tópico (seria o canal da TV por assinatura)
e todas as aplicações consumidoras
que são assinantes do tópico podem
receber a mensagem. Aplicações
diferentes podem produzir mensagens para um
mesmo tópico e, se não houver
assinantes para o tópico, as mensagens,
por valor default, não ficam armazenadas.
3. Composição das mensagens
Uma mensagem JMS é composta pelas seguintes
partes:
-
Cabeçalho
-Presente em toda mensagem. Contém
informações para a identificação
e o direcionamento das mensagens. Produzido
pelo JMS provider e pela aplicação
produtora da mensagem.
-
Propriedades
-Presença opcional. Contém
valores que as aplicações
consumidoras podem utilizar para realizar
a filtragem das mensagens. Fornece informações
tais como a data e hora em que a mensagem
foi criada. Podem ser consideradas como
uma extensão do cabeçalho.
-
Corpo
-Define o tipo de mensagem que está
sendo enviada. São suportados seis
tipos de mensagens:
§ TextMessage: indica
que o corpo da mensagem contém uma
string Java.
§ MapMessage: indica
que o corpo da mensagem contém pares
nomes/valores. Cada nome
é uma string e cada valor é
um tipo primitivo Java.
§ BytesMessage:
indica que o corpo da mensagem contém
um stream de bytes não interpretados.
§ StreamMessage:
indica que o corpo da mensagem contém
um stream de tipos primitivos
Java.
§ ObjectMessage:
indica que o corpo da mensagem contém
um objeto Java do tipo serialized.
4. Produzindo e consumindo mensagens
A seguir são descritos os passos necessários
para que os aplicativos JMS possam produzir
e consumir mensagens. Todos os objetos e interfaces
necessários para as tarefas fazem partem
do pacote javax.jms, integrante padrão
da plataforma J2EE. São utilizados os
seguintes objetos e interfaces:
-
ConnectionFactory
-
Connection
-
Session
-
MessageProducer
-
MessageConsumer
-
Destination
O objeto ConnectionFactory é utilizado
para selecionar o tipo de conexão que
será feita com o JMS provider. Esta seleção
deve ser realizada tanto pela aplicação
produtora da mensagem quanto pela aplicação
consumidora. Existem dois tipos de instância
de ConnectionFactory: QueueConnectionFactory
que é utilizada para aplicações
do modelo point-to-point; e TopicConnectionFactory
que é utilizada para aplicações
do modelo publish-subscribe. Para localizar
o objeto ConnectionFactory pode ser utilizada
a interface Java Naming and Directory Interface(JNDI),
ou instanciá-lo diretamente especificando
seus atributos.
Após a instanciação do
modelo apropriado à necessidade da aplicação
(nada impede que os dois modelos possam ser
utilizados simultaneamente) deve ser feita a
conexão com o JMS provider, para tal
é utilizado o objeto Connection. Um objeto
Connection representa uma conexão ativa
entre uma aplicação cliente JMS
e um JMS provider. Para uma conexão no
modelo point-to-point utiliza-se o objeto QueueConnection,
e para uma conexão no modelo publish-subscribe
é utilizado o método TopicConnection.
Uma vez que a conexão ao JMS provider
tenha sido realizada com sucesso a próxima
etapa é iniciar uma sessão. Uma
sessão é representada pela interface
Session e é iniciada pelo objeto Connection.
A sessão é quem fornece o contexto
transacional com que as mensagens fluem entre
produtores e consumidores.
A interface Session possui duas sub-interfaces
diretas: TopicSession e QueueSession. Para criar
um objeto do tipo TopicSession utiliza-se o
método createTopicSession e para criar
um objeto do tipo QueueSession é utilizado
o método createQueueSession. Cada mensagem
distribuída pelo JMS provider para um
consumidor precisa ter seu recebimento acusado,
pois, caso contrário, a mensagem poderá
ser novamente enviada. Uma sessão pode
ser configurada para automaticamente acusar
o recebimento de cada mensagem recebida ou processada,
para tal, durante a criação da
sessão algum dos argumentos abaixo podem
ser utilizados:
-
AUTO_ACKNOWLEDGE
- A sessão automaticamente acusa
o recebimento de uma mensagem pelo JMS provider.
-
CLIENT_ ACKNOWLEDGE
- O consumidor acusa o recebimento da mensagem
acionando o seu método acknowledge.
-
DUPS_OK_ACKNOWLEDGE
- Instrui a sessão para realizar
a acusação de recebimento
a cada dez mensagens recebidas. Nesta seleção
a mesma mensagem pode ser recebida mais
de uma vez.
As sessões podem se enquadrar em dois
tipos distintos:
-
Transacted
- Uma sessão do tipo transacionada
significa que as mensagens serão
agrupadas antes de serem enviadas ou recebidas.
-
Non-transacted
- Indica que as mensagens serão enviadas
ou recebidas uma de cada vez.
Estes tipos são especificados durante
a criação da sessão, sendo
especificados como o primeiro argumento passado.
Uma sessão non-transacted deve ser especificada
como false enquanto uma sessão transacted
deve ser especificada como true. Adicionalmente,
em uma sessão transacted devem ser são
utilizados os métodos commit e rollback.
Com a sessão criada, é o momento
de ser definido o nome da fila para onde as
mensagens produzidas irão, se for utilizado
o modelo point-to-point, ou o nome do tópico,
no caso de ser publish-subscribe. Para tal é
utilizado o objeto Destination, que pode ser
instanciado através do JNDI ou diretamente.
O último passo é promover o envio
ou a recepção de mensagens. Para
enviar uma mensagem deve ser implementada a
interface MessageProducer. Esta interface também
possui duas sub-interfaces, QueueSender e TopicPublisher,
que identificarão o modelo que está
sendo utilizado. Para a recepção
das mensagens a interface é MessageConsumer
que também possui duas sub-interfaces,
QueueReceiver e TopicSubscriber, que, da mesma
forma, identificarão o modelo.
|