Exemplo completo com JSF Primefaces + EJB + Hibernate + MySQL + JMS
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/feltexco/public_html/felix/wp-content/plugins/wp-syntax/wp-syntax.php on line 380
Exemplo completo com JSF Primefaces + EJB + Hibernate + MySQL + JMS
Olá Amigos,
Continuando o trabalho de implementação do projeto AcademicNet incluiremos o uso de Filas. Vamos trabalhar tanto com Queue como Topic para nosso Exemplos.
Tarefas:
- – Configuração da Fila no servidor
- – Criação de componentes para consumir as filas
- – Criação do Servlet que enviará uma mensagem para a fila
- – Trabalhar com Queue fila de Aluno
- – Trabalhar com Topic fila de Professor
Veja como ficará o nosso exemplo:
Tipos de filas:
Queue – Fila de mensagens que Point-to-Point (Ponto a ponto). Neste caso há um cliente e um consumidor de mensagens.
Topic – Fila de mensagens Publish-Subscribe (Publicação e consumo). Neste caso há um cliente e vários consumidores das mensagens.
MDB – Message Drive Bean é um tipo especial de EJB que consegue consumir as mensagens disponibilizadas nas filas JMS. Ele tem todas as característica de um EJB (transação, gerenciamento de contexto) e precisa implementar uma Interface “MessageListener” que fica monitorando as mensagens que entram na fila.
Para que sua fila funciona é necessário fazer uma configuração no servidor..
Inclusão da configuração das filas
Acesse o arquivo “wildfly-8.0.0.Final\standalone\configuration\standalone.xml”. Localize a tag
“hornetq-server”. Adicione o seguinte conteúdo entre a tag inicial e final.
1 2 3 4 5 6 7 8 9 10 | <jms-destinations> <jms-queue name="alunoQueue"> <entry name="queue/alunoQueue"/> <entry name="java:jboss/exported/jms/queue/alunoQueue"/> </jms-queue> <jms-topic name="professorTopic"> <entry name="topic/professorTopic"/> <entry name="java:jboss/exported/jms/topic/professorTopic"/> </jms-topic> </jms-destinations> |
Criação dos consumidores MDB (Message Drive Bean)
Nesta parte criaremos o MDB que consumirá a fila de alunos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package br.com.feltex.academicnet.mdb; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.ObjectMessage; import javax.jms.TextMessage; import br.com.feltex.academicnet.entidade.Aluno; /** * Message-Driven Bean implementation class for: AlunoMDB */ @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/queue/alunoQueue") }, mappedName = "java:/queue/alunoQueue") public class AlunoQueueMDB implements MessageListener { public AlunoQueueMDB() { } public void onMessage(Message message) { System.out.println(getClass() + " Inicio"); try { if (message instanceof TextMessage) { TextMessage mensagem = (TextMessage) message; System.out.println("Mensagem recebida: " + mensagem.getText()); } else if (message instanceof ObjectMessage) { try { ObjectMessage obj = (ObjectMessage) message; Aluno aluno = (Aluno) obj.getObject(); System.out.println("Objeto Recebido: " + aluno); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } System.out.println(getClass() + " Fim"); } } |
Vamos analisar o código:
@MessageDriven – Esta anotação define que a sua classe é um MDB e que poderá consumir mensagens de uma fila JMS
@ActivationConfigProperty(propertyName = “destinationType”, propertyValue = “javax.jms.Queue”),
@ActivationConfigProperty(propertyName = “destination”, propertyValue = “java:/queue/alunoQueue”)},
mappedName = “java:/queue/alunoQueue”)
Nas declarações de “ActivationConfigProperty” definimos que tipo de fila estamos utilizando. Neste caso é uma Queue e qual o nome da fila “queue/alunoQueue”.
O nosso MDB deve implementar a interface “MessageListener” que define o método “onMessage()”. Esse método é o responsável por executar as ações de consumo da mensagem.
O método recebe como parâmetro um objeto do tipo Message. Nele teremos o conteúdo que foi disponibilizado pelo cliente (produtor da mensagem).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public void onMessage(Message message) { System.out.println(getClass() + " Inicio"); try { if (message instanceof TextMessage) { TextMessage mensagem = (TextMessage) message; System.out.println("Mensagem recebida: " + mensagem.getText()); } else if (message instanceof ObjectMessage) { try { ObjectMessage obj = (ObjectMessage) message; Aluno aluno = (Aluno) obj.getObject(); System.out.println("Objeto Recebido: " + aluno); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } System.out.println(getClass() + " Fim"); } |
No nosso caso é verificado o tipo da mensagem. Se é uma mensagem do tipo texto (TextMessage) converteremos o conteúdo em texto. Se for do tipo ObjectMessage converteremos em um objeto do tipo Aluno, pois a nossa fila é de objetos aluno.
Atenção: Se for colocado um objeto diferente de Aluno na fila haverá erro na execução da fila.
Criação do Servlet produtor da mensagem
Código utilizando o padrão JMS 1.1 contido na especificação JEE 6.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | package br.com.feltex.academicnet.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.annotation.Resource; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.jms.Session; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import br.com.feltex.academicnet.entidade.Aluno; @WebServlet("/AlunoServletJMS") public class AlunoServletJMS extends HttpServlet { private static final long serialVersionUID = 1L; @Resource(mappedName = "java:/queue/alunoQueue") private Queue fila; @Resource(mappedName = "java:/ConnectionFactory") private ConnectionFactory connectionFactory; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(getClass() + "Inicio........"); Aluno aluno = new Aluno(); aluno.setMatricula(2221L); aluno.setNome("Maria da Silva"); enviarObjetoForma1(aluno); System.out.println(getClass() + "Fim........"); PrintWriter out = response.getWriter(); out.print("<H1>Objeto enviado com sucesso! JMS 1.0</H1>"); } /** * Envia um objeto complexo para a fila JMS * * @param aluno Classe de entidade * Esta forma de envio é a mais conhecida e utilizada atualmente */ public void enviarObjetoForma1(Aluno aluno) { try { Connection connection = connectionFactory.createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); ObjectMessage objMessage = session.createObjectMessage(); objMessage.setObject(aluno); MessageProducer messageProducer = session.createProducer(fila); messageProducer.send(objMessage); messageProducer.close(); } finally { connection.close(); } } catch (JMSException ex) { ex.printStackTrace(); } } } |
Encontramos 2 anotações do tipo “resource”. A primeira faz o mapeamento para a fila que usaremos para gravar a fila. E na segunda anotação temos o apontamento para a Fábrica de conexão com de fila.
@Resource(mappedName = “java:/queue/alunoQueue”)
private Queue fila;
@Resource(mappedName = “java:/ConnectionFactory”)
private ConnectionFactory connectionFactory;
No método doPost(…) há uma chamada para o método “enviarObjetoForma1(Aluno aluno)” que é responsável por instanciar a fila e enviar a mensagem. Vejamos como é método.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public void enviarObjetoForma1(Aluno aluno) { try { Connection connection = connectionFactory.createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); ObjectMessage objMessage = session.createObjectMessage(); objMessage.setObject(aluno); MessageProducer messageProducer = session.createProducer(fila); messageProducer.send(objMessage); messageProducer.close(); } finally { connection.close(); } } catch (JMSException ex) { ex.printStackTrace(); } } |
O processo de envio de uma mensagem é parecido com a conexão de um banco de dados em JDBC.
É criada uma conexão com o banco de Dados, nessa conexão é criada uma sessão. Utilizamos essa sessão para incluirmos um objeto e depois executamos o método de envio de mensagem (send).
Pronto. Definimos o uso de fila Queue para o nosso projeto.
Implementação via JMS 2.0
O envio de mensagem JMS foi simplificado na especificação JMS 2.0. Nessa versão não utilizamos uma ConnectionFactory e sim um contexto. Vejam um exemplo de envio de mensagem em outro servlet. Observe que o consumidor e a fila são os mesmos o que mudou foi a simplificação no envio.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | package br.com.feltex.academicnet.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.annotation.Resource; import javax.inject.Inject; import javax.jms.JMSConnectionFactory; import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import br.com.feltex.academicnet.entidade.Aluno; @WebServlet("/AlunoServletJMS2") public class AlunoServletJMS2 extends HttpServlet { private static final long serialVersionUID = 1L; @Resource(mappedName = "java:/queue/alunoQueue") private Queue fila; @Inject @JMSConnectionFactory("java:/ConnectionFactory") private JMSContext context; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(getClass() + "Inicio........"); Aluno aluno = new Aluno(); aluno.setMatricula(2221L); aluno.setNome("Maria da Silva"); enviarObjetoForma2(aluno); System.out.println(getClass() + "Fim........"); PrintWriter out = response.getWriter(); out.print("<H1>Objeto enviado com sucesso! JMS 2.0</H1>"); } /** * Envia um objeto complexo para a fila JMS * * */ public void enviarObjetoForma2(Aluno aluno) { try { ObjectMessage objMessage = context.createObjectMessage(); objMessage.setObject(aluno); context.createProducer().send(fila, objMessage); } catch (JMSException ex) { ex.printStackTrace(); } } } |
Observe que o código
1 2 | @Resource(mappedName = "java:/ConnectionFactory") private ConnectionFactory connectionFactory; |
Foi substituído por
1 2 3 | @Inject @JMSConnectionFactory("java:/ConnectionFactory") private JMSContext context; |
Execução do projeto
Rode o projeto completo. Acesse o menu principal e escolha as opções de envio JMS
“Envio de Mensagem JMS 1.0 (Queue) – Alunos”
“Envio de Mensagem JMS 2.0(Queue) – Alunos”
Abraços e bons estudos.
Links relacionados
JMS no JEE 6
JMS no JEE 7
Próximos passos
No próximo Post trataremos o uso de filas JMS Topic.
Exemplo Completo(AcademicNetWebJMS.war)
Links relacionados
Recomendo que leia: Como gerenciar a transação JPA com Hibernate via Filtro em projeto Web
Leia também: Exemplo completo com JSF Primefaces + EJB + Hibernate + MySQL + JMS (Topic)
Você irá gostar:Bean Transaction Management
Deixe um comentário
Você precisa fazer o login para publicar um comentário.