Announcement Announcement Module
Collapse
No announcement yet.
JMS Subscription Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JMS Subscription

    Is there any sample code on how to subscribe to a destination using the new Spring 1.1 JMS framework? Publish is straightforward but there is little to no documentation on the subscription. Just a simple example with snippets from applicationContext.xml showing the DI and the cooresponding Java code using those objects to subscribe would help a ton.

  • #2
    Factory beans in Sandbox

    Hi,

    There are some factory bean in the sandbox that you can use to wire up a simple JMS apps, including consumers. We decided to remove it from the release since we wanted to wait to have more robust subscription support akin to MDBs.

    I will post that section of the docs here in the forum for you to use in another email

    Cheers,
    Mark

    Comment


    • #3
      Docs for JMS Factory Classes

      Not sure this is the best place for it but here it is. The formatting isn't preserved

      1.1. Factory Classes
      A collection of factory classes are provided to create instances of a JMS Connection, Session, MessageProducer, and MessageConsumer and expose them inside an application context. This can be an effective means for configuring a JMS based application.

      The factories are for use only with JMS 1.1 providers. The JmsConnectionFactoryBean will return a singleton/non-prototype connection and requires a reference to a ConnectionFactory. Setting the ClientID property of the connection should only be done if it is not configured in a client-specific ConnectionFactory implementation. The JmsSessionFactoryBean will return a singleton/non-prototype session and requires a reference to a Connection. The JmsProducerFactoryBean creates a new prototype instance of MessageProducer. You can specify all the various QOS properties, disable message ID and timestamp creation, and destination. The JmsConsumerFactoryBean creates a new prototype instance of a MessageConsumer and requires a reference to a session and destination. You can also create a durable subscriber to a topic.

      The following application context listing shows how you can use the factory classes to send a message.

      Code:
      <beans>
                      
              <bean id="jmsSendExample" class="example.jms.JmsSendExample">
                      <property name="session"><ref bean="jmsSession"/></property>
                      <property name="producer"><ref bean="jmsProducer"/></property>
              </bean>
              
              <bean id="jmsProducer" class="org.springframework.jms.JmsProducerFactoryBean">
                      <property name="session"><ref bean="jmsSession"/></property>                    
                      <property name="destination"><ref bean="queue"/></property>
                      <property name="priority"><value>6</value></property>
              </bean>
              
              <bean id="queue" class="org.springframework.jndi.JndiObjectFactoryBean">
                      <property name="jndiName"><value>testQueueJndi</value></property>
              </bean>
              
              <bean id="jmsSession" class="org.springframework.jms.JmsSessionFactoryBean">
                      <property name="transacted"><value>false</value></property>
                      <property name="connection"><ref bean="jmsConnection"/></property>              
              </bean>
              
              <bean id="jmsConnection" class="org.springframework.jms.JmsConnectionFactoryBean">
                      <property name="connectionFactory"><ref bean="jmsConnFactory"/></property>
              </bean>
              
              <bean id="jmsConnFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
                      <property name="jndiName"><value>QueueConnectionFactory</value></property>
              </bean>
      
      </beans>    
          
      import org.springframework.context.ConfigurableApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      import javax.jms.JMSException;
      import javax.jms.Message;
      import javax.jms.MessageProducer;
      import javax.jms.Session;
      
      
      public class JmsSendExample
      &#123;
          
          private Session session;
          
          private MessageProducer producer;
      
          public void setProducer&#40;MessageProducer producer&#41;
          &#123;
              this.producer = producer;
          &#125;
      
          public void setSession&#40;Session s&#41;
          &#123;
              session = s;
          &#125;
      
      
          public void sendMessage&#40;&#41; throws JMSException
          &#123;
              Message m = session.createTextMessage&#40;"Hello World!"&#41;;
              producer.send&#40;m&#41;;
              System.out.println&#40;"Sent message = " + m&#41;;
          &#125;
          
          public static void main&#40;String&#91;&#93; args&#41; throws JMSException
          &#123;
              String ctxFile = "/example/jms/appContext.xml";
              ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext&#40;ctxFile&#41;;
              JmsSendExample sendExample = &#40;JmsSendExample&#41; ctx.getBean&#40;"jmsSendExample"&#41;;
              sendExample.sendMessage&#40;&#41;;
              ctx.getBeanFactory&#40;&#41;.destroySingletons&#40;&#41;;
          &#125;
          
      &#125;
      Similarly, to receive a message add the following to the application context
      Code:
              <bean id="jmsConsumer" class="org.springframework.jms.JmsConsumerFactoryBean">
                      <property name="session"><ref bean="jmsSession"/></property>
                      <property name="destination"><ref bean="queue"/></property>
                      <property name="messageListener"><ref bean="msgListener"/></property>
              </bean>
              
              <bean id="msgListener" class="example.jms.JmsMsgListener">
              </bean>
      The java code to receive the message is then
      Code:
          public static void main&#40;String&#91;&#93; args&#41; throws Exception
          &#123;
              String ctxFile = "/example/jms/appContext.xml";
              ApplicationContext ctx = new ClassPathXmlApplicationContext&#40;ctxFile&#41;;      
              Connection c = &#40;Connection&#41; ctx.getBean&#40;"jmsConnection"&#41;;
              c.start&#40;&#41;;
              System.out.println&#40;"Listening for messages"&#41;;      
              Thread.sleep&#40;100000&#41;;
          &#125;
      A durable consumber on for a topic is specified by setting the isDurableSubscriber property to true. Durable Subscriptions only apply to the publish-subscribe messaging domain and you must provide a durable identity for the subscriber.

      The full lifecycle management of starting and stopping the JMS Connection after all beans have been initialized is left to the application code. You should avoid initialization methods on beans that may start the JMS connection since messages can be delivered before the BeanFactory has finished processing all the objects. Some helper classes for this case are in the sandbox under the package org.springframework.service but the depends-on attribute in a bean declaration can be leverged as well.

      Comment


      • #4
        Mark,

        You can preserve formatting by using the 'code' BBCode tag. I edited your message to use that tag around the code...

        Comment


        • #5
          Re: Factory beans in Sandbox

          Originally posted by Mark Pollack
          Hi,

          There are some factory bean in the sandbox that you can use to wire up a simple JMS apps, including consumers. We decided to remove it from the release since we wanted to wait to have more robust subscription support akin to MDBs.

          Cheers,
          Mark
          Questions:

          1. When do we expect to have "more robust subscription support" for the sandbox stuff? Just interested to get an idea of the plan and likely timeframe.

          2. Spring 1.1 JMS stuff uses JmsTemplate/JmsTemplate102 to send messages (and receive synchronously), while the sandbox JMS stuff seems to be using a different model (and includes async receive support). I am not sure if the sandbox stuff is supposed to be used together with the current Spring 1.1 JMS stuff, or the sandbox stuff is supposed to replace it eventually? I can see that things like JMSTransactionManager and MessageConverter are not currently available in the sandbox.

          3. Also , the stuff in the sandbox is JMS 1.1. only. Will this still be the case in the future?

          Comment


          • #6
            Hi,

            I'll have to get back to you on the timeframe, not quite sure.

            The sandbox code isn't going to replace anything in the main branch, so don't think of it as a newer version. The code in the sandbox is basically factorybeans to provide the ability to expose the standard JMS API within the application context. You could use the JmsProducerFactoryBean to set a reference to a MessageProducer in another class, like the JmsHelper in the sandbox. This is for those people who want to operate at the 'raw' JMS 1.1 level for sending messages. For async-receiving, the only option in the code base now is to use the JmsConsumerFactoryBean. This obviously doesn't compete with the infrastructure provided by MDBs, but might be good enough for some needs. You basically have the choice to use whatever approach is best for you, but I'd shy away from using 'raw' JMS for sending since the JmsTemplate handles that better and doesn't offer the features you mention.

            I made 1.1 factory beans just because that is what I use most often. Are people interested in 1.0.2 jms factory beans?

            Hope this helps.

            - Mark

            Comment


            • #7
              Re: JMS Subscription

              Originally posted by mperham
              Is there any sample code on how to subscribe to a destination using the new Spring 1.1 JMS framework? Publish is straightforward but there is little to no documentation on the subscription. Just a simple example with snippets from applicationContext.xml showing the DI and the cooresponding Java code using those objects to subscribe would help a ton.
              Here's an example of creating a subscription using Spring and a lightweight JCA container that handles the JMS pooling and transactions for you...

              http://activemq.codehaus.org/JCA+Container

              Comment


              • #8
                Hiya,

                I've just been trawling through the forums trying to get JMS working in a project of mine when I saw Marks post on the 25/8. I have been scratching my head ever since. :?

                I have checked the Spring API and the spring.jar itself and I can't find any reference to:

                org.springframework.jms.JmsProducerFactoryBean
                org.springframework.jms.JmsSessionFactoryBean
                org.springframework.jms.JmsConnectionFactoryBean
                org.springframework.jms.JmsConsumerFactoryBean

                looking through the API I have found classes that seem to have similar behaviour so instead I have used

                Code:
                	
                <!-- start JMS Beans -->
                	
                    <bean id="jmsConnFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> 
                      <property name="jndiName"><value>weblogic/jms/JMSFactory</value></property> 
                    </bean> 
                	
                    <bean id="jmsConnection" class="org.springframework.jms.connection.SingleConnectionFactory"> 
                      <property name="targetConnectionFactory"><ref bean="jmsConnFactory"/></property> 
                    </bean> 	
                	
                    <bean id="topic" class="org.springframework.jndi.JndiObjectFactoryBean"> 
                      <property name="jndiName"><value>jms/myapp/fileCache</value></property> 
                    </bean> 
                        
                    <bean id="jmsSession" class="org.springframework.jms.core.JmsTemplate"> 
                      <property name="sessionTransacted"><value>false</value></property> 
                      <property name="connectionFactory"><ref bean="jmsConnection"/></property>              
                    </bean> 	
                
                    <bean id="jmsConsumer" class="org.springframework.jms.JmsConsumerFactoryBean"> 
                      <property name="session"><ref bean="jmsSession"/></property> 
                      <property name="destination"><ref bean="topic"/></property> 
                      <property name="messageListener"><ref bean="fileCache"/></property> 
                    </bean> 
                	
                <!-- end JMS Beans -->
                Obviously I haven't gotten this working yet as I haven't been able to replace

                org.springframework.jms.JmsConsumerFactoryBean

                Does anyone know something that might have comparable behaviour? Does anyone know if I am simply wrong? :oops:

                Thanks in advance,
                Arran

                Comment


                • #9
                  As mentioned in the earlier posts, those classes exist in the sandbox, not the Spring release.

                  The release JMS code supports only synchronous receiving of messages. For that simply use another JmsTemplate and invoke its receive() methods.

                  Tim

                  Comment


                  • #10
                    sandbox?

                    There are some factory bean in the sandbox that you can use to wire up a simple JMS apps, including consumers. We decided to remove it from the release since we wanted to wait to have more robust subscription support akin to MDBs.
                    Still working my way around the Spring site - can someone tell me where the sandbox is?

                    Sorry if this is obvious & I missed it?

                    Mike

                    Comment


                    • #11
                      Mike,

                      You need to check out from CVS to get the sandbox code. As Mark mentioned we have not released this code yet because we are waiting to perform more tests and to extend the support.

                      In the meantime you might want to look at the support offered by ActiveMQ that James mentioned earlier.

                      Rob

                      Comment


                      • #12
                        Re: Docs for JMS Factory Classes

                        I've created a publisher - subscriber test, but have been unable to make it durable yet. I haven't found much documentation on doing this in Spring. In a previous post Mr. Pollack said:

                        Originally posted by Mark Pollack
                        A durable consumber on for a topic is specified by setting the isDurableSubscriber property to true. Durable Subscriptions only apply to the publish-subscribe messaging domain and you must provide a durable identity for the subscriber.
                        I have tried adding this to a subscriber that I have created to connect to a durable topic, but it hasn't worked yet. Is this something that can only be done with the bean classes that are only in the sandbox?

                        Comment


                        • #13
                          To clarify what I'm doing a little:

                          I can publish a durable message to a durable topic in my MQ from an instance of a JmsTemplate. Once published, I can check the topic and see that the durable message are in fact waiting there for a durable subscriber to pick them up.

                          My problem comes in here. I can create a subscriber using JmsTemplate, but how do I tell JmsTemplate to create a durable subscriber?

                          Looking in the Spring API, I don't even see a createDurableSubscriber listed among the other protected createSubscriber methods. Is there a different class that I should be looking at?

                          Comment


                          • #14
                            JMS 1.0.2 factory bean, specifically a JmsConsumerFactoryBean

                            Originally posted by Mark Pollack
                            ...
                            I made 1.1 factory beans just because that is what I use most often. Are people interested in 1.0.2 jms factory beans?
                            ...
                            - Mark
                            Hi Mark,

                            We are intending to use spring for sending, however we are having issues with the lack of asychronous message consumption support (specifically on the client, on the server we're relying on message driven beans), so some guidance on how JmsConsumerFactoryBean could be used in a JMS 1.0.2 framework would be helpful (or a 1.0.2 compliant JmsConsumerFactoryBean would be even better).

                            Thanks

                            Comment

                            Working...
                            X