Primeiras aulas do curso JMS e ActiveMQ: Mensageria com Java

JMS e ActiveMQ: Mensageria com Java

Introdução ao Mensageria com ActiveMQ - Introdução ao Mensageria com ActiveMQ

Bem-vindo ao treinamento de mensageria, JMS e ActiveMQ.

Downloads desse capítulo

Loja virtual e geração de nota fiscal

Bom, temos uma loja virtual que já está no ar há algum tempo. Produtos são colocados em um carrinho de compra e no final o pedido é finalizado. Quando a compra é finalizada, enviamos os dados da compra para outro sistema responsável pela geração da nota. Até aí tudo bem.

Problemas de comunicação

Sabemos que eventos promocionais com black friday aumentam o número de acesso vertiginosamente. Queremos que nossa aplicação funcione, mas o problema é que o outro sistema pode falhar, inclusive pode haver algum problema de comunicação na rede e também ele pode não aguentar processar um grande número de informações enviadas. Não podemos perder um pedido só porque o sistema de geração de notas não funciona.

Para evitarmos os problemas que foram citados, precisamos desacoplar os dois sistemas através de um bloco arquitetural que ficará entre ambos. É uma espécie de servidor entre dois sistemas. Esse servidor é chamado de middleware e com ele o a loja virtual não conversa mais diretamente com o sistema de geração de notas fiscais. O objetivo do middleware é desacoplar os dois lados, isto é, as duas aplicações.

Agora, a loja enviará o pedido empacotando-o dentro de um envelope para o middleware que guardará a mensagem recebida e algum momento depois a entregará para o sistema de nota fiscal (assíncrono). Esse processo é orientado à mensagens, por isso que é chamado de MOM (Message Oriented Middleware).

Então, dentro do que vimos, percebemos o desacoplamento arquitetural entre a loja e o sistema de notas (um sistema deixar de conhecer o outro) e todo comunicação é via mensagem. A mensagem é recebida pelo middleware e algum momento posterior, é entregue para o sistema destinarário. Justamente por ser “um momento posterior” tudo ocorre assincronamente, pois não sabemos quando a mensagem será entregue.

ActiveMQ, o MOM da Apache Foundation

Para implementarmos essa solução, precisamos de um middleware e o mais famoso no mundo Java se chama ActiveMQ da Apache Foundation. Usaremos o ActiveMQ ao longo deste treinamento, um MOM da Apache.

Primeiro passo é instalar o ActiveMQ.

Instalando o ActiveMQ

Baixamos o ActiveMQ 5.12.x (ou mais recente) em http://activemq.apache.org/download.html.

Observação: No Windows é preciso executar o script InstallService.bat da pasta win32 ou win64 dependendo da arquitetura do computador.

Depois de baixado, só precisamos descompactá-lo. Como todo servidor, precisamos rodá-lo e fazemos através do terminal entrando na pasta apache-activemq-5.12.2/bin. Lá uma série de scripts e precisamos rodar aquele que condiz com o sistema operacional que estamos usando. Por exemplo, no OSX usamos no terminal o comando

sh activemq

Só que não foi dessa vez. A razão é que precisamos passar parâmetros para esse script. Usarmos a opção console:

sh activemq console

Agora sim. Além de subir nosso servidor, ele nos apresenta uma série de logs. O terminal também indica o endereço do nosso servidor: http://localhost:8161

Visualizamos a página principal do ActiveMQ. Há um link (http://localhost:8161/admin) para o console de administrar. Ao ser clicado, precisamos um usuário e uma senha. O login e senha padrão são admin.

A primeira fila

É bem simples, porém há informações que já são úteis como o nome da máquina que está rodando, versão do servidor, etc. Podemos até enviar já mensagens através do link send. Há também duas opções, queues e topics. Vamos focar no primeiro, pois nossa loja quer enviar uma mensagem com o pedido empacotado a esse MOM. O MOM poderia ter vários outros clientes, isto é, aplicações. Não simplesmente entregamos a mensagem para o MOM, nós indicamos também qual o destino desta mensagem. A mensagem do pedido enviado para o MOM fica cadastrado dentro de uma fila (queue) para o ActiveMQ organizar, inclusive poderíamos ter várias filas. O topic, que não vamos utilizar agora, é um outro destino.

Clicando em queue, é perguntada o nome da fila que chamaremos de financeiro. Podemos acessar a fila criada e seus consumidores (quem gostaria de receber) e os active producers, quem está enviando. Há uma opção de enviar uma mensagem para a fila e é exatamente o que faremos.

Enviando a mensagem

Na tela de envio de mensagem, precisamos informar qual é o destino, mas não apenas isso. Há um monte de cabeçalhos da mensagem que podemos preencher quando necessário.

Na caixa “Message Body” vamos escrever: Oi mundo mensageria!

Uma mensagem foi enviada, ela está enqueued. Isso signiica que a fila recebeu e guardou, salva. Que tal enviarmos mais uma mensagem? Dessa vez será “Oi! Mensageria segunda mensagem”. As mensagem ficam enqueued, mas nenhum foi entregue pois ainda não temos um consumidor.

Simulando a entrega

Vamos simular essa entrega para nossa aplicação de nota fiscal que tem interesse em receber essas mensagens. Para isso, preparamos um jar com código Java que consumirá a mensagem, mas ele não possui todo o protocolo possível do ActiveMQ, é por isso que da pasta do ActiveMQ que baixamos, vamos mover o activemq-all-5.12.0.jar. Resumindo: nosso aula-jms.jar depende de ativemq-all-5.12.0.jar.

Sem fechar o terminal do ActiveMQ que está rodando, vamos abrir um novo terminal e executar:

No Linux e Mac:

java –cp activemq-all-5.12.0.jar:aula-jms.jar br.com.caelum.TesteMensageria consome

No Windows:

java –cp activemq-all-5.12.0.jar;aula-jms.jar br.com.caelum.TesteMensageria consome

Nosso programa se conectou ao nosso MOM e recebeu as mensagens que cadastramos.

Podemos enviar mensagens na linha de comando também usando o parâmetro envia seguido com a quantidade de números :

No Linux e Mac:

java –cp activemq-all-5.12.0.jar:aula-jms.jar br.com.caelum.TesteMensageria envia 10

No Windows:

java –cp activemq-all-5.12.0.jar;aula-jms.jar br.com.caelum.TesteMensageria envia 10

Neste exemplo, estamos enviando 10 mensagens. Agora em nosso MOM, temos 10 mensagens. Ao testar a consumidor (recebimento das mensagens) aparece no console:

Agora vamos praticar com os exercícios do capítulo.

Consumindo mensagens com JMS - Consumindo mensagens com JMS

No primeiro capítulo, tivemos uma introdução de o que é um MOM, como ele desacopla o produtor do consumidor da mensagem, e que a entrega das mesmas é feita de forma assíncrona. Neste segundo capítulo do curso, queremos entrar nos detalhes do código, criar um consumidor e dar início a nossa aplicação.

JMS - A API de mensageria

Vimos um dos MOM's mais famosos do mundo Java, que é o ActiveMQ. Porém ele não é o único, e a própria ideia de MOM's é bem antiga. Existe uma série de servidores e middlewares no mercado, como: IBM WebSphere, WebLogic Server Messaging, HornetQ, Artemis, Apollo ...

Imagine agora, que para produzir ou consumir mensagens a partir do código java, devemos aprender sempre a API específica desses MOM's. Porém, no final, a gente sempre cria mensagem e recebe mensagem. Para facilitar o trabalho do desenvolvedor, foi criado um padrão JavaEE em cima dessa ideia de mensageria, que é o JMS (Java Messaging Service).

Continuaremos usando o ActiveMQ, porém o código que estaremos utilizando, serve também para um IBM WebSphere ou para um WebLogic Server Messaging. Muda muito pouco o código Java necessário para consumir ou escrever mensagens, e por debaixo dos panos, continuamos a usar o ActiveMQ.

Criação do projeto

Agora, vamos rapidamente subir o ActiveMQ, do mesmo jeito que foi feito na aula anterior(com o parâmetro 'console' na linha de comando) e acessar com "User Name: admin / Password: admin".

Para começar com os códigos, precisamos abrir também o eclipse JavaEE, e criar um projeto Java padrão. Usaremos o Java 1.8 como JRE e o nome será jms. Precisamos do arquivo do ActiveMQ no nosso projeto. Para isso, clique com o botão direito no projeto, New -> folder. Chame essa pasta de lib e então, arraste o arquivo do ActiveMQ activemq-all-5.12.0.jar para dentro dela. Após isso, dentro do eclipse, clique com o botão direito no JAR copiado e Build Path -> Add to Build Path.

Criando uma Conexão com o ActiveMQ

Com a importação do .jar feita, podemos começar com o nosso código. Crie uma classe TesteConsumidor no pacote br.com.caelum.jms. Usaremos o tempo todo importações da biblioteca javax.jms.

Criaremos uma conexão. Porém, da onde vem a nossa ConnectionFactory? O MOM vai te fornecer! A ideia é que quando o MOM é inicializado, que ele ja disponibilize essa conexão dentro de um registro. Com isso, precisamos apenas pegar essa conexão dentro de um registro, e esse é o JNDI. O nome utilizado no lookup é apresentado na documentação do MOM.

public class TesteConsumidor {
    public static void main(String[] args) throws Exception{

        InitialContext context = new InitialContext(); 

        //imports do package javax.jms
        ConnectionFactory factory = (ConnectionFactory) context.lookup("ConnectionFactory");
        Connection connection = factory.createConnection();
        connection.start();

        new Scanner(System.in).nextLine(); //parar o programa para testar a conexao

        connection.close();
        context.close();
}

Além disso, devemos criar um arquivo jndi.properties na pasta src que copiamos do site do ActiveMQ:

java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory

# use the following property to configure the default connector
java.naming.provider.url = vm://localhost

# use the following property to specify the JNDI name the connection factory
# should appear as. 
#connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactry

# register some queues in JNDI using the form
# queue.[jndiName] = [physicalName]
queue.MyQueue = example.MyQueue

# register some topics in JNDI using the form
# topic.[jndiName] = [physicalName]
topic.MyTopic = example.MyTopic

Subindo o ActiveMQ em memória

Ao rodar o código aparentemente foi estabelecida uma conexão com ActiveMQ como previsto. Vamos verificar isso no console de administração do ActiveMQ. Para nossa supresa não aparece nenhuma conexão. O que aconteceu? A resposta está no arquivo jndi.properties. Repare a linha:

vm://localhost

o vm indica que o ActiveMQ subiu em memória. O ActiveMQ não precisa rodar em sua JVM dedicada. O nosso código Java não só estabeleceu uma conexão como também criou uma nova instancia do ActiveMQ! Mas com certeza isso não foi a nossa intenção pois já subimos o ActiveMQ antes separadamente. Vamos mudar isso e alterar a linha no jndi.properties:

java.naming.provider.url = tcp://localhost:61616

Rodando nossa classe de teste, vemos que não imprime nada no console, mas ao entrarmos na console de administração do (http://localhost:8161/admin/connections.jsp) ActiveMQ -> Connections, observamos que há uma nova conexão com o ID da sua máquina local.

Criando um MessageConsumer

Agora queremos criar um Consumer, que irá receber nossas mensagens.

public class TesteConsumidor {
//cria context, factory, connection

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination fila = (Destination) context.lookup("financeiro");
MessageConsumer consumer = session.createConsumer(fila);

Message message = consumer.receive();
System.out.println("Recebendo msg: "+ message);

session.close();
//fecha conexões
}

Ja tinhamos nossa fila de consumo, que foi criada na primeira aula. Sendo assim, o ActiveMQ disponibiliza no jndi.properties, e acessamos pelo lookup. Porém, precisamos configurar o arquivo de properties para ele saber o que procurar.

Dentro do JNDI, temos a linha:

# queue.[jndiName] = [physicalName]
Queue.MyQueue = example.MyQueue

Na direita, fica o nome da fila que foi criada no ActiveMQ, que no nosso caso é fila.financeiro. Na esquerda, fica o nome na qual usaremos para referenciar essa fila no código Java. Substituindo:

queue.financeiro = fila.financeiro

Testando o consumidor

Assim, ja podemos acessar o nosso consumer do ActiveMQ pelo nosso código Java. Criamos também uma Message que irá receber uma mensagem do consumer e printá-la no nosso console. Rodamos a classe para criar o nosso MessageConsumer:

Agora para testar, enviamos uma mensagem através da console de administração.

E no console...

Queremos agora que nossa aplicação fique online, que o MessageConsumer consiga receber essas mensagens o tempo todo e não só uma mensagem. Essa configuração, iremos aprender mais a frente. Agora é a hora dos exercícios.

Recebendo mensagens com MessageListener - Recebendo mensagens com MessageListener

Começando deste ponto? Você pode fazer o DOWNLOAD completo do projeto do capítulo anterior e continuar seus estudos a partir deste capítulo.

No capítulo anterior conseguimos estabelecer uma conexão utilizando a fábrica disponibilizada pelo ActiveMQ, através do InitialContext. E a partir dessa conexão que inicializamos, criamos a nossa sessão, que faz o recebimento e a confirmação das mensagens.

Da nossa Session, criamos um MessageConsumer, que fica escutando mensagens da fila (Destination) que pegamos do nosso InitialContext. E conseguimos obter nossa mensagem através do método consumer.receive().

Tratador de mensagem

O problema que encontramos no último capítulo, é que nosso sistema recebia apenas uma mensagem e encerrava o seu funcionamento, e não é isso que queremos. Nos esperamos que ele fique escutando o tempo todo por mensagens, e para isso , devemos cadastrar um novo objeto no nosso consumer, com o responsabilidade de tratar as mensagens que recebemos.

Para manter a separação de responsabilidades, vamos fazer com o que Consumer delegue o tratamento das mensagens para um objeto da interface MessageListener:

consumer.setMessageListener();

E para usar esta interface, vamos utilizar uma classe anônima MessageListener que a implementa:

consumer.setMessageListener(new MessageListener(){

});

E nesta classe devemos implementar o método chamado onMessage, que recebe a mensagem e a faz algum processamento com ela. Por enquanto vamos apenas exibi-la no console:

consumer.setMessageListener(new MessageListener(){

    @Override
    public void onMessage(Message message){
        System.out.println(message);
    }

});

Removendo a linha System.out.println("Recebendo msg: " + message");, podemos ir na página de envio de mensagens do ActiveMQ testar que o nosso método onMessage funciona, e enviar diversas mensagens sem que o nosso sistema se encerre.

Repare que apesar de enviarmos apenas mensagens de texto, no nosso console aparece algo do tipo:

ActiveMQTextMessage {commandId = 7,responseRequired = false, messageId = ID, message="Sua mensagem aqui!!"}

Subinterfaces da Message

Isto ocorre pois estamos usando a interface Message, que possui subinterfaces mais específicas, que podemos utilizar para pegar o texto da mensagem mais diretamente.

Primeiro vamos pegar a mensagem que estamos recebendo e fazer um cast dela para uma das suas subinterfaces, a TextMessage, já que estamos trabalhando com mensagens de texto:

consumer.setMessageListener(new MessageListener(){

    @Override
    public void onMessage(Message message){
        TextMessage textMessage  = (TextMessage)message;
        System.out.println(message);
    }

});

Agora que temos uma TextMessage podemos utilizar o método getText() para pegar apenas o texto da mensagem, deixando assim o resultado mais elegante:

consumer.setMessageListener(new MessageListener(){

    @Override
    public void onMessage(Message message){
        TextMessage textMessage  = (TextMessage)message;
        System.out.println(textMessage.getText());
    }

});

Como esta API é um pouco antiga, o Eclipse deve reclamar dizendo que o método getText joga uma exceção , então devemos envolve-lo com um try-catch:

consumer.setMessageListener(new MessageListener(){

    @Override
    public void onMessage(Message message){
        TextMessage textMessage  = (TextMessage)message;
        try{
            System.out.println(textMessage.getText());
        } catch(JMSException e){
            e.printStackTrace();
        }    
    }

});

Testando agora vemos que as nossas mensagens aparecem muito mais limpas no console:

Sobre o curso JMS e ActiveMQ: Mensageria com Java

O curso JMS e ActiveMQ: Mensageria com Java possui 167 minutos de vídeos, em um total de 75 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

  • 1056 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

Premium

  • 1056 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$75
à vista R$900
Matricule-se

Premium Plus

  • 1056 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$100
à vista R$1.200
Matricule-se

Max

  • 1056 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$120
à vista R$1.440
Matricule-se
Procurando planos para empresas?
Acesso por 1 ano
Estude 24h/dia onde e quando quiser
Novos cursos toda semana