Results 1 to 8 of 8

Thread: Dynamic Queue creation and consumption

  1. #1

    Default 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. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    I suggest the reference guide, especially the part regarding MessageListenerContainers.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3

    Default

    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.

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    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?!
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5

    Default

    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.

  6. #6

    Default

    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.

  7. #7

    Default

    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....?

  8. #8
    Join Date
    Dec 2007
    Posts
    90

    Default 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 at 11:31 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •