Remote JMS

Boa tarde,

Estou tendo algumas dificuldades em consumir um JMS remotamente, o problema é:

No glassfish criei um javax.jms.TopicConnectionFactory e um javax.jms.Topic. Então crieu uma aplicação web que produz registros nessa fila:

@Named(value = "JMSProductor")
@Dependent
public class JMSProductorBean implements Serializable {

    @Resource(name = "JMSTPFactory")
    private ConnectionFactory cmf;
    @Resource(name = "JMSTP")
    private Destination destination;

    public String send() throws JMSException {
        TopicConnection connection = null;

        try {
            connection = ((TopicConnection) cmf.createConnection());
            TopicSession topicSession =
                    connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
            TopicPublisher topicPublisher = topicSession.createPublisher((Topic) destination);
            TextMessage message = topicSession.createTextMessage("Novo Tópico");
            topicPublisher.publish(message);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }

        return null;
    }

E crieu uma outra aplicação que consome essa fila:

@MessageDriven( mappedName = "JMSTP", activationConfig = {
    @ActivationConfigProperty(
        propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(
        propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
})
public class TopicConsumerBean implements MessageListener {

    @Override
    public void onMessage(Message message) {
        try {
            TextMessage msg = (TextMessage) message;
            System.out.println("#>" + msg.getText());

        } catch (Exception e) {
            System.out.println("deu erro!!!");
        }
    }
}

Ok, até aqui rodando no mesmo servidor funciona sem problemas. Consigo produzir e consumir a fila. Mas agora, como eu faço para que esse mesmo cenario funcione remotamente, com cada aplicação rodando em um servidor? Já tentei diversas formas de configurar seguindo a documentação do JEE6 e outros exemplos que achei por ai, mas nada funciona. Aqui http://docs.oracle.com/javaee/6/tutorial/doc/bncgv.html tem vários exemplos, mas a maioria com aplicações fazendo lookup remoto com InitialContext, não usando CDI. Isso que estou tentando fazer é possível? Isso parece ser uma coisa tão trivial quando falamos de filas que penso estar esquecendo de algum detalhe, ou não sei de algum detalhe. Preciso que duas aplicações web em servidores diferentes troquem informações usando JMS.

Aguadeço a ajuda.

Já fiz isso com lookup, com CDI não sei se é possível, eu acho que não faria sentido.

Olá,

Se eu tenho duas applicações web, uma produzindo e uma consumindo acho que faria sentido.

Isso, se ambos estiverem hospedadas no mesmo servidor.

Sim, mas no caso não estão no mesmo. No mesmo servidor consegui fazer funcionar.

Exato. Por isso eu acho que só daria para fazer via loopkup .

É que no jee6 é possível fazer CDI com EJB remoto, com a anotação @EJB, logo acho que é possível fazer com JMS também. Tem alguns parametros que da pra passar na criação do @MessageDriven, mas não consegui achar um que funcione.

e tu sabe como configurar um MessageDriven e MessageListener via descritor?

Cara se eu tiver falando #@#$% ignora please…

  • se tu tem 2 servidor voce n precisa do acesso remoto…
    vc precisa de uma bridge.

tipo em um sistema com um frontend e um backend, cada um em servidore separado (é esse o teu caso?):

  • cria uma fila para largar as mensagens no servidor de frontend
  • cria uma fila para buscar as mensagens no servidor do backend
  • coloca as aplicações em cada uma e faz comunicar com as devidas fila
  • configura uma bridge para pegar todas as mensagens que cairem na fila do frontend e largar automaticamente na fila do backend
    ( com isso não é a tua aplicação a responsavel por acessar o outro servidor sim o servidor da aplicação)
  • se teu mdb estiver corretamente feito, quando a mensagem cair na fila do backend ele automaticamente vai ler ela

tratei como bridge, mas tbm tem as SAFE são implementações parecidas …

Qual servidor vc utiliza ?

Add um exemplo com jbos,
http://theopentutorials.com/tutorials/java-ee/ejb3/mdb/mdb-example/

( nunca mechi com jbos só com WLP e é muito facil depois que se aprende :smiley: )

Espero ter ajudado…

Estou usando glassfish, mas poderia usar outro servidor sem problemas. Se fosse um servidor mais leve, seria melhor ainda.

Ainda não tinha passado isso pela cabeça, mas perece que iria facilitar muito minha vida. Vou dar uma olhada nessa possibilidade.

vlws

Então, dessa maneira que o pdpbom falou funcionou perfeitamente. Acho até que não tem outra maneira de fazer isso entre dois servidores de aplicação, apenas com um cliente standalone. Desse modo fica bem simples a arquitetura, pois a responsabilidade de entrega e recebimento de mensagens fica por conta dos appserver.

Mas fazendo o teste com um cliente standalone não tive sucesso usando o glassfish. Quando executo o código abaixo remotamente, ele trava fazendo o lookup de TopicFactory, e fica eternamente travado, sem dar qualquer mensagem de erro. Mas quando executo o mesmo código na maquina local funciona. Estou fazendo alguns testes com o jboss agora.

   [code] Properties props = new Properties();
    props.setProperty("java.naming.factory.initial",
            "com.sun.enterprise.naming.SerialInitContextFactory");
    props.setProperty("java.naming.factory.url.pkgs",
            "com.sun.enterprise.naming");
    props.setProperty("java.naming.factory.state",
            "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
    props.setProperty("org.omg.CORBA.ORBInitialHost", "192.168.1.18");
    props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");        
    
    InitialContext ic = new InitialContext(props);
    
    TopicConnection tconn = (TopicConnection)((ConnectionFactory) ic.lookup("jms/TopicFactory")).createConnection();
    Topic topic = (Topic) ic.lookup("jms/Topic");

    TopicSession tseSession = tconn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    TopicSubscriber ts = tseSession.createSubscriber(topic);

    ts.setMessageListener(new MessageListener() {
        public void onMessage(Message message) {
            try {
                System.out.println(((TextMessage) message).getText());
            } catch (JMSException ex) {
                System.out.println("## error");
            }
        }
    });        

    tconn.start();

[/code]

Obrigado pela luz!