descadastro
site NCE
 
 
J2EE
 
artigos publicados

Java Message Service (JMS)

 

Austeclynio Pereira
Pesquisador, NCE/UFRJ, M.Sc.

     
 

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.

 

 
avançar >>
         
 
    página principal
 
Núcleo de Computação Eletrônica
Universidade Federal do Rio de Janeiro
Prédio do Centro de Ciências Matemáticas e da Natureza Bloco C
Caixa Postal: 2324 - CEP: 20.010-974
Cidade Universitária - Ilha do Fundão, Rio de Janeiro - RJ Tel: 2598-3333