001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.test.messagedriven.support;
023:
024: import java.util.ArrayList;
025: import java.util.HashMap;
026: import java.util.Properties;
027:
028: import javax.jms.Connection;
029: import javax.jms.ConnectionFactory;
030: import javax.jms.Destination;
031: import javax.jms.ExceptionListener;
032: import javax.jms.JMSException;
033: import javax.jms.Message;
034: import javax.jms.MessageProducer;
035: import javax.jms.Session;
036: import javax.management.ObjectName;
037:
038: import org.jboss.mx.util.ObjectNameFactory;
039: import org.jboss.naming.Util;
040: import org.jboss.test.JBossTestCase;
041: import org.jboss.test.messagedriven.mbeans.TestMessageDrivenManagementMBean;
042:
043: /**
044: * Basic tests of message driven beans
045: *
046: * @author <a href="mailto:adrian@jboss.com>Adrian Brock</a>
047: * @version <tt>$Revision: 1.4</tt>
048: */
049: public abstract class BasicMessageDrivenUnitTest extends JBossTestCase
050: implements ExceptionListener {
051: protected static final long WAIT_TIME = 5000L;
052: protected static final long REPEATED_WAIT = 4;
053:
054: protected static final ObjectName testQueue = ObjectNameFactory
055: .create("jboss.mq.destination:service=Queue,name=testQueue");
056: protected static final Properties testQueueProps = new Properties();
057:
058: protected static final ObjectName testTopic = ObjectNameFactory
059: .create("jboss.mq.destination:service=Topic,name=testTopic");
060: protected static final Properties testTopicProps = new Properties();
061:
062: protected static final ObjectName testDurableTopic = ObjectNameFactory
063: .create("jboss.mq.destination:service=Topic,name=testDurableTopic");
064: protected static final Properties testDurableTopicProps = new Properties();
065:
066: static {
067: testQueueProps.put("destination", "queue/testQueue");
068: testQueueProps.put("destinationType", "javax.jms.Queue");
069:
070: testTopicProps.put("destination", "topic/testTopic");
071: testTopicProps.put("destinationType", "javax.jms.Topic");
072:
073: testDurableTopicProps.put("destination",
074: "topic/testDurableTopic");
075: testDurableTopicProps.put("destinationType", "javax.jms.Topic");
076: //testDurableTopicProps.put("clientID", "DurableSubscriberExample");
077: testDurableTopicProps.put("durability", "Durable");
078: testDurableTopicProps.put("subscriptionName", "messagedriven");
079: testDurableTopicProps.put("user", "john");
080: testDurableTopicProps.put("password", "needle");
081: }
082:
083: protected Thread thread;
084: protected boolean running = false;
085:
086: protected String mdbjar = "testmessagedriven.jar";
087: protected String mbeansar = "testmessagedriven.sar";
088:
089: protected ObjectName jmxDestination = ObjectNameFactory
090: .create("does:not=exist");
091: protected ObjectName dlqJMXDestination = ObjectNameFactory
092: .create("jboss.mq.destination:service=Queue,name=DLQ");
093: protected String connectionFactoryJNDI = "ConnectionFactory";
094: protected Destination destination;
095: protected Destination dlqDestination;
096: protected Properties defaultProps;
097: protected Properties props;
098:
099: protected Connection connection;
100: protected Session session;
101: protected HashMap producers = new HashMap();
102: protected ArrayList messages = new ArrayList();
103:
104: public BasicMessageDrivenUnitTest(String name,
105: ObjectName jmxDestination, Properties defaultProps) {
106: super (name);
107: this .jmxDestination = jmxDestination;
108: this .defaultProps = defaultProps;
109: }
110:
111: public void runTest(Operation[] ops, Properties props)
112: throws Exception {
113: startTest(props);
114: try {
115: for (int i = 0; i < ops.length; ++i)
116: ops[i].run();
117: } finally {
118: stopTest();
119: }
120: }
121:
122: public String getMDBDeployment() {
123: return mdbjar;
124: }
125:
126: public ObjectName getJMXDestination() {
127: return jmxDestination;
128: }
129:
130: public ObjectName getDLQJMXDestination() {
131: return dlqJMXDestination;
132: }
133:
134: public Destination getDestination() throws Exception {
135: if (destination != null)
136: return destination;
137: String jndiName = (String) getAttribute(getJMXDestination(),
138: "JNDIName");
139: destination = (Destination) lookup(jndiName, Destination.class);
140: return destination;
141: }
142:
143: public Destination getDLQDestination() throws Exception {
144: if (dlqDestination != null)
145: return dlqDestination;
146: String jndiName = (String) getAttribute(getDLQJMXDestination(),
147: "JNDIName");
148: dlqDestination = (Destination) lookup(jndiName,
149: Destination.class);
150: return dlqDestination;
151: }
152:
153: public MessageProducer getMessageProducer() throws Exception {
154: return getMessageProducer(getDestination());
155: }
156:
157: public MessageProducer getMessageProducer(Destination destination)
158: throws Exception {
159: MessageProducer producer = (MessageProducer) producers
160: .get(destination);
161: if (producer == null)
162: producer = getSession().createProducer(destination);
163: return producer;
164: }
165:
166: public Session getSession() throws Exception {
167: if (session != null)
168: return session;
169:
170: return getConnection().createSession(false,
171: Session.AUTO_ACKNOWLEDGE);
172: }
173:
174: public Connection getConnection() throws Exception {
175: if (connection != null)
176: return connection;
177:
178: ConnectionFactory factory = (ConnectionFactory) lookup(
179: connectionFactoryJNDI, ConnectionFactory.class);
180: connection = factory.createConnection();
181: connection.setExceptionListener(this );
182: return connection;
183: }
184:
185: public Connection getConnection(String user, String password)
186: throws Exception {
187: if (connection != null)
188: return connection;
189:
190: ConnectionFactory factory = (ConnectionFactory) lookup(
191: connectionFactoryJNDI, ConnectionFactory.class);
192: connection = factory.createConnection(user, password);
193: connection.setExceptionListener(this );
194: return connection;
195: }
196:
197: public void onException(JMSException e) {
198: log.debug("Notified of error", e);
199: Connection temp = connection;
200: connection = null;
201: try {
202: if (temp != null)
203: temp.close();
204: } catch (JMSException ignored) {
205: log.debug("Ignored ", ignored);
206: }
207: }
208:
209: public Message getTestMessage() throws Exception {
210: return getSession().createMessage();
211: }
212:
213: protected void setUp() throws Exception {
214: if ("testServerFound".equals(getName()))
215: return;
216: deploy(mbeansar);
217: }
218:
219: protected void tearDown() throws Exception {
220: if ("testServerFound".equals(getName()))
221: return;
222: try {
223: undeploy(mbeansar);
224: } catch (Throwable t) {
225: getLog().error("Error undeploying: " + mbeansar, t);
226: }
227: }
228:
229: protected void startTest(Properties props) throws Exception {
230: this .props = props;
231: clearMessages(getJMXDestination());
232: clearMessages(getDLQJMXDestination());
233: tidyup(props);
234: initProperties(props);
235: deploy(getMDBDeployment());
236: try {
237: // FIXME Need to wait for asynchrounous bootstrap of container
238: Thread.sleep(5000);
239: startReceiverThread();
240: } catch (Exception e) {
241: undeploy(getMDBDeployment());
242: throw e;
243: }
244: }
245:
246: protected void stopTest() {
247: if (connection != null) {
248: try {
249: connection.close();
250: } catch (Exception ignored) {
251: }
252: connection = null;
253: }
254: stopReceiverThread();
255: try {
256: undeploy(getMDBDeployment());
257: } catch (Throwable t) {
258: getLog().error("Error undeploying: " + getMDBDeployment(),
259: t);
260: }
261: try {
262: clearMessages(getJMXDestination());
263: tidyup(props);
264: } catch (Throwable t) {
265: getLog().error(
266: "Error clearing messages: " + getJMXDestination(),
267: t);
268: }
269: try {
270: clearMessages(getDLQJMXDestination());
271: } catch (Throwable t) {
272: getLog().error(
273: "Error clearing messages: "
274: + getDLQJMXDestination(), t);
275: }
276: }
277:
278: protected void clearMessages(ObjectName name) throws Exception {
279: if (name != null) {
280: getLog().info("Clearing messages " + name);
281: getServer().invoke(name, "removeAllMessages",
282: new Object[0], new String[0]);
283: }
284: }
285:
286: protected void tidyup(Properties props) throws Exception {
287: String name = props.getProperty("subscriptionName");
288: if (name != null) {
289: String user = props.getProperty("user");
290: if (user != null) {
291: String password = props.getProperty("password");
292: getConnection(user, password);
293: } else
294: getConnection();
295: try {
296: Session session = getSession();
297: try {
298: session.unsubscribe(name);
299: } catch (Throwable t) {
300: log.debug("Unsubscribe failed: ", t);
301: }
302: } finally {
303: try {
304: connection.close();
305: } catch (Exception ignored) {
306: }
307: connection = null;
308: }
309: }
310: }
311:
312: protected void activate(ObjectName name) throws Exception {
313: getServer().invoke(name, "startDelivery", new Object[0],
314: new String[0]);
315: }
316:
317: protected void deactivate(ObjectName name) throws Exception {
318: getServer().invoke(name, "stopDelivery", new Object[0],
319: new String[0]);
320: }
321:
322: protected void start(ObjectName name) throws Exception {
323: getServer()
324: .invoke(name, "create", new Object[0], new String[0]);
325: getServer().invoke(name, "start", new Object[0], new String[0]);
326: }
327:
328: protected void stop(ObjectName name) throws Exception {
329: getServer().invoke(name, "stop", new Object[0], new String[0]);
330: getServer().invoke(name, "destroy", new Object[0],
331: new String[0]);
332: }
333:
334: protected void initProperties(Properties props) throws Exception {
335: getLog().info("Init properties " + props);
336: getServer().invoke(
337: TestMessageDrivenManagementMBean.OBJECT_NAME,
338: "initProperties", new Object[] { props },
339: new String[] { Properties.class.getName() });
340: }
341:
342: protected void waitMessages(int expected, long wait)
343: throws Exception {
344: synchronized (this ) {
345: if (wait != 0)
346: wait(wait);
347:
348: for (int i = 0; i < REPEATED_WAIT
349: && messages.size() < expected; ++i)
350: wait(WAIT_TIME);
351: }
352: }
353:
354: protected ArrayList getMessages() throws Exception {
355: synchronized (this ) {
356: return new ArrayList(messages);
357: }
358: }
359:
360: protected void startReceiverThread() {
361: synchronized (this ) {
362: thread = new Thread(new ReceiverRunnable(), getClass()
363: .getName());
364: thread.start();
365: running = true;
366: }
367: }
368:
369: protected void stopReceiverThread() {
370: synchronized (this ) {
371: running = false;
372: while (thread != null) {
373: try {
374: this .notifyAll();
375: this .wait();
376: } catch (Throwable t) {
377: getLog().error(
378: "Error waiting for receiver thread to stop "
379: + thread, t);
380: }
381: }
382: }
383: }
384:
385: protected Object getAttribute(ObjectName name, String attribute)
386: throws Exception {
387: return getServer().getAttribute(name, attribute);
388: }
389:
390: protected Object lookup(String jndiName, Class clazz)
391: throws Exception {
392: return Util.lookup(getInitialContext(), jndiName, clazz);
393: }
394:
395: public class ReceiverRunnable implements Runnable {
396: public void run() {
397: try {
398: while (true) {
399: ArrayList result = (ArrayList) getAttribute(
400: TestMessageDrivenManagementMBean.OBJECT_NAME,
401: "Messages");
402: synchronized (BasicMessageDrivenUnitTest.this ) {
403: if (running == false)
404: break;
405: if (result.size() > 0) {
406: messages.addAll(result);
407: BasicMessageDrivenUnitTest.this .notifyAll();
408: }
409: BasicMessageDrivenUnitTest.this .wait(WAIT_TIME);
410: }
411: }
412: } catch (Throwable t) {
413: getLog().error("Error in receiver thread " + thread, t);
414: }
415:
416: synchronized (BasicMessageDrivenUnitTest.this) {
417: thread = null;
418: BasicMessageDrivenUnitTest.this.notifyAll();
419: }
420: }
421: }
422: }
|