1
2
3
4
5
6
7 package org.mule.module.spring.events;
8
9 import org.mule.api.MuleEventContext;
10 import org.mule.api.MuleException;
11 import org.mule.api.MuleMessage;
12 import org.mule.module.client.MuleClient;
13 import org.mule.tck.functional.EventCallback;
14 import org.mule.tck.junit4.FunctionalTestCase;
15 import org.mule.transformer.AbstractMessageTransformer;
16 import org.mule.util.ExceptionUtils;
17 import org.mule.util.concurrent.Latch;
18
19 import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
20 import edu.emory.mathcs.backport.java.util.concurrent.Executors;
21 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
22 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
23 import org.junit.Test;
24 import org.springframework.context.ApplicationContext;
25 import org.springframework.context.ApplicationEvent;
26 import org.springframework.context.event.ContextRefreshedEvent;
27 import org.springframework.context.support.AbstractApplicationContext;
28
29 import static org.junit.Assert.assertEquals;
30 import static org.junit.Assert.assertNotNull;
31 import static org.junit.Assert.assertNull;
32 import static org.junit.Assert.assertTrue;
33 import static org.junit.Assert.fail;
34
35 public class SpringEventsTestCase extends FunctionalTestCase
36 {
37
38 protected static final int DEFAULT_LATCH_TIMEOUT = 10000;
39
40 private static final int NUMBER_OF_MESSAGES = 10;
41 volatile AtomicInteger eventCounter1;
42 volatile AtomicInteger eventCounter2;
43
44 @Override
45 protected void doSetUp() throws Exception
46 {
47 super.doSetUp();
48 eventCounter1 = new AtomicInteger(0);
49 eventCounter2 = new AtomicInteger(0);
50 }
51
52 @Override
53 protected String getConfigResources()
54 {
55 return "mule-events-app-context.xml";
56 }
57
58 @Test
59 public void testManagerIsInstanciated() throws Exception
60 {
61 assertTrue(muleContext.isInitialised());
62 assertTrue(muleContext.isStarted());
63 assertNotNull(muleContext.getRegistry().lookupObject(
64 AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME));
65 }
66
67 @Test
68 public void testRemovingListeners() throws Exception
69 {
70 TestSubscriptionEventBean subscriptionBean = (TestSubscriptionEventBean) muleContext.getRegistry()
71 .lookupObject("testSubscribingEventBean1");
72 assertNotNull(subscriptionBean);
73 MuleEventMulticaster multicaster = (MuleEventMulticaster) muleContext.getRegistry().lookupObject(
74 AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME);
75 assertNotNull(multicaster);
76
77 Latch whenFinished = new Latch();
78 subscriptionBean.setEventCallback(new CountingEventCallback(eventCounter1, 1, whenFinished));
79
80 multicaster.removeApplicationListener(subscriptionBean);
81 MuleClient client = new MuleClient(muleContext);
82 client.send("vm://event.multicaster", "Test Spring MuleEvent", null);
83
84 assertEquals(0, eventCounter1.get());
85
86 multicaster.addApplicationListener(subscriptionBean);
87 client.send("vm://event.multicaster", "Test Spring MuleEvent", null);
88
89 assertTrue(whenFinished.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
90 assertEquals(1, eventCounter1.get());
91 eventCounter1.set(0);
92
93 multicaster.removeAllListeners();
94 client.send("vm://event.multicaster", "Test Spring MuleEvent", null);
95
96 assertEquals(0, eventCounter1.get());
97 multicaster.addApplicationListener(subscriptionBean);
98
99 subscriptionBean.setEventCallback(null);
100 }
101
102 @Test
103 public void testReceivingANonSubscriptionMuleEvent() throws Exception
104 {
105 TestMuleEventBean bean = (TestMuleEventBean) muleContext.getRegistry().lookupObject(
106 "testNonSubscribingMuleEventBean");
107 assertNotNull(bean);
108
109
110 Latch whenFinished = new Latch();
111 bean.setEventCallback(new CountingEventCallback(eventCounter1, 1, whenFinished));
112
113 MuleClient client = new MuleClient(muleContext);
114 client.send("vm://event.multicaster", "Test Spring MuleEvent", null);
115
116 whenFinished.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
117 assertEquals(1, eventCounter1.get());
118 }
119
120 @Test
121 public void testReceivingASpringEvent() throws Exception
122 {
123 TestApplicationEventBean bean = (TestApplicationEventBean) muleContext.getRegistry().lookupObject(
124 "testEventSpringBean");
125 assertNotNull(bean);
126
127 final Latch whenFinished = new Latch();
128 EventCallback callback = new EventCallback()
129 {
130 public void eventReceived(MuleEventContext context, Object o) throws Exception
131 {
132 assertNull(context);
133 if (o instanceof TestApplicationEvent)
134 {
135 if (eventCounter1.incrementAndGet() == 1)
136 {
137 whenFinished.countDown();
138 }
139 }
140 }
141 };
142
143 bean.setEventCallback(callback);
144
145 ApplicationContext context = ((MuleEventMulticaster) muleContext.getRegistry().lookupObject(
146 "applicationEventMulticaster")).applicationContext;
147 context.publishEvent(new TestApplicationEvent(context));
148
149 whenFinished.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
150 assertEquals(1, eventCounter1.get());
151 }
152
153 @Test
154 public void testReceivingAllEvents() throws Exception
155 {
156 TestAllEventBean bean = (TestAllEventBean) muleContext.getRegistry().lookupObject("testAllEventBean");
157 assertNotNull(bean);
158
159 Latch whenFinished = new Latch();
160 bean.setEventCallback(new CountingEventCallback(eventCounter1, 2, whenFinished));
161
162 MuleClient client = new MuleClient(muleContext);
163 client.send("vm://event.multicaster", "Test Spring MuleEvent", null);
164 ApplicationContext context = ((MuleEventMulticaster) muleContext.getRegistry().lookupObject(
165 "applicationEventMulticaster")).applicationContext;
166 context.publishEvent(new TestApplicationEvent(context));
167
168 whenFinished.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
169 assertEquals(2, eventCounter1.get());
170 }
171
172 @Test
173 public void testReceivingASubscriptionEvent() throws Exception
174 {
175 TestSubscriptionEventBean subscriptionBean = (TestSubscriptionEventBean) muleContext.getRegistry()
176 .lookupObject("testSubscribingEventBean1");
177 assertNotNull(subscriptionBean);
178
179 Latch whenFinished = new Latch();
180 subscriptionBean.setEventCallback(new CountingEventCallback(eventCounter1, 1, whenFinished));
181
182 MuleClient client = new MuleClient(muleContext);
183 client.send("vm://event.multicaster", "Test Spring MuleEvent", null);
184
185 whenFinished.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
186 assertEquals(1, eventCounter1.get());
187 }
188
189 @Test
190 public void testReceiveAndPublishEvent() throws Exception
191 {
192 TestSubscriptionEventBean bean1 = (TestSubscriptionEventBean) muleContext.getRegistry().lookupObject(
193 "testSubscribingEventBean1");
194 assertNotNull(bean1);
195
196 final Latch whenFinished1 = new Latch();
197 EventCallback callback = new EventCallback()
198 {
199 public void eventReceived(MuleEventContext context, Object o) throws Exception
200 {
201 MuleApplicationEvent returnEvent = new MuleApplicationEvent("MuleEvent from a spring bean",
202 "vm://testBean2");
203 MuleApplicationEvent e = (MuleApplicationEvent) o;
204 e.getApplicationContext().publishEvent(returnEvent);
205 if (eventCounter1.incrementAndGet() == NUMBER_OF_MESSAGES)
206 {
207 whenFinished1.countDown();
208 }
209 }
210 };
211 bean1.setEventCallback(callback);
212
213 TestSubscriptionEventBean bean2 = (TestSubscriptionEventBean) muleContext.getRegistry().lookupObject(
214 "testSubscribingEventBean2");
215 assertNotNull(bean2);
216
217 Latch whenFinished2 = new Latch();
218 bean2.setEventCallback(new CountingEventCallback(eventCounter2, NUMBER_OF_MESSAGES, whenFinished2));
219
220
221 this.doSend("vm://event.multicaster", "Test Spring MuleEvent", NUMBER_OF_MESSAGES);
222
223 whenFinished1.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
224 whenFinished2.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
225 assertEquals(NUMBER_OF_MESSAGES, eventCounter1.get());
226 assertEquals(NUMBER_OF_MESSAGES, eventCounter2.get());
227 }
228
229 @Test
230 public void testPublishOnly() throws Exception
231 {
232 final MuleApplicationEvent event = new MuleApplicationEvent("MuleEvent from a spring bean",
233 "vm://testBean2");
234
235 TestSubscriptionEventBean bean2 = (TestSubscriptionEventBean) muleContext.getRegistry().lookupObject(
236 "testSubscribingEventBean2");
237 assertNotNull(bean2);
238
239 Latch whenFinished = new Latch();
240 bean2.setEventCallback(new CountingEventCallback(eventCounter1, NUMBER_OF_MESSAGES, whenFinished));
241
242
243 this.doPublish(event, NUMBER_OF_MESSAGES);
244
245 whenFinished.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
246 assertEquals(NUMBER_OF_MESSAGES, eventCounter1.get());
247 }
248
249 @Test
250 public void testPublishWithEventAwareTransformer() throws Exception
251 {
252 CountDownLatch transformerLatch = new CountDownLatch(1);
253
254 TestEventAwareTransformer trans = new TestEventAwareTransformer();
255 trans.setLatch(transformerLatch);
256 muleContext.getRegistry().registerTransformer(trans);
257
258 MuleApplicationEvent event = new MuleApplicationEvent("MuleEvent from a spring bean",
259 "vm://testBean2?transformers=dummyTransformer");
260
261 TestSubscriptionEventBean bean2 = (TestSubscriptionEventBean) muleContext.getRegistry().lookupObject(
262 "testSubscribingEventBean2");
263 assertNotNull(bean2);
264
265 Latch whenFinished = new Latch();
266 bean2.setEventCallback(new CountingEventCallback(eventCounter1, 1, whenFinished));
267
268
269 this.doPublish(event, 1);
270
271 whenFinished.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
272 assertTrue(transformerLatch.await(DEFAULT_LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
273 assertEquals(1, eventCounter1.get());
274 }
275
276
277 protected void doPublish(final ApplicationEvent event, final int count)
278 {
279 Runnable publisher = new Runnable()
280 {
281 public void run()
282 {
283 for (int i = 0; i < count; i++)
284 {
285 ApplicationContext context = null;
286 try
287 {
288 context = ((MuleEventMulticaster) muleContext.getRegistry().lookupObject(
289 "applicationEventMulticaster")).applicationContext;
290 context.publishEvent(event);
291 }
292 catch (IllegalArgumentException e)
293 {
294
295 e.printStackTrace();
296 }
297 catch (SecurityException e)
298 {
299
300 e.printStackTrace();
301 }
302 }
303 }
304 };
305
306 Executors.newSingleThreadExecutor().execute(publisher);
307 }
308
309
310 protected void doSend(final String url, final Object payload, final int count)
311 {
312 Runnable sender = new Runnable()
313 {
314 public void run()
315 {
316 try
317 {
318 MuleClient client = new MuleClient(muleContext);
319 for (int i = 0; i < count; i++)
320 {
321 client.send(url, payload, null);
322 }
323 }
324 catch (MuleException ex)
325 {
326 fail(ExceptionUtils.getStackTrace(ex));
327 }
328 }
329 };
330
331
332 Executors.newSingleThreadExecutor().execute(sender);
333 }
334
335
336
337
338
339
340
341 public static class CountingEventCallback implements EventCallback
342 {
343 private final AtomicInteger counter;
344 private final int maxCount;
345 private final CountDownLatch finished;
346
347 public CountingEventCallback(AtomicInteger counter, int maxCount, CountDownLatch whenFinished)
348 {
349 super();
350 this.counter = counter;
351 this.maxCount = maxCount;
352 this.finished = whenFinished;
353 }
354
355 public void eventReceived(MuleEventContext context, Object o) throws Exception
356 {
357
358
359
360 if (!(o instanceof ContextRefreshedEvent))
361 {
362 if (counter.incrementAndGet() == maxCount && finished != null)
363 {
364 finished.countDown();
365 }
366 }
367 }
368 }
369
370
371
372
373
374 public static class TestEventAwareTransformer extends AbstractMessageTransformer
375 {
376 private CountDownLatch latch;
377
378 public TestEventAwareTransformer()
379 {
380 this.setName("dummyTransformer");
381 }
382
383 @Override
384 public Object clone() throws CloneNotSupportedException
385 {
386 TestEventAwareTransformer clone = (TestEventAwareTransformer) super.clone();
387
388
389
390 clone.setLatch(latch);
391 return clone;
392 }
393
394 public CountDownLatch getLatch()
395 {
396 return latch;
397 }
398
399 public void setLatch(CountDownLatch latch)
400 {
401 this.latch = latch;
402 }
403
404 @Override
405 public Object transformMessage(MuleMessage message, String outputEncoding)
406 {
407 assertNotNull(message);
408
409 if (latch != null)
410 {
411 latch.countDown();
412 }
413
414 return message;
415 }
416 }
417
418
419
420
421 public static class TestApplicationEvent extends ApplicationEvent
422 {
423 private static final long serialVersionUID = 1L;
424
425 public TestApplicationEvent(Object source)
426 {
427 super(source);
428 }
429 }
430
431 }