Hello JMS

Jakarta Messaging - antes conhecida apenas como Java Message Service - (JMS) é a API que especifica como aplicações Java Enterprise enviam e recebem mensagens através de um Message Oriented Middleware (MOM). MOMs são um componente essencial para integração de operações entre sistemas corporativos diferentes.

Mensagens

O conceito de mensagem possui uma definição bastante ampla na computação. No contexto do JMS, mensagens são requisições assincronas ou eventos que são produzidos ou consumidos pelas aplicações. Essas mensagens geralmente contêm informações vitais necessárias para a coordenação entres os diferentes sistemas.

Arquitetura do JMS

Em um alto nível, a arquitetura do JMS consiste nos seguintes componentes:

  • Provider: JMS é apenas uma API, então ela precisa de uma implementação que efetivamente direcione as mensagens, ou seja, o provider, também conhecido como message broker.

  • Client: a aplicação que produz ou consome mensagens atraves de algum provider.

  • Messages: os objetos que os clientes enviam ou recebem dos providers.

  • Administered Objects: objetos disponibilizados pelos brokers ao cliente (conexão e destino).

Os providers habilitam a comunicação assíncrona disponibilizando um destino, que é o lugar onde as mensagens ficam até que sejam consumidas pelo cliente. Com base no destino, há 2 tipos de modelos de envio de mensagens:

  • Point to Point (P2P): 1 mensagem destinada a um único consumidor

  • Publish-Subscribe (pub-sub): 1 mensagem para N consumidores

Hello JMS

Criemos agora um exemplo de uma aplicação JEE que:

  1. através de um timer, envia uma mensagem para uma fila chamada HelloQueue a cada 3 segundos.

  2. um tópico chamado PurchaseTopic que é observado pelo Operador de Cartão de Crédito e pelo Departamento Financeiro, ou seja, toda vez que uma operação de cartão de crédito chega nesse Tópico, as respectivas áreas são notificadas.

Como servidor de aplicação, usaremos Payara Application Server, que tem como message broker default o OpenMQ instalado na pasta <PAYARA_HOME>/mq/bin

Para iniciar o payara executamos o binário asadmin localizado em

<PAYARA_HOME>/glassfish/bin

depois o comando start-domain

O console administrativo do payara pode ser acessado por padrão na porta 4848:

other images...

Enviando Mensagens para jms/HelloQueue

@Stateless
@LocalBean
public class TimedQueueProducer {

    @Inject
    private JMSContext jmsContext;

    @Resource(lookup = "jms/HelloQueue")
    private Queue queue;

    @Schedule(hour = "*", minute = "*", second = "*/3", info = "Every 3 seconds", timezone = "UTC", persistent = false)
    public void sendToQueue() {

        TextMessage textMessage = jmsContext.createTextMessage("New Text Message");
        JMSProducer producer = jmsContext.createProducer();

        producer.send(queue, textMessage);
    }
}

TimedProducer é um EJB, o método sendToQueue é anotado com @Schedule cujos parâmetros configuram para que seja chamado a cada 3 segundos. Esse método cria uma mensagem do tipo texto e envia para a queue.

Depois criamos uma classe que consome cada mensagem enviada para HelloQueue. Chamamos de QueueReceiver.

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/HelloQueue")
})
public class QueueReceiver implements MessageListener {

    private final static Logger LOG = Logger.getLogger(QueueReceiver.class.getName());

    @Override
    public void onMessage(Message message) {

        TextMessage textMessage = (TextMessage) message;
        try {
            LOG.info(">>> received: " + textMessage.getText());
        }
        catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

QueueReceiver é anotada com @MessageDriven, o que a torna um consumidor assíncrono, isto é, o método onMessage é chamado pelo container sempre quando uma nova mensagem chega na fila especificada.

Quando a mensagem chega, ela é registrada nos logs do payara, localizado em <PAYARA_HOME>/glassfish/domain/domain1logs/server.log