Exemplo completo com JSF Primefaces + EJB + Hibernate + MySQL + JMS

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:

  1. – Configuração da Fila no servidor
  2. – Criação de componentes para consumir as filas
  3. – Criação do Servlet que enviará uma mensagem para a fila
  4. – Trabalhar com Queue fila de Aluno
  5. – Trabalhar com Topic fila de Professor

Veja como ficará o nosso exemplo:

queue


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

Não se esqueça de curtir este post nas rede sociais. Dê a sua contribuição social e ajude o autor:

Deixe um comentário