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

  • JMS polling too frequently.

    I have a scenario where I need to look at a JMS queue, attempt to process
    messages and if not successful return the messages back to the queue. Basically the class that processes the message(s) routes the messages back to the pendingUpdatesChannel if processing is unsuccessful.

    Currently the channels are wired together as given below
    <integration:channel id="pendingUpdatesChannel">
    		<integration:queue capacity="1000"/>	
    	<jms:outbound-channel-adapter id="pendingQueueOutAdapter" 
    		<integration:poller id="updatesChannelPoller" receive-timeout="5">
            	 <integration:interval-trigger interval="5"/>
    		<integration:poller id="updatesQueuePoller" receive-timeout="1" >
    	        	 <integration:interval-trigger interval="60000"/>
    (here pendingUpdatesQueue is a JMS queue, and mainChannel is backed by a JMS queue using a message driven adapter)

    The problem is that the pendingUpdatesPoller does not poll every minute, but rather polls something like a for loop. I saw some threads that mention to set max-messages-per-poll="1", but I don't want to limit processing one message per poll.

    Can someone point out what's wrong here ? I would expect that the poller polls the queue, gets 'n' messages and keeps quiet for the polling interval.


  • #2
    The 'max-messages-per-poll' value limits the number of Messages that can be retrieved for each time it polls. So, the looping that you are seeing is happening for each poll until a null JMS Message is returned (that's the default).

    You mention that you expect it to get 'n' Messages for each poll. What is 'n' in your case? You can set max-messages-per-poll to be the max value of 'n' that you want to process for each poll.

    Does that make sense?


    • #3
      I would guess that n < 100.

      Say lets take the case that I set 100 as max-messages-per-poll; I end up making 100 calls to the JMS layer which I want to avoid.

      As I mentioned earlier the processor class puts the message back onto the tail of the queue if processing is unsuccessful , so typically I end up with too many calls to the JMS infrastructure layer for each poll.

      Another concern that I have is that- since I am using a pollable channel, if the java process is abnormally terminated, I will lose messages.


      • #4
        The poller should stop polling as soon as it receives a NULL JMS Message. Otherwise, it polls until max-messages-per-poll is reached.

        I'm not quite understanding what you want it to do. The way I am interpreting your comments, it seems that on one hand you are saying that it should try to receive as many messages as are available on the JMS queue, but then you are also saying that it calls receive() too many times. Can you clarify that a bit?



        • #5
          Sorry for being vague here. So this is how the flow is

          The processor-class (service activator) gets messages from the mainChannel , looks if the messages can be processed if yes they are send to a router, if not they are sent back to the pendingUpdatesChannel.

          A poller picks up messages from the Queue that backs the pendingUpdatesChannel and sends the message back to the mainChannel.

          Now, Consider the case where the processor received a message that cannot be processed right away (say due to target system downtime) the message gets pushed back to the pendingUpdatesChannel , which in turn gets moved to the pendingUpdatesQueue. At this point there is 1 message on the queue.

          I was expecting that the poller would pick all messages from the pendingUpdatesQueue and forward them to the mainchannel , once every X seconds.

          The issue is that the poller continously polls the JMS queue 'n' times , where n= max-messages-per-poll.

          I see your point that the poller continually polls the channel till a null is returned, but I guess that condition is never achieved because of the feedback mechanism on processing failure.

          I initially thought of introducing a delayer between the poller and the pendingUpdatesChannel , but am worried that I would lose messages if the process terminates when the message is in the delay queue, as it is not part of the same txn.


          • #6
            Okay... I think I am beginning to understand

            However it does still confuse me a bit when you say:
            I was expecting that the poller would pick all messages from the pendingUpdatesQueue and forward them to the mainchannel , once every X seconds.
            That *is* what's happening, right? The problem is that you actually don't want to process Messages *immediately* after sending them back to that queue. Is that correct?


            • #7
              Yes you are right

              I want to process the messages only at the defined polling intervals, but it appears to me that the poller instantly picks messages from the queue. (i.e. as soon as it gets onto the queue, irrespective of the trigger timing)

              I tried setting the receive-timeout of the poller to 1 millisec, thinking that the message got back onto the queue before the polling was complete, but that doesn't help.


              • #8
                Let me see if I can explain what you're seeing...

                The poller is the beginning of the flow, and that flow is invoked within a single Thread. At the end of the flow, if the Message was not processed, you send it back to the queue. At that point, the poller continues with the next iteration of the loop. So, the problem is that your unprocessed Message is already on the queue before even the next iteration. You can easily create an infinite loop with that type of configuration as long as one or more Messages are unprocessed within the poller's loop. The poller's loop is basically 0..max-messages-per-poll, and if at any point a NULL Message is received, it is essentially a "break" statement in the loop.

                So, I think you probably want to provide a transactional JmsTemplate to the inbound-channel-adapter, and if possible rely on JMS redelivery. That would mean that you simply throw an Exception to rollback rather than explicitly sending back to the JMS Queue yourself.


                • #9
                  Alright Mark, I'll try that approach. Thanks a lot for the help !