JMS Topic exclusivo para clientes

2 respostas
T

Olá pessoal, sou novo aqui nesse grupo, e já chego com uma dúvida! :stuck_out_tongue:

Estou iniciando com EJB3, no momento estou estudando MDB. Então segue a dúvida.

Fiz uma aplicação chat para propósitos de estudo que funciona da seguinte forma:

1- Cada cliente se conecta ao servidor através de um EJB stateful que armazena dados do usuario (por enquanto só o apelido) após ele se conectar.
2- Através de um método remote, o usuário invoca um método do EJB, que manda um topic de nome “chatTopic”.
3- Cada usuário já assina esse “chatTopic” e recebe as mensagens

Até aqui tudo funcionando muito bem, contudo, para fins de estudo decidi fazer uma modificação, e assim que ficaria a aplicação:

1- Cada cliente se conecta ao servidor através de um EJB stateful que armazena dados do usuario (por enquanto só o apelido) após ele se conectar.
2- Através de um método remote, o usuário manda mensagens para o EJB, que manda um topic ou queue de nome “chatTopic”.
3- Um MDB recebe esse “chatTopic” faz algum tratamento na mensagem (como inibir certas palavras, ou por no log, não decidi ainda).
4- O MDB envia essa mensagem tratada para um topic de nome "clientTopic"
5- Cada usuário já assina esse “clientTopic” e recebe as mensagens

Aqui que está dando problema. No cliente o código é esse:

public Cliente() throws NamingException, JMSException {
		Context initialContext = getInitialContext();
		Object ref = initialContext.lookup("ChatSessionBean/remote");
		chat = (RemoteChat) PortableRemoteObject.narrow(ref,
				RemoteChat.class);
		InitialContext context=getInitialConext();
		ConnectionFactory factory= (ConnectionFactory)context.lookup("TopicConnectionFactory");
		Topic topic=(Topic)context.lookup("topic/clientTopic");
		Connection con =factory.createConnection();
		Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
		MessageConsumer consumer=session.createConsumer(topic);
		consumer.setMessageListener(this);
		con.start();

	}

O problema é que na linha:

levanta o NamingException, pois o clientTopic não existe. Existe alguma forma que eu possa criá-lo?
Encontrei um work around colocando um MDB que recebe o “clientTopic” mas não faz nada. Dessa forma o “clientTopic” é registrado. Mas tem alguma forma menos gambiarreira?
Valeu por ter lido até aqui! :stuck_out_tongue:

Abraços,
Thiago Jamir

2 Respostas

Jsatriani

Ola,
vc ta registrando esse teu Topic em <JBOSS_HOME>\server\default\deploy\jms\jbossmq-destinations-service.xml ?

&lt;mbean code="org.jboss.mq.server.jmx.Topic"
	 name="jboss.mq.destination:service=Topic,name=clientTopic"&gt;
    &lt;depends optional-attribute-name="DestinationManager"&gt;jboss.mq:service=DestinationManager&lt;/depends&gt;
    &lt;depends optional-attribute-name="SecurityManager"&gt;jboss.mq:service=SecurityManager&lt;/depends&gt;
    &lt;attribute name="SecurityConf"&gt;
      &lt;security&gt;
        &lt;role name="publisher" read="true" write="true" create="false"/&gt;
      &lt;/security&gt;
    &lt;/attribute&gt;
  &lt;/mbean&gt;
T

Jsatriani,

Desculpe a demora para responder, mas eu estive sem internet o fds. Sobre a solução: funcionou sim! Muito obrigado. Contudo agora está aparecendo umas mensagens no log do servidor. Fica dando esse warn:

E quando alguém manda uma mensagem aparece essa exceção:

14:49:30,421 ERROR [JmsServerSession] org.jboss.resource.adapter.jms.inflow.JmsServerSession@88485f failed to commit/rollback
javax.transaction.HeuristicMixedException
	at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1397)
	at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
	at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
	at org.jboss.resource.adapter.jms.inflow.JmsServerSession$XATransactionDemarcationStrategy.end(JmsServerSession.java:494)
	at org.jboss.resource.adapter.jms.inflow.JmsServerSession.run(JmsServerSession.java:248)
	at org.jboss.resource.work.WorkWrapper.execute(WorkWrapper.java:204)
	at org.jboss.util.threadpool.BasicTaskWrapper.run(BasicTaskWrapper.java:275)
	at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:756)
	at java.lang.Thread.run(Unknown Source)

Segue as classes:

O Session Bean:

@Stateful
public class ChatSessionBean implements RemoteChat{
	
	String usuario;
	
	@Resource(mappedName="TopicConnectionFactory") private TopicConnectionFactory factory;
	
	

	
	public void falar(String message) throws JMSException, NamingException {
		if(usuario==null){
			throw new NullPointerException("Usuário não logado");
		}
	
		message=usuario+": "+message;
		Connection con=factory.createConnection();
		Session session=con.createSession(true, 0);
		Topic topic=(Topic) getInitialContext().lookup("topic/chatTopic");
		MessageProducer sender=session.createProducer(topic);
		ObjectMessage oMsg=session.createObjectMessage();
		oMsg.setObject(message);
		sender.send(oMsg);
		con.close();
		
	}
	
	public InitialContext getInitialContext() throws NamingException{
		InitialContext context=new InitialContext();
		
		return context;
	}

	public void login(String usuario) throws JMSException, NamingException {
		this.usuario=usuario;
		this.falar(usuario+" entrou na sala.");
	}

}

O MDB:

@MessageDriven(activationConfig = {

		@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
		@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
		@ActivationConfigProperty(propertyName = "destination", propertyValue = "topic/chatTopic"), })
public class Chat implements MessageListener {

	@Resource(mappedName="TopicConnectionFactory") private TopicConnectionFactory factory;
	
	
	
	public void onMessage(Message message) {
		try {

			Connection con=factory.createConnection();
			Session session=con.createSession(true, 0);
			Topic topic=(Topic) new InitialContext().lookup("topic/clientTopic");
			MessageProducer sender=session.createProducer(topic);
			ObjectMessage oMsg=session.createObjectMessage();
			oMsg.setObject(((ObjectMessage)message).getObject());
			sender.send(oMsg);
			con.close();
		} catch (JMSException ex) {
			System.out.println("Erro ao pegar a mensagem: " + ex.getMessage());
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Apesar de mostrar essas mensagens de erro no log do JBoss, para o cliente, é transparente. A aplicação funciona normalmente.
Agradeço desde já qualquer ajuda.

EDIT: debugando descobri que o erro acontece após a execução do onMessage() da classe Chat.

Criado 6 de junho de 2008
Ultima resposta 9 de jun. de 2008
Respostas 2
Participantes 2