Announcement Announcement Module
Collapse
No announcement yet.
Dynamic Queue creation and consumption Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dynamic Queue creation and consumption

    I am looking for a little guidance on the best way to handle this:

    Network thingys come and register with us.
    We create a queue for them and we start accepting events from them which we place on that queue.
    The events are ordered so must follow one-by-one.
    The event consumer is independent of the queue-adder so both run at the same time.
    There may be 20 or 30 or more network thingys.


    My current solution is:

    Code:
        <bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver"/>
    
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <property name="connectionFactory" ref="jmsConnectionFactory"/>
            <property name="destinationResolver" ref="jmsDestinationResolver"/>
            <property name="pubSubDomain" value="false"/>
            <property name="receiveTimeout" value="5000"/>
        </bean>
    The java class which adds messages uses:
    Code:
      String queueName = "net-thing-" + id;
      jmsTemplate.send (queueName, new MessageCreator ()
        {
          public Message createMessage (Session session) throws JMSException
          {
          return session.createTextMessage (mytext) ;
          }
        }) ;
    The java class which processes messages uses:
    Code:
    while (true)
    {
      try
        {
        Message msg = jmsTemplate.receive (queueName) ;
        // do stuff
        }
      catch (receiveTimeoutException e)
        {
        // ignore
        }
    }
    I have found that when I call jmsTemplate.receive it blocks which means I need a separate thread to sit around waiting for things to do.

    Is there a way that spring can manage this? Is there a way to get Spring to call onMessage (or similar) when a message arrives for that queue without having to define the queue in advance or having to create my own threads to do the event processing.

    Any help would be greatly appreciated.

  • #2
    I suggest the reference guide, especially the part regarding MessageListenerContainers.

    Comment


    • #3
      I have read the Spring JMS reference lots of times but it doesn't answer my question.

      From: 19.3. Sending a Message para 5
      The method send(String destinationName, MessageCreator creator) lets you send to a message using the string name of the destination. If these names are registered in JNDI, you should set the destinationResolver property of the template to an instance of JndiDestinationResolver.
      If the names are not registered in JNDI (because you are not using it) then what happens?

      In all the examples in the ref doc the destination is set as a property in the bean's configuration, but I only know what it is at runtime. How do I tie my message producer and my message consumer together (at runtime), so that my consumer is called by spring and I don't have to explicitly call the blocking jmsTemplate.receive.

      Comment


      • #4
        If the names are not registered in JNDI (because you are not using it) then what happens?
        A queue is dynamically created.

        Define your definition on runtime. Does it come from a properies file or does the user enter is somewhere?!

        Comment


        • #5
          In post #1 a network thingy comes and says hello and I create a unique name based on it's client id. It's an arbitrary name that I don't know before hand.

          Comment


          • #6
            Perhaps I am not explaining myself very well.

            MessageListenerContainers are end points for queues. So the queue is known in advance - otherwise it can't have an end point?

            So my question is: after adding the messages to my well-known queue name "net-thing-5", how do I write a DefaultMessageListenerContainer type thing that is managed by spring and is called on demand.

            19.2.3. Destination Management talks about a DynamicDestinationResolver which sounds like the right kind of thing, but the documentation seems to skirt over the subject and doesn't give any examples of how you actually do it.

            Please can you tell me how I get spring to call my message handler when I don't know what the queue name is.

            Comment


            • #7
              After a lot of reading and banging my head against the wall, I have discovered a couple of things.

              The destinationResolver converts the pre-defined destinationName into a Destination name. It does not convert an arbitrary destination name into a Destination which is what I want.

              Code:
              <bean id="jmsIsaEventProcessor" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
                 <property name="connectionFactory" ref="nonPersistancePooledConnectionFactory"/>
                 <property name="destinationName" value="internal-queue"/>
                 <property name="destinationResolver" ref="dynamicDestinationResolver"/>
                 <property name="messageListener" ref="isaEventProcessor"/>
                 <property name="concurrentConsumers" value="1" />
                 <property name="maxConcurrentConsumers" value="1" />
                 <property name="pubSubDomain" value="false"/>
                 <property name="transactionManager" ref="nonPersistanceJmsTransactionManager"/>
              </bean>
              I was hoping to miss out the destinationName property and have the destinationResolver resolve to a Destination name. So as a queue is created an automatic consumer is created to start processing the messages on the queue.

              I think, I'm a bit confused but the documentation says:
              19.2.3. Destination Management

              Destinations, like ConnectionFactories, are JMS administered objects that can be stored and retrieved in JNDI. When configuring a Spring application context you can use the JNDI factory class JndiObjectFactoryBean to perform dependency injection on your object's references to JMS destinations. However, often this strategy is cumbersome if there are a large number of destinations in the application or if there are advanced destination management features unique to the JMS provider. <b>Examples of such advanced destination management would be the creation of dynamic destinations</b> or support for a hierarchical namespace of destinations. The JmsTemplate delegates the resolution of a destination name to a JMS destination object to an implementation of the interface DestinationResolver.
              ... and never mentions it again. When creating the DefaultMessageListenerContainer you can't supply a DestinationResolver without a destination - so I think the dynamic bit is the "what 'Destination' actually points to" as opposed to the name being dynamic.

              I have potentially hundreds of queues and I thought there would be some way that spring would help with the management of it. It is starting to look like I must create my producer, create my consumer and then link them together myself and manage their life times.

              Unless anyone knows a better idea....?

              Comment


              • #8
                JMS dynamic destination resolution

                I am not using jndi, just spring, and developing a jms framework that has to also connect with flex's message service for async handling. I'm passing dynamic dest names and possibly a pub sub type to resolve to a jms Destination. The second wraps a dynamic destination created in the callback

                Code:
                   public Destination resolveJmsDestination(String dest, boolean pubSubDomain) throws JMSException {
                            return getJmsTemplate().getDestinationResolver().resolveDestinationName(createSession(), dest, pubSubDomain);
                   }
                Code:
                 public Message createAndReceive(final String dest, final String selector, final boolean pubSubDomain) {
                        return (Message) getJmsTemplate().execute(new ProducerCallback() {
                            public Object doInJms(Session session, MessageProducer producer) throws JMSException {
                                Destination d = getJmsTemplate().getDestinationResolver().resolveDestinationName(session, dest, pubSubDomain);
                                return session.createConsumer(d, selector).receive();
                            }
                        });
                    }
                Last edited by Helena; Dec 10th, 2008, 11:31 AM.

                Comment

                Working...
                X