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