Announcement Announcement Module
Collapse
No announcement yet.
JMS queue message viewing without removing it from the queue Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JMS queue message viewing without removing it from the queue

    Can anyone tell me how I can use "jmsTemplate" (JMS 1.1) to peek at (view only) a message without actually removing it first from the queue. In other words, I would like to get a "virtual" message and if I am unable to process the message then I want to leave it on the queue (in the same sequence).

    Is there a way to do that?

    Thanks.

  • #2
    I am very surprised that no one has run into this before. There's no built-in support for browsing the queue in Spring. This is an absolute necessity for a JMS application that doesn't want to loose it's messages in case it has any sort of fatal error.

    Comment


    • #3
      RE: Default JMS queue message viewing without removing it from the queue

      We have done this by setting the JMS Session to CLIENT_ACKNOWLEDGE and then getting a message from the queue. We check the message and if we can't handle it or want to leave it on the queue we do not call acknowledge before closing the session. This will leave it on the queue. (per JMS specs)

      However last time I used Spring/JMS (circa version 1.1.5) it could not support this.

      -Mike

      Comment


      • #4
        Hey, that's great. That's exactly what I needed. I found that jmsAccessor class in version 1.2.6 has the ability to set the session.CLIENT_ACKNOWLEDGE which is used by jmsTemplate (via extending a supporting class). I just added the following line to my application context file and it didn't complain while generating the bean so I think I am good to go. The value 2 is the int value for session.CLIENT_ACKNOWLEDGE. Happy Spring'ing!

        <property name="sessionAcknowledgeMode"><value>2</value></property>

        Comment


        • #5
          Is it working?

          dshah, have you ever made this work to your liking? I think it's impossible with Spring JMS support (before 2 anyway). Please confirm. Thank you.

          Comment


          • #6
            JMS Viewer

            I have this working. I am using Spring Framework 1.2.8. I use transaction manager in read-only mode and once processed completely, I consume the message.

            Following is XML config.

            <!-- JMS Queue Connection Factory -->
            <bean id="internalJmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryB ean">
            <property name="jndiTemplate"> <ref bean="jndiTemplate"/> </property>
            <property name="jndiName"> <value>${NPA_MSG_FACTORY}</value> </property>
            </bean>

            <!-- Spring JMS Queue Connection Factory -->
            <bean id="jmsQueueConnectionFactory" class="org.springframework.jms.connection.UserCred entialsConnectionFactoryAdapter">
            <property name="targetConnectionFactory"> <ref bean="internalJmsQueueConnectionFactory"/> </property>
            <property name="username"> <value>${NPA_MSG_USER}</value> </property>
            <property name="password"> <value>${NPA_MSG_PWD}</value> </property>
            </bean>

            <!-- JMS Queue Template -->
            <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
            <property name="connectionFactory"><ref bean="jmsQueueConnectionFactory"/></property>
            <property name="sessionAcknowledgeMode"><value>2</value></property>
            <property name="priority"><value>4</value></property>
            <property name="explicitQosEnabled"><value>true</value></property>
            <property name="pubSubDomain"><value>false</value></property>
            <property name="receiveTimeout"><value>5000</value></property>
            </bean>

            <bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTrans actionManager">
            <property name="connectionFactory"><ref local="jmsQueueConnectionFactory"/></property>
            </bean>

            <bean id="jmsOperations" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
            <property name="transactionManager"><ref local="jmsTransactionManager"/></property>
            <property name="target"><ref local="jmsQueueTemplate"/></property>
            <property name="transactionAttributes">
            <props>
            <prop key="convertAndSend*">PROPAGATION_REQUIRED</prop>
            <prop key="send*">PROPAGATION_REQUIRED</prop>
            <prop key="receive*">PROPAGATION_REQUIRED</prop>
            </props>
            </property>
            </bean>

            <bean id="jmsSender" class="com.wachovia.ppds.utils.tools.JMSSender">
            <property name="jmsTemplate"> <ref bean="jmsQueueTemplate"/> </property>
            </bean>

            <bean id="jmsReceiver" class="com.wachovia.ppds.utils.tools.JMSReceiver">
            <property name="jmsTemplate"> <ref bean="jmsQueueTemplate"/> </property>
            </bean>


            Following is the transaction manager code.

            TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
            Message msg = jmsTemplate.receive(queueName);


            Following is the standard receive that consumes the message.

            Message msg = jmsTemplate.receive(queueName);

            That's it.

            Comment


            • #7
              You really should be using a queue browser; so just create a browser using a Session.

              Comment


              • #8
                If you still want to use JmsTemplate, you can use JmsTemplate.execute that takes a SessionCallback (there are two versions). You still will need a little bit of try/catch/finally code for allocating/freeing the browser but the amount of boilerplate code will be less.

                Comment


                • #9
                  Originally posted by dshah View Post
                  Hey, that's great. That's exactly what I needed. I found that jmsAccessor class in version 1.2.6 has the ability to set the session.CLIENT_ACKNOWLEDGE which is used by jmsTemplate (via extending a supporting class). I just added the following line to my application context file and it didn't complain while generating the bean so I think I am good to go. The value 2 is the int value for session.CLIENT_ACKNOWLEDGE. Happy Spring'ing!

                  <property name="sessionAcknowledgeMode"><value>2</value></property>
                  Nice! thats exactly what I was searching for! thank you!

                  Comment


                  • #10
                    Since you have revived this very old thread, I'd like to point out that with Spring 3.0 you can now use SpEL to access constants such as this...

                    Code:
                    <property name="sessionAcknowledgeMode"
                           value="#{T(javax.jms.Session).CLIENT_ACKNOWLEDGE}"/>
                    In Spring 2.5 we have <util:constant/> to do a similar thing.

                    Comment

                    Working...
                    X