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

  • JMS MessageListener listen frequency

    Hello,

    First of all, sorry for my bad English : I'm french

    I'm starting with JMS and I have a problem I can't manage to resolve. I have a class that manages a persistent queue in HSQLDB databse (the one by default). So, my class implements "MessageListener" interface.

    This class can send messages and receive them.
    In fact, the goal is to store emails and to send them later. For example, it will be used to store 500 generated emails and try to send the queued emails every 30 minutes.

    My problem is that when I queue an email using my class, the listener see it immediatly. If I generate emails during 3 minutes, each email will be handled immediately...

    I've seen that the "receiveTimeout" property of my JMS container should help me to define a frequency, but it does not seems to do anything.

    Here s my applicationContext-mail.xml file, managing the dedicated beans :
    Code:
       <bean id="mailManager" class="com.actoll.svad.vadm.svd.mail.metier.MailManagerImpl">
        </bean>
        
        <bean id="fileManager" class="com.actoll.svad.vadm.svd.mail.metier.FileManagerImpl">
            <property name="jmsTemplate" ref="jmsTemplate" />
            <property name="mailManager" ref="mailManager" />
        </bean>
    
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <property name="connectionFactory" ref="connectionFactory" />
            <property name="defaultDestination" ref="queue" />
        </bean>
    
        <jee:jndi-lookup id="connectionFactory" jndi-name="ConnectionFactory"
            cache="true" resource-ref="true" />
    
        <jee:jndi-lookup id="queue" jndi-name="/queue/mailQueue"
            cache="true" resource-ref="true" />
    
        <bean id="jmsContainer"
            class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory" />
            <property name="destination" ref="queue" />
            <property name="messageListener" ref="fileManager" />
            <property name="sessionTransacted" value="true" />
                    <property name="concurrentConsumers" value="5" />
                    <property name="receiveTimeout" value="2000" />
                    <property name="recoveryInterval" value="3000" /> 
        </bean>
    If I understand well, it should set a frequency of 2 seconds (2000 ms.).

    Here is my class that manages the queue of emails :
    ("file" can be assimilated to "queue" in French)
    Code:
    public class FileManagerImpl implements FileManager, MessageListener {
    
        /** La file. */
        private File file;
    
        /**
         * Classe d'interface utilisée pour l'injection de code. La classe
         * d'implémentation utilisée par le bean est définie dans
         * WEB-INF/applicationContext-mail.xml
         */
        private MailManager mailManager;
    
        /**
         * Spring interface : Helper class that simplifies synchronous JMS access
         * code.
         */
        private JmsTemplate jmsTemplate;
    
        public void ajouteUnMailEnFile(final Mail p_mail) {
            getJmsTemplate().send(getJmsTemplate().getDefaultDestination(),
                    new MessageCreator() {
                        public javax.jms.Message createMessage(final Session session)
                                throws JMSException {
                            System.out.println("Publication - " + p_mail.getTitre()
                                    + " - " + System.currentTimeMillis());
                            final ObjectMessage message = session
                                    .createObjectMessage(p_mail);
                            message.setLongProperty("startTime", System
                                    .currentTimeMillis());
                            return message;
                        }
                    });
        }
    
        @Override
        public void onMessage(javax.jms.Message arg0) {
    
            ObjectMessage objectMessage = (ObjectMessage) arg0;
            Mail mail;
            try {
                mail = (Mail) objectMessage.getObject();
                System.out.println("Réception - " + mail.getTitre() + " - "
                        + System.currentTimeMillis());
                try {
                    // send the email
                    boolean l_envoiOk = false;
                    System.out.println("Envoi du mail " + mail.getTitre() + "...");
                    l_envoiOk = getMailManager().envoiSimple(mail);
                    System.out.println("Envoi du mail " + mail.getTitre() + " : "
                            + l_envoiOk);
                } catch (ExceptionVadm e) {
                    System.out.println(e.getCodeErreur());
                    System.out.println(e.getMessageMachine());
                    e.printStackTrace();
                }
            } catch (JMSException e) {
                e.printStackTrace();
            }
    
            // TODO a implémenter.
        }
    
        /**
         * Paramètre la file.
         * 
         * @param p_file
         *            la nouvelle file
         */
        public void setFile(final File p_file) {
            this.file = p_file;
        }
    
        /**
         * Récupère la file.
         * 
         * @return la file
         */
        public File getFile() {
            return this.file;
        }
    
        public JmsTemplate getJmsTemplate() {
            return jmsTemplate;
        }
    
        public void setJmsTemplate(JmsTemplate jmsTemplate) {
            this.jmsTemplate = jmsTemplate;
        }
    
        /**
         * @return the mailManager
         */
        public final MailManager getMailManager() {
            return this.mailManager;
        }
    
        /**
         * @param p_mailManager
         *            the mailManager to set
         */
        public final void setMailManager(final MailManager p_mailManager) {
            this.mailManager = p_mailManager;
        }
    
    }
    So I have not a lot of things : I'm just tracing what happens, and I send the email when I got it from the queue.

    I made also a small JUnit test class to see what happens :
    Code:
        @Test
        public void testEnvoiDiffere() throws Exception {
            // Cretae an email
            Mail l_mail = new Mail();
            l_mail.setTitre("Mail de test JMS");
            l_mail.setDestinataire(DESTINATAIRE);
            l_mail.setExpediteur("[email protected]");
            l_mail.setMessagePlaintext("Texte du mail (Plaintext)");
    
            long startTime = System.currentTimeMillis(); // start loop date
            long dureeBoucle = 5; // loop wanted duration (seconds)
            double freqAjoutMail = 1; // frequency for mail adding in the queue (seconds)
    
            long currentTime = startTime;
            long dernierAjoutMail = 0;
            long indiceMail = 0;
    
            System.out.println("-------- start loop --------");
            while (System.currentTimeMillis() < (startTime + (dureeBoucle * 1000))) {
                currentTime = System.currentTimeMillis();
    
                // Ajout d'un mail ?
                if ((currentTime - dernierAjoutMail) >= (freqAjoutMail * 1000)) {
                    indiceMail++;
                    l_mail.setTitre("Mail n°" + indiceMail);
                    getFileManager().ajouteUnMailEnFile(l_mail);
                    dernierAjoutMail = System.currentTimeMillis();
                }
            }
            System.out.println("-------- end loop --------");
        }
    As you can see, it loops for 5 seconds. Each second, it adds an email to the queue. So, like my frequency for listening the queue is about 2 seconds, I should have a trace like :
    - add mail 1
    - add mail 2
    - see mails 1 and 2 in the queue
    - add mail 3
    - ...

    but what I get is :
    - add mail 1
    - send mail 1
    - add mail 2
    - send mail 2
    - ...

    As soon as a mail is added to the queue, the essage is delivered. There is no delay/frequency.

    Please, could you help me ?

  • #2
    JMS MessageListener listen frequency

    IllegalStateException: CWSIA0045E: The optional JMS operation Session. ... As advertised, it sets the message consumer's MessageListener . This makes sense. A single session can have ... The tag cloud indicates the frequency of tag use.

    Comment


    • #3
      I'm sorry janu03, but I don't understand your answer. I'm french and my english speaking is not so good... Could you explain me again, please ?

      Comment


      • #4
        Scheduled Processing

        I don't think you will be able to solve the Problem with setting a Message Listener Attribute.

        A possible solution for your problem will be scheduled message dispatching which is not a standard JMS Thing.

        Some Broker do allow you to define a additional property in JMS Message to tell the broker to delay delivery of received message.

        Using Oracle AQ for example you can set
        Code:
        msg.setIntProperty("JMS_OracleDelay", 10000);
        within the Jms Message using a MessagePostProcessor.
        Oracle AQ Broker will delay the delivery of the messag for 10 sec.
        Setting the proberty will cause that the message will not be available vor listeners till the delay is over.
        You want get the message in any Queue Browser etc. for listeners it will just occur in the queue after the delay is over.


        In Oracle this feature is called "Scheduled Message Processing" or something like that and
        I know that there is the same thing available for JBoss AQ and JBoss Messaging.
        The name of the property might be different but it is done the same way (check it in the JBoss Doc)

        Unfortunately Active Mq dose not support scheduled Message delivery yet.
        Last edited by [email protected]; Jul 2nd, 2009, 03:13 AM.

        Comment


        • #5
          Found it for JBoss and WebLogic

          WebLogic version


          Code:
          queueConnection = queueConnectionFactory.createQueueConnection();
          QueueSession queueSession = queueConnection.createQueueSession(true, 0);
          QueueSender queueSender = queueSession.createSender(queue);
          ObjectMessage jmsMsg = queueSession.createObjectMessage(message);
          
          //Casts queueSender to weblogic.jms.extensions.WLMessageProducer interface and set delivery time
          ((WLMessageProducer) queueSender).setTimeToDeliver(timeToDeliver);
          queueSender.send(jmsMsg);
          JBoss version

          Code:
          //Setting JMS_JBOSS_SCHEDULED_DELIVERY message property
          jmsMsg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", timeToDeliver);
          queueSender.send(jmsMsg);

          Comment

          Working...
          X