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: ListenerTest.java,v 1.7 2004/02/03 07:32:07 tanderson Exp $ 44 */ 45 package org.exolab.jmscts.test.connection; 46 47 import javax.jms.Connection; 48 import javax.jms.Destination; 49 import javax.jms.MessageConsumer; 50 51 import org.apache.log4j.Category; 52 53 import junit.framework.Test; 54 55 import org.exolab.jmscts.core.AbstractSendReceiveTestCase; 56 import org.exolab.jmscts.core.DelayedAction; 57 import org.exolab.jmscts.core.EchoListener; 58 import org.exolab.jmscts.core.MessageReceiver; 59 import org.exolab.jmscts.core.MessageSender; 60 import org.exolab.jmscts.core.SessionHelper; 61 import org.exolab.jmscts.core.TestContext; 62 import org.exolab.jmscts.core.TestContextHelper; 63 import org.exolab.jmscts.core.TestCreator; 64 import org.exolab.jmscts.core.WaitingListener; 65 66 67 /*** 68 * This class tests the behaviour of stopping and closing a connection 69 * while a listener is active. 70 * 71 * NOTE: Temporary destinations cannot be used as a separate connection is 72 * required to verify that the test is successful. 73 * 74 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> 75 * @version $Revision: 1.7 $ 76 * @see AbstractSendReceiveTestCase 77 * @see org.exolab.jmscts.core.SendReceiveTestRunner 78 * @jmscts.session all 79 * @jmscts.message TextMessage 80 * @jmscts.delivery NON_PERSISTENT, administered, asynchronous 81 * @jmscts.delivery PERSISTENT, administered, asynchronous 82 */ 83 public class ListenerTest extends AbstractSendReceiveTestCase { 84 85 /*** 86 * The destination that the message listener receives messages on 87 */ 88 private static final String REQUEST = "requestClose"; 89 90 /*** 91 * The destination that the message listeners send messages to 92 */ 93 private static final String REPLY = "replyClose"; 94 95 /*** 96 * The destinations to create prior to running the test 97 */ 98 private static final String[] DESTINATIONS = {REQUEST, REPLY}; 99 100 /*** 101 * The logger 102 */ 103 private static final Category log = 104 Category.getInstance(ListenerTest.class); 105 106 107 /*** 108 * Construct a new <code>ListenerTest</code> 109 * 110 * @param name the name of test case 111 */ 112 public ListenerTest(String name) { 113 super(name); 114 } 115 116 /*** 117 * Sets up the test suite 118 * 119 * @return an instance of this class that may be run by 120 * {@link org.exolab.jmscts.core.JMSTestRunner} 121 */ 122 public static Test suite() { 123 return TestCreator.createSendReceiveTest(ListenerTest.class); 124 } 125 126 /*** 127 * Returns if this test can share resources with other test cases. 128 * This implementation always returns <code>false</code>, to 129 * ensure that a new connection is created for each test. 130 * 131 * @return <code>false</code> 132 */ 133 public boolean share() { 134 return false; 135 } 136 137 /*** 138 * Returns if the connection should be started prior to running the test. 139 * This implementation always returns <code>false</code> to avoid 140 * conflicts with test cases 141 * 142 * @return <code>false</code> 143 */ 144 public boolean startConnection() { 145 return false; 146 } 147 148 /*** 149 * Returns the list of destination names used by this test case. These 150 * are used to pre-create destinations prior to running the test case. 151 * 152 * @return the list of destinations used by this test case 153 */ 154 public String[] getDestinations() { 155 return DESTINATIONS; 156 } 157 158 /*** 159 * Verifies that running MessageListeners have full access to the 160 * connection, if the connection is stopped. 161 * 162 * @jmscts.requirement connection.stop.listeners 163 * @throws Exception for any error 164 */ 165 public void testConnectionStop() throws Exception { 166 final int count = 10; // the number of messages to send 167 TestContext context = getContext(); 168 169 // set up a receiver for the destination that the listener replies to 170 MessageReceiver receiver = createReceiver(REPLY); 171 172 try { 173 runTest(context, true, count); 174 175 // restart the connection and verify that the listener sent a 176 // message 177 Connection connection = context.getConnection(); 178 connection.start(); 179 receive(receiver, count); 180 } finally { 181 receiver.remove(); 182 } 183 } 184 185 /*** 186 * Verifies that running MessageListeners have full access to connection if 187 * the connection is closed - the close invocation must wait until they 188 * complete. 189 * 190 * @jmscts.requirement connection.close.listeners 191 * @throws Exception for any error 192 */ 193 public void testConnectionClose() throws Exception { 194 final int count = 10; // the number of messages to send 195 TestContext context = getContext(); 196 197 // set up a duplicate context, to enable a receiver to be created 198 // for the destination that the listener replies to 199 TestContext context2 = TestContextHelper.createSendReceiveContext( 200 context); 201 MessageReceiver receiver = createReceiver(context2, REPLY); 202 203 try { 204 runTest(context, false, count); 205 206 // start the duplicate connection 207 context2.getConnection().start(); 208 209 // verify that the listener sent a message 210 receive(receiver, count); 211 } finally { 212 receiver.remove(); 213 context2.getConnection().close(); 214 } 215 } 216 217 /*** 218 * Run the test 219 * 220 * @param context the test context 221 * @param stop if <code>true</code>, stop the connection, else close it 222 * @param count the number of messages to send 223 * @throws Exception for any error 224 */ 225 private void runTest(TestContext context, boolean stop, 226 int count) throws Exception { 227 final int delayTime = 500; // 500 ms 228 Connection connection = context.getConnection(); 229 Destination request = getDestination(REQUEST); 230 MessageConsumer consumer = null; 231 boolean durable = context.getMessagingBehaviour().getDurable(); 232 233 try { 234 // set up the listener 235 String name = (durable) ? SessionHelper.getSubscriberName() : null; 236 consumer = SessionHelper.createConsumer(context, request, name); 237 MessageSender sender = createSender(context, REPLY); 238 EchoListener replier = new EchoListener( 239 context.getSession(), sender, count, true); 240 final WaitingListener listener = new WaitingListener(replier, 1); 241 consumer.setMessageListener(listener); 242 243 // send a message and start the connection 244 send(REQUEST, 1); 245 connection.start(); 246 247 // wait for the listener to start processing before 248 // stopping/closing the connection 249 log.debug("waiting for listener"); 250 listener.waitForReceipt(); 251 252 // notify the listener in a separate thread that it may proceed 253 // with processing. The notification has to occur in a separate 254 // thread else close would block indefinitely waiting for the 255 // listener to complete. 256 // The half second delay is to help ensure that close is invoked 257 // before the listener begins processing the message 258 log.debug("notifying listener"); 259 DelayedAction action = new DelayedAction(delayTime) { 260 public void runProtected() { 261 listener.notifyContinue(); 262 } 263 }; 264 action.start(); 265 if (stop) { 266 connection.stop(); 267 } else { 268 connection.close(); 269 } 270 listener.waitForCompletion(); // make sure the listener is done 271 } finally { 272 try { 273 consumer.close(); 274 } catch (Exception exception) { 275 fail("Attempting to invoke close() for a consumer on a " 276 + ((stop) ? "stopped" : "closed") + " connection threw " 277 + "exception=" + exception.getClass().getName() 278 + ", message=" + exception.getMessage()); 279 } 280 } 281 } 282 283 }

This page was automatically generated by Maven