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