/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.jbossmessaging.test; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueReceiver; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.jms.Session; import javax.naming.Context; import javax.naming.InitialContext; import org.jboss.test.JBossJMSTestCase; import org.jboss.test.util.jms.JMSDestinationsUtil; /** * JBossSessionRecoverUnitTestCase.java * * a simple session.recover test of JBossMQ * * @author Seth Sites * @version $Revision: 105321 $ */ public class JBossSessionRecoverUnitTestCase extends JBossJMSTestCase { String QUEUE_FACTORY = "ConnectionFactory"; String TEST_QUEUE = "queue/testQueue"; Context context; QueueConnection queueConnection; QueueSession session; int counter=0; Exception exception=null; public JBossSessionRecoverUnitTestCase(String name) throws Exception { super(name); } protected void setUp() throws Exception { // call setUp() in superclass super.setUp() ; JMSDestinationsUtil.setupBasicDestinations(); this.getLog().debug("JBossSessionRecoverUnitTestCase, ConnectionFactory started"); } protected void tearDown() throws Exception { this.getLog().debug("JBossSessionRecoverUnitTestCase, ConnectionFactory done"); JMSDestinationsUtil.destroyDestinations(); // call tearDown() in superclass super.tearDown() ; } // Emptys out all the messages in a queue private void drainQueue() throws Exception { QueueSession session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = (Queue)context.lookup(TEST_QUEUE); QueueReceiver receiver = session.createReceiver(queue); Message message = receiver.receive( 1000 ); int c=0; while( message != null ) { message = receiver.receive( 1000 ); c++; } if( c!=0 ) getLog().debug(" Drained "+c+" messages from the queue"); session.close(); } static public void main ( String []args ) { String newArgs[] = { "org.jboss.test.jbossmq.test.JBossSessionRecoverUnitTestCase" }; junit.swingui.TestRunner.main(newArgs); } protected void connect() throws Exception { if( context == null ) { context = new InitialContext(); } QueueConnectionFactory queueFactory = (QueueConnectionFactory) context.lookup(QUEUE_FACTORY); queueConnection = queueFactory.createQueueConnection(); getLog().debug("Connection to JBossMQ established."); } /** * Test that session.recover works with a message listener */ public void testQueueSessionRecovermessageListener() throws Exception { counter = 0; getLog().debug("Starting session.recover() Message Listener test"); connect(); queueConnection.start(); drainQueue(); session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = (Queue)context.lookup(TEST_QUEUE); QueueSender sender = session.createSender(queue); // send 20 messages to the queue for ( int i=0; i<20; i++ ) { sender.send(session.createObjectMessage(new Integer(i))); } //close the session, so we can start one with CLIENT_ACKNOWLEDGE session.close(); queueConnection.stop(); session = queueConnection.createQueueSession( false, Session.CLIENT_ACKNOWLEDGE ); //create our receiver QueueReceiver receiver = session.createReceiver( queue ); MessageListener messagelistener = new MessageListener() { public void onMessage(Message message) { processMessage( message ); } }; receiver.setMessageListener( messagelistener ); queueConnection.start(); //since we put in 20 messages and recovered after receiving 20 we should receive those 20 //back and get 40 total while ( counter < 40 && exception == null ) { try { Thread.sleep( 500 ); } catch ( InterruptedException ie ) { } } if ( exception != null ) { queueConnection.close(); throw exception; } queueConnection.close(); getLog().debug("session.recover() Message Listener passed"); } private void processMessage ( Message message ) { try { if ( message instanceof ObjectMessage ) { counter++; ObjectMessage objectmessage = (ObjectMessage)message; Integer integer = (Integer)objectmessage.getObject(); int mynumber = integer.intValue(); getLog().debug("message object " + integer + " counter=" + counter ); if ( mynumber == 19 ) { if (counter == 20) { session.recover(); } else { message.acknowledge(); } } } } catch ( JMSException e ) { exception = e; } } class Synch { boolean waiting = false; public synchronized void doWait(long timeout) throws InterruptedException { waiting = true; this.wait(timeout); } public synchronized void doNotify() throws InterruptedException { while (waiting == false) wait(100); this.notifyAll(); } } /** * Test that session.recover delivers messages in the correct orer */ public void testQueueSessionRecoverMessageListenerOrder() throws Exception { counter = 0; exception = null; getLog().debug("Starting session.recover() Message Listener Order test"); connect(); queueConnection.start(); drainQueue(); session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = (Queue)context.lookup(TEST_QUEUE); QueueSender sender = session.createSender(queue); // send 4 messages to the queue for (int i=0; i<4; ++i) { sender.send(session.createObjectMessage(new Integer(i))); } //create our receiver QueueReceiver receiver = session.createReceiver( queue ); final Synch synch = new Synch(); MessageListener messagelistener = new MessageListener() { public void onMessage(Message message) { checkMessagesInOrder(session, message, synch); } }; receiver.setMessageListener( messagelistener ); queueConnection.start(); synch.doWait(10000); if ( exception != null ) { queueConnection.close(); throw exception; } queueConnection.close(); getLog().debug("session.recover() Message Listener Order passed"); } private void checkMessagesInOrder(Session session, Message message, Synch synch) { try { ObjectMessage objectmessage = (ObjectMessage)message; Integer integer = (Integer)objectmessage.getObject(); int mynumber = integer.intValue(); if (message.getJMSRedelivered() == false) { log.debug("Recovering " + mynumber); session.recover(); return; } log.debug("Checking " + mynumber); assertTrue("Expected messages in order", mynumber == counter); counter++; if (counter == 4) synch.doNotify(); } catch (Exception e) { exception = e; } } /** * Test that session.recover works with receive */ public void testQueueSessionRecoverReceive() throws Exception { counter = 0; getLog().debug("Starting session.recover() receive test"); connect(); queueConnection.start(); drainQueue(); session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = (Queue)context.lookup(TEST_QUEUE); QueueSender sender = session.createSender(queue); // send 20 messages to the queue for ( int i=0; i<20; i++ ) { sender.send(session.createObjectMessage(new Integer(i))); } //close the session, so we can start one with CLIENT_ACKNOWLEDGE session.close(); queueConnection.stop(); session = queueConnection.createQueueSession( false, Session.CLIENT_ACKNOWLEDGE ); //create our receiver QueueReceiver receiver = session.createReceiver( queue ); queueConnection.start(); Message message = receiver.receive( 1000 ); int messagecounter=0; while( message != null ) { message = receiver.receive( 1000 ); messagecounter++; } if ( messagecounter != 20 ) { throw new Exception ( "Not all sent messages were delivered! messagecounter=" + messagecounter ); } //we got all of our messages, let's recover session.recover(); message = receiver.receive(); messagecounter=0; while( message != null ) { if ( !message.getJMSRedelivered() ) { throw new Exception ( "Message was not marked as redelivered! messagecounter=" + messagecounter ); } message.acknowledge(); messagecounter++; //workaround to keep from timing out since there are no more message on the server if ( messagecounter < 15 ) { message = receiver.receive(); } else { message = receiver.receive ( 1000 ); } } if ( messagecounter != 20 ) { throw new Exception ( "Not all unacknowledged messages were redelivered! messagecounter=" + messagecounter ); } queueConnection.close(); getLog().debug("session.recover() receive passed"); } /** * Test that session.recover works with receive(timeout) */ public void testQueueSessionRecoverReceiveTimeout() throws Exception { counter = 0; getLog().debug("Starting session.recover() receive(timeout) test"); connect(); queueConnection.start(); drainQueue(); session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = (Queue)context.lookup(TEST_QUEUE); QueueSender sender = session.createSender(queue); // send 20 messages to the queue for ( int i=0; i<20; i++ ) { sender.send(session.createObjectMessage(new Integer(i))); } //close the session, so we can start one with CLIENT_ACKNOWLEDGE session.close(); queueConnection.stop(); session = queueConnection.createQueueSession( false, Session.CLIENT_ACKNOWLEDGE ); //create our receiver QueueReceiver receiver = session.createReceiver( queue ); queueConnection.start(); Message message = receiver.receive( 1000 ); int messagecounter=0; while( message != null ) { message = receiver.receive( 1000 ); messagecounter++; } if ( messagecounter != 20 ) { throw new Exception ( "Not all sent messages were delivered! messagecounter=" + messagecounter ); } //we got all of our messages, let's recover session.recover(); message = receiver.receive(1000); messagecounter=0; while( message != null ) { if ( !message.getJMSRedelivered() ) { throw new Exception ( "Message was not marked as redelivered! messagecounter=" + messagecounter ); } message.acknowledge(); messagecounter++; message = receiver.receive( 1000 ); } if ( messagecounter != 20 ) { throw new Exception ( "Not all unacknowledged messages were redelivered! messagecounter=" + messagecounter ); } queueConnection.close(); getLog().debug("session.recover() receive(timeout) passed"); } /** * Test that session.recover works with receiveNoWait */ public void testQueueSessionRecoverReceiveNoWait() throws Exception { counter = 0; getLog().debug("Starting session.recover() receiveNoWait test"); connect(); queueConnection.start(); drainQueue(); session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = (Queue)context.lookup(TEST_QUEUE); QueueSender sender = session.createSender(queue); // send 20 messages to the queue for ( int i=0; i<20; i++ ) { sender.send(session.createObjectMessage(new Integer(i))); } //close the session, so we can start one with CLIENT_ACKNOWLEDGE session.close(); queueConnection.stop(); session = queueConnection.createQueueSession( false, Session.CLIENT_ACKNOWLEDGE ); //create our receiver QueueReceiver receiver = session.createReceiver( queue ); queueConnection.start(); //NOTE! The semantics of receiveNoWait do not guarantee the message is available //immediately after the message is sent //It will be available some indeterminate time later. //This is fine and as per spec. //To implement receiveNoWait otherwise would be very costly //Also other messaging systems e.g. Sun implement it this way Thread.sleep(1000); Message message = receiver.receiveNoWait(); int messagecounter=0; while( message != null ) { message = receiver.receiveNoWait(); messagecounter++; } if ( messagecounter != 20 ) { throw new Exception ( "Not all sent messages were delivered! messagecounter=" + messagecounter ); } //we got all of our messages, let's recover session.recover(); // See previous note on sleep Thread.sleep(1000); message = receiver.receiveNoWait(); messagecounter=0; while( message != null ) { if ( !message.getJMSRedelivered() ) { throw new Exception ( "Message was not marked as redelivered! messagecounter=" + messagecounter ); } message.acknowledge(); messagecounter++; message = receiver.receiveNoWait(); } if ( messagecounter != 20 ) { throw new Exception ( "Not all unacknowledged messages were redelivered! messagecounter=" + messagecounter ); } queueConnection.close(); getLog().debug("session.recover() receiveNoWait passed"); } }