9 Replies Latest reply: May 11, 2012 10:41 AM by Jérémy Caramelle RSS

Push with own JMS  queue

Jérémy Caramelle Newbie

Hello,

 

I'm trying to use a4j:push richfaces tag.

 

I have my own JMS queue defined in the application_context file :

 

<bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">

                    <property name="transportType" value="1" />

                    <property name="queueManager" value="QUEUEMANAGER" />

                    <property name="hostName" value="hostName" />

                    <property name="port" value="26007" />

                    <property name="channel" value="SYSTEM.CH.CHANNEL" />

</bean>

 

I obviously know the name of the JMS queue.

 

So, i've several question about push tag :

      - Do I have to put the context param :

   

<context-param>

                         <param-name>org.richfaces.push.jms.enabled</param-name>

                         <param-value>true</param-value>

</context-param>

 

     - Which adress have I to put in the "adress" parameter of the a4j:push tag ?

 

     - Do I need anything else ?

 

Thanks for your answers.

Jérémy Caramelle

  • 1. Re: Push with own JMS  queue
    Jérémy Caramelle Newbie

    Hello again,

     

    Maybe my question wasn't clear.

     

    I would like to plug my <a4j:push> to an existing JMS queue.

     

    Is this possible ?

     

    Thanks.

  • 2. Re: Push with own JMS  queue
    Lukáš Fryč Master

    Hi Jeremy,

     

    you can subscribe only to topics.

     

    There is fundamental difference:

    • queue delivers to one subscriber
    • topic delivers to all subscribers

     

    From architectural point, we decided not to support queues,

    since the scenario of delivering to one particular browser is unique.

  • 3. Re: Push with own JMS  queue
    Jérémy Caramelle Newbie

    Ok, we have created a Topic like this :

     

    define topic(MyTopic) topicstr(/MyTopicName)

     

    I've registered the Topic in Spring configuration file :

     

    <bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQTopicConnectionFactory">

                        <property name="transportType" value="1" />

                        <property name="queueManager" value="QueueManager" />

                        <property name="hostName" value="host" />

                        <property name="port" value="10010" />

                        <property name="channel" value="SYSTEM.DEF.SVRCONN" />

    </bean>

     

    And I try to connect the Topic to the a4j;push component :

     

    <a4j:push id="push" address="MyTopic" onerror="alert(event.rf.data)">

             <a4j:ajax event="dataavailable" render="now2" execute="@none" />

    </a4j:push>

     

     

    But when I access to the xhtml page where this push is, I get the following error :

    javax.naming.NameNotFoundException: The Name com.ibm.mq.jms.MQTopicConnectionFactory@ee461ef0 is not bound to this context.

     

    So, the component doesn't seem to find the Topic.

     

    Did I do something wrong ?

  • 4. Re: Push with own JMS  queue
    Lukáš Fryč Master

    Jeremy, could you dig and post whole stacktrace of the exception thrown?

     

    Not the topic, but connection factory wasn't found.

    I guess there could be problem with visibility, if you are using EAR packaging, is it your case?

     

    It also seems interesting that name of the connection factory have hash of the instance as suffix: @ee461ef0

  • 5. Re: Push with own JMS  queue
    Jérémy Caramelle Newbie

    Here is the full stacktrace from Tomcat :

     

    GRAVE: "Servlet.service()" pour la servlet Faces Servlet a généré une exception

    com.google.common.collect.ComputationException: javax.faces.FacesException: Le Nom com.ibm.mq.jms.MQTopicConnectionFactory@9d3f2441 n'est pas lié à ce Contexte

              at com.google.common.collect.ComputingConcurrentHashMap$ComputingMapAdapter.get(ComputingConcurrentHashMap.java:397)

              at org.richfaces.application.push.impl.jms.JMSTopicsContextImpl.createTopic(JMSTopicsContextImpl.java:281)

              at org.richfaces.application.push.TopicsContext.getOrCreateTopic(TopicsContext.java:48)

              at org.richfaces.application.push.impl.SessionImpl.createSubscriptions(SessionImpl.java:182)

              at org.richfaces.application.push.impl.SessionImpl.subscribe(SessionImpl.java:177)

              at org.richfaces.resource.PushResource.encode(PushResource.java:88)

              at org.richfaces.resource.UserResourceWrapperImpl.encode(UserResourceWrapperImpl.java:188)

              at org.richfaces.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:222)

              at javax.faces.webapp.FacesServlet.service(FacesServlet.java:591)

              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)

              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

              at org.richfaces.webapp.PushFilter.doFilter(PushFilter.java:130)

              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

              at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)

              at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

              at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)

              at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

              at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

              at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

              at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)

              at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)

              at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)

              at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)

              at java.lang.Thread.run(Thread.java:619)

    Caused by: javax.faces.FacesException: Le Nom com.ibm.mq.jms.MQTopicConnectionFactory@9d3f2441 n'est pas lié à ce Contexte

              at org.richfaces.application.push.impl.jms.JMSTopicsContextImpl$1.apply(JMSTopicsContextImpl.java:207)

              at org.richfaces.application.push.impl.jms.JMSTopicsContextImpl$1.apply(JMSTopicsContextImpl.java:195)

              at com.google.common.collect.ComputingConcurrentHashMap$ComputingValueReference.compute(ComputingConcurrentHashMap.java:355)

              at com.google.common.collect.ComputingConcurrentHashMap$ComputingSegment.compute(ComputingConcurrentHashMap.java:184)

              at com.google.common.collect.ComputingConcurrentHashMap$ComputingSegment.getOrCompute(ComputingConcurrentHashMap.java:153)

              at com.google.common.collect.ComputingConcurrentHashMap.getOrCompute(ComputingConcurrentHashMap.java:69)

              at com.google.common.collect.ComputingConcurrentHashMap$ComputingMapAdapter.get(ComputingConcurrentHashMap.java:393)

              ... 24 more

    Caused by: javax.naming.NameNotFoundException: Le Nom com.ibm.mq.jms.MQTopicConnectionFactory@9d3f2441 n'est pas lié à ce Contexte

              at org.apache.naming.NamingContext.lookup(NamingContext.java:770)

              at org.apache.naming.NamingContext.lookup(NamingContext.java:140)

              at org.apache.naming.SelectorContext.lookup(SelectorContext.java:130)

              at javax.naming.InitialContext.lookup(InitialContext.java:396)

              at org.richfaces.application.push.impl.jms.JMSTopicsContextImpl$JMSTopicContext.createConnection(JMSTopicsContextImpl.java:98)

              at org.richfaces.application.push.impl.jms.JMSTopicsContextImpl$JMSTopicContext.start(JMSTopicsContextImpl.java:123)

              at org.richfaces.application.push.impl.jms.JMSTopicsContextImpl$1.apply(JMSTopicsContextImpl.java:199)

              ... 30 more

     

    I'm on a local server and I don't use EAR packaging

     

    I've also modified the web.xml putting following parameters :

     


    <context-param>


    <param-name>org.richfaces.push.jms.connectionFactory</param-name>


    <param-value>#{jmsConnectionFactory}</param-value>

    </context-param>

     

     


    <context-param>


    <param-name>org.richfaces.push.jms.topicsNamespace</param-name>


    <param-value>/</param-value>

    </context-param>

     

    Thanks for taking time to look at my problem

  • 6. Re: Push with own JMS  queue
    Lukáš Fryč Master

    Ah, yeah, it's a little bit tricky to understand since the your language is unfamiliar to me,

    but it can't simply find the connection factory you have provided using #{jmsConnectionFactory}.

     

    it seems this expressions evaluates to com.ibm.mq.jms.MQTopicConnectionFactory@9d3f2441,

    but it can't be find in InitialContext.

  • 7. Re: Push with own JMS  queue
    Jérémy Caramelle Newbie

    Hello,

     

    I've finally well configured my Topic and my ConectionFactory to make them accessible from the a4j:push component.

     

    I've package my web app in a EAR and deployed it on a Websphere Application Server 7.

    The web app is deployed and started without any error.

     

    In a java class I've put the Richfaces example to publish messages in a topic :

    TopicConnection connection; 
    TopicSession session;
    TopicPublisher publisher; 
    public void sendCurrentDate() throws JMSException {
        String currentDate = new Date().toString();
        ObjectMessage message = session.createObjectMessage(message);
        publisher.publish(message);
    } 
    // messaging needs to be initialized before using method #sendCurrentDate()
    private void initializeMessaging() throws JMSException, NamingException {
        if (connection == null) {
            TopicConnectionFactory tcf = (TopicConnectionFactory) InitialContext.doLookup("java:/ConnectionFactory");
            connection = tcf.createTopicConnection();
        }
        if (session == null) {
            session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        }
        if (topic == null) {
            topic = InitialContext.doLookup("topic/datePush");
        }
        if (publisher == null) {
            publisher = session.createPublisher(topic);
        }

     

    In my xhtml file I've also put the example :

    <a4j:push id="datePush" address="datePush"
                ondataavailable="jQuery(#{rich:element('serverDate')}).text(event.rf.data)" />
               
    <a4j:outputPanel id="serverDate" layout="block">
        <i>waiting for event...</i>
    </a4j:outputPanel>

     

    So, I've several problems :

         - When I call more than one time the sendCurrentDate() method, I get a javax.jms.IllegalStateException : Session closed

         - The panel is never updated, the push component doesn't seem to see any message in the Topic.

     

    Maybe the problem comes from my ConnectionFactory settings in Websphere.

    For the connectionFactory I've found these parameters :

    connectionFactory.png

    connectionFactory2.png

    And for the Topic :

    Topic.png

    So I think that the root problem is that session closed exception but I can't find how to configure the WAS to avoid it.

     

    Thanks for your answers.

     

    Jérémy

  • 8. Re: Push with own JMS  queue
    Jérémy Caramelle Newbie

    I got a detailed log of the exception :

     

    FFDC Exception:com.ibm.msg.client.jms.DetailedIllegalStateException

    SourceId:com.ibm.ejs.jms.JMSMessageConsumerHandle.receive ProbeId:221

    Reporter:com.ibm.ejs.jms.JMSMessageConsumerHandle@1f031f03

    com.ibm.msg.client.jms.DetailedIllegalStateException: JMSCC0032: This message consumer

    is closed. An application called a method that must not be used after the

    message consumer is closed. Ensure that the message consumer is not closed before

    calling the method.

            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Methoda

    t sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccesso

    rImpl.java:56)

            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC

    onstructorAccessorImpl.java:39)

            at java.lang.reflect.Constructor.newInstance(Constructor.java:527)

            at com.ibm.msg.client.commonservices.j2se.NLSServices.createException(NL

    SServices.java:313)

            at com.ibm.msg.client.commonservices.nls.NLSServices.createException(NLS

    Services.java:388)

            at com.ibm.msg.client.jms.internal.JmsErrorUtils.createException(JmsErro

    rUtils.java:104)

            at com.ibm.msg.client.jms.internal.State.checkNotClosed(State.java:145)

            at com.ibm.msg.client.jms.internal.JmsMessageConsumerImpl.receive(JmsMes

    sageConsumerImpl.java:394)

            at com.ibm.mq.jms.MQMessageConsumer.receive(MQMessageConsumer.java:228)

            at com.ibm.ejs.jms.JMSMessageConsumerHandle.receive(JMSMessageConsumerHa

    ndle.java:444)

            at org.richfaces.application.push.impl.jms.JMSTopicsContextImpl$JMSTopic

    Context$1.run(JMSTopicsContextImpl.java:131)

            at java.lang.Thread.run(Thread.java:736)

  • 9. Re: Push with own JMS  queue
    Jérémy Caramelle Newbie

    Hello,

     

    After some tests, I've verified that I correctly send messages to the topic.

    I can read these messages with a manually created durable subscriber :

     

         try {

                                  consumer = session.createDurableSubscriber(topic,"mySubscriber");

                                  connection.start();

                   Message msg;

                                  System.out.println("Waiting message...");

                                  msg = consumer.receive();

                                  System.out.println("Message received !");

                                  System.out.println("New message : "+msg.toString());

     

     

                        }catch(JMSException e){

                                  e.printStackTrace();

                                  System.out.println("Erreur receive consumer !!");

                        }

     

    I can see the sent message in the SystemOut.log.

     

    But the Richfaces push component still doesn't see the message and the push event isn't processed.

     

    The JNDI name of my topic is jms/TBDTopicEFF7

    My push component is declared like that :

     

      <a4j:push id="pushPanel" address="TBDTopicEFF7"

                                                 ondataavailable="jQuery(#{rich:element('serverDate')}).text(event.rf.data)"

                                                 onerror="alert(event.rf.data)">

                                  </a4j:push>

     

     

      <a4j:outputPanel id="serverDate" layout="block">

                                                 <i>waiting for event...</i>

                                  </a4j:outputPanel>

     

    And the topic namespace is correctly declared in my web.xml :

     


    <context-param>


    <param-name>org.richfaces.push.jms.topicsNamespace</param-name>


    <param-value>jms</param-value>

    </context-param>

     

    The push functionnality works perfectly with the TopicContext functionnality but I need to bind the push component to my own topic.

    Why ? Because a message will be send to my topic from a MDB (in the same EAR).

     

    If someone have an idea why the push component doesn't react when a message arrives into the topic, him help will be apreciated.

     

    Thanks for your repplies.

     

    Jérémy