View Javadoc
1 /*** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Exoffice Technologies. For written permission, 18 * please contact tma@netspace.net.au. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Exoffice Technologies. Exolab is a registered 23 * trademark of Exoffice Technologies. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 2001-2004 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: MessageListenerTest.java,v 1.7 2004/02/03 21:52:11 tanderson Exp $ 44 */ 45 package org.exolab.jmscts.test.session; 46 47 import javax.jms.Destination; 48 import javax.jms.Message; 49 import javax.jms.MessageConsumer; 50 import javax.jms.MessageListener; 51 import javax.jms.Session; 52 53 import org.apache.log4j.Category; 54 55 import junit.framework.Test; 56 57 import org.exolab.jmscts.core.AbstractSendReceiveTestCase; 58 import org.exolab.jmscts.core.MessageSender; 59 import org.exolab.jmscts.core.MessagingBehaviour; 60 import org.exolab.jmscts.core.SessionHelper; 61 import org.exolab.jmscts.core.TestContext; 62 import org.exolab.jmscts.core.TestCreator; 63 64 65 /*** 66 * This class tests that MessageListeners are invoked serially. 67 * 68 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> 69 * @version $Revision: 1.7 $ 70 * @see AbstractSendReceiveTestCase 71 * @see org.exolab.jmscts.core.SendReceiveTestRunner 72 * @jmscts.message TextMessage 73 * @jmscts.delivery asynchronous 74 */ 75 public class MessageListenerTest extends AbstractSendReceiveTestCase { 76 77 /*** 78 * The destinations to create prior to running the test 79 */ 80 private static final String[] DESTINATIONS = {"dest1", "dest2", "dest3"}; 81 82 /*** 83 * The logger 84 */ 85 private static final Category log = 86 Category.getInstance(MessageListenerTest.class); 87 88 89 /*** 90 * Contruct a new <code>MessageListenerTest</code> 91 * 92 * @param name the name of test case 93 */ 94 public MessageListenerTest(String name) { 95 super(name); 96 } 97 98 /*** 99 * Sets up the test suite. 100 * 101 * @return an instance of this class that may be run by 102 * {@link org.exolab.jmscts.core.JMSTestRunner} 103 */ 104 public static Test suite() { 105 return TestCreator.createSendReceiveTest(MessageListenerTest.class); 106 } 107 108 /*** 109 * Returns the list of destination names used by this test case. These 110 * are used to pre-administer destinations prior to running the test case. 111 * 112 * @return the list of destinations used by this test case 113 */ 114 public String[] getDestinations() { 115 return DESTINATIONS; 116 } 117 118 /*** 119 * Verifies that message listeners are invoked serially. 120 * 121 * @jmscts.requirement session.listener.serialization 122 * @throws Exception for any error 123 */ 124 public void testSerialInvocation() throws Exception { 125 final int send = 50; 126 final int expected = send * DESTINATIONS.length; 127 final long sleep = 100; 128 129 MessageConsumer[] consumers = new MessageConsumer[DESTINATIONS.length]; 130 131 TestListener listener = new TestListener(expected, sleep); 132 133 TestContext context = getContext(); 134 MessagingBehaviour behaviour = context.getMessagingBehaviour(); 135 for (int i = 0; i < DESTINATIONS.length; ++i) { 136 Destination destination = getDestination(DESTINATIONS[i]); 137 String name = null; 138 if (behaviour.getDurable()) { 139 name = SessionHelper.getSubscriberName(); 140 } 141 MessageConsumer consumer = SessionHelper.createConsumer( 142 context, destination, name); 143 consumer.setMessageListener(listener); 144 consumers[i] = consumer; 145 } 146 Message message = context.getMessage(); 147 for (int i = 0; i < DESTINATIONS.length; ++i) { 148 Destination destination = getDestination(DESTINATIONS[i]); 149 MessageSender sender = SessionHelper.createSender( 150 context, destination); 151 sender.send(message, send); 152 sender.close(); 153 } 154 Session session = context.getSession(); 155 if (session.getTransacted()) { 156 session.commit(); 157 } 158 159 synchronized (listener) { 160 if (listener.getReceived() != expected) { 161 listener.wait(expected * sleep * 2); 162 } 163 } 164 for (int i = 0; i < consumers.length; ++i) { 165 consumers[i].close(); 166 } 167 if (listener.getFailures() != 0) { 168 fail("The listener was not invoked serially"); 169 } 170 if (listener.getReceived() != expected) { 171 fail("Received " + listener.getReceived() 172 + " messages, but expected " + expected); 173 } 174 } 175 176 /*** 177 * MessageListener implementation which checks if 178 * onMessage() is invoked by multiple threads 179 */ 180 private class TestListener implements MessageListener { 181 /*** 182 * The no. of expected messages 183 */ 184 private final int _expected; 185 186 /*** 187 * The time to wait for in onMessage(), before returning 188 */ 189 private final long _sleep; 190 191 /*** 192 * Determines if onMessage() has been invoked by another thread 193 */ 194 private boolean _invoked = false; 195 196 /*** 197 * The no. of times onMessage() has been invoked by multiple threads 198 */ 199 private int _failures = 0; 200 201 /*** 202 * The no. of received messages 203 */ 204 private int _received = 0; 205 206 207 /*** 208 * Construct a new <code>TestListener</code> 209 * 210 * @param expected the no.of messages to receive 211 * @param sleep the time to wait in onMessage() 212 */ 213 public TestListener(int expected, long sleep) { 214 _expected = expected; 215 _sleep = sleep; 216 } 217 218 /*** 219 * Handle a message 220 * 221 * @param message the message 222 */ 223 public void onMessage(Message message) { 224 synchronized (this) { 225 if (_invoked) { 226 _failures++; 227 } 228 _invoked = true; 229 ++_received; 230 if (_received == _expected) { 231 notify(); 232 } 233 } 234 try { 235 Thread.currentThread().sleep(_sleep); 236 } catch (InterruptedException ignore) { 237 log.debug("TestListener interrupted while sleeping " 238 + "- continuing"); 239 } 240 synchronized (this) { 241 _invoked = false; 242 } 243 } 244 245 /*** 246 * Returns the no. of times {@link #onMessage()} was invoked by 247 * more than one thread 248 * 249 * @return the no. of failures 250 */ 251 public int getFailures() { 252 return _failures; 253 } 254 255 /*** 256 * Returns the no. of received messages 257 * 258 * @return the no. of received messages 259 */ 260 public int getReceived() { 261 return _received; 262 } 263 } 264 265 }

This page was automatically generated by Maven