View Javadoc

1   /*
2    * $Id: DefaultMessageProcessorChainTestCase.java 22369 2011-07-11 07:53:30Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.processor.chain;
12  
13  import org.mule.DefaultMuleEvent;
14  import org.mule.DefaultMuleMessage;
15  import org.mule.api.MuleEvent;
16  import org.mule.api.MuleException;
17  import org.mule.api.lifecycle.InitialisationException;
18  import org.mule.api.lifecycle.Lifecycle;
19  import org.mule.api.processor.InterceptingMessageProcessor;
20  import org.mule.api.processor.MessageProcessor;
21  import org.mule.api.processor.MessageProcessorBuilder;
22  import org.mule.api.processor.MessageProcessorChain;
23  import org.mule.processor.AbstractInterceptingMessageProcessor;
24  import org.mule.tck.junit4.AbstractMuleContextTestCase;
25  import org.mule.transformer.simple.StringAppendTransformer;
26  import org.mule.util.ObjectUtils;
27  
28  import org.junit.Test;
29  
30  import static org.junit.Assert.assertEquals;
31  import static org.junit.Assert.assertFalse;
32  import static org.junit.Assert.assertNotSame;
33  import static org.junit.Assert.assertNull;
34  import static org.junit.Assert.assertTrue;
35  
36  public class DefaultMessageProcessorChainTestCase extends AbstractMuleContextTestCase
37  {
38  
39      @Test
40      public void testMPChain() throws MuleException, Exception
41      {
42          DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
43          builder.chain(new AppendingMP("1"), new AppendingMP("2"), new AppendingMP("3"));
44          assertEquals("0123", builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
45      }
46  
47      @Test
48      public void testMPChainWithNullReturn() throws MuleException, Exception
49      {
50          DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
51  
52          AppendingMP mp1 = new AppendingMP("1");
53          AppendingMP mp2 = new AppendingMP("2");
54          ReturnNullMP nullmp = new ReturnNullMP();
55          AppendingMP mp3 = new AppendingMP("3");
56  
57          builder.chain(mp1, mp2, nullmp, mp3);
58          assertEquals("0123", builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
59  
60          assertNotSame(mp1.event, mp1.resultEvent);
61          assertEquals(mp1.resultEvent, mp2.event);
62          
63          assertNotSame(mp2.event, mp2.resultEvent);
64          assertEquals(mp2.resultEvent, nullmp.event);
65  
66          assertNotSame(mp3.event, mp3.resultEvent);
67  
68          assertNotSame(nullmp.event, mp3.event);
69          assertEquals(mp3.event.getMessageAsString(), "012");
70  
71      }
72  
73      @Test
74      public void testMPChainWithNullReturnAtEnd() throws MuleException, Exception
75      {
76          DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
77          builder.chain(new AppendingMP("1"), new AppendingMP("2"), new AppendingMP("3"), new ReturnNullMP());
78          assertNull(builder.build().process(getTestEventUsingFlow("0")));
79      }
80  
81      @Test
82      public void testMPChainWithBuilder() throws MuleException, Exception
83      {
84          DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
85          builder.chain(new AppendingMP("1"));
86          builder.chain(new MessageProcessorBuilder()
87          {
88              public MessageProcessor build()
89              {
90                  return new AppendingMP("2");
91              }
92          });
93          builder.chain(new AppendingMP("3"));
94          assertEquals("0123", builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
95      }
96  
97      @Test
98      public void testInterceptingMPChain() throws MuleException, Exception
99      {
100         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
101         builder.chain(new AppendingInterceptingMP("1"), new AppendingInterceptingMP("2"),
102             new AppendingInterceptingMP("3"));
103         assertEquals("0before1before2before3after3after2after1",
104             builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
105     }
106 
107     @Test
108     public void testInterceptingMPChainWithNullReturn() throws MuleException, Exception
109     {
110         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
111         
112         AppendingInterceptingMP lastMP = new AppendingInterceptingMP("3");
113         
114         builder.chain(new AppendingInterceptingMP("1"), new AppendingInterceptingMP("2"),
115             new ReturnNullInterceptongMP(), lastMP);
116         assertNull(builder.build().process(getTestEventUsingFlow("0")));
117         assertFalse(lastMP.invoked);
118     }
119 
120     @Test
121     public void testMixedMPChain() throws MuleException, Exception
122     {
123         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
124         builder.chain(new AppendingInterceptingMP("1"), new AppendingMP("2"), new AppendingMP("3"),
125             new AppendingInterceptingMP("4"), new AppendingMP("5"));
126         assertEquals("0before123before45after4after1", builder.build()
127             .process(getTestEventUsingFlow("0"))
128             .getMessageAsString());
129     }
130 
131     @Test
132     // Whenever there is a IMP that returns null the final result is null
133     public void testMixedMPChainWithNullReturn1() throws MuleException, Exception
134     {
135         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
136         builder.chain(new AppendingInterceptingMP("1"), new ReturnNullInterceptongMP(), new AppendingMP("2"),
137             new AppendingMP("3"), new AppendingInterceptingMP("4"), new AppendingMP("5"));
138         assertNull(builder.build().process(getTestEventUsingFlow("0")));
139     }
140 
141     @Test
142     // Whenever there is a IMP that returns null the final result is null
143     public void testMixedMPChainWithNullReturn2() throws MuleException, Exception
144     {
145         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
146         builder.chain(new AppendingInterceptingMP("1"), new AppendingMP("2"), new ReturnNullInterceptongMP(),
147             new AppendingMP("3"), new AppendingInterceptingMP("4"), new AppendingMP("5"));
148         assertNull(builder.build().process(getTestEventUsingFlow("0")));
149     }
150 
151     @Test
152     // A simple MP that returns null does not affect flow as long as it's not at the
153     // end
154     public void testMixedMPChainWithNullReturn3() throws MuleException, Exception
155     {
156         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
157         builder.chain(new AppendingInterceptingMP("1"), new ReturnNullMP(), new AppendingMP("2"),
158             new AppendingMP("3"), new AppendingInterceptingMP("4"), new AppendingMP("5"));
159         assertEquals("0before123before45after4after1", builder.build()
160             .process(getTestEventUsingFlow("0"))
161             .getMessageAsString());
162     }
163 
164     @Test
165     // A simple MP that returns null does not affect flow as long as it's not at the
166     // end
167     public void testMixedMPChainWithNullReturn4() throws MuleException, Exception
168     {
169         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
170         builder.chain(new AppendingInterceptingMP("1"), new AppendingMP("2"), new ReturnNullMP(),
171             new AppendingMP("3"), new AppendingInterceptingMP("4"), new AppendingMP("5"));
172         assertEquals("0before123before45after4after1", builder.build()
173             .process(getTestEventUsingFlow("0"))
174             .getMessageAsString());
175     }
176 
177     @Test
178     // A simple MP that returns null does not affect flow as long as it's not at the
179     // end
180     public void testMixedMPChainWithNullReturn5() throws MuleException, Exception
181     {
182         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
183         builder.chain(new AppendingInterceptingMP("1"), new AppendingMP("2"), new AppendingMP("3"),
184             new ReturnNullMP(), new AppendingInterceptingMP("4"), new AppendingMP("5"));
185         assertEquals("0before123before45after4after1", builder.build()
186             .process(getTestEventUsingFlow("0"))
187             .getMessageAsString());
188     }
189 
190     @Test
191     // A simple MP at the end of a single level chain causes chain to return null
192     public void testMixedMPChainWithNullReturnAtEnd() throws MuleException, Exception
193     {
194         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
195         builder.chain(new AppendingInterceptingMP("1"), new AppendingMP("2"), new AppendingMP("3"),
196             new AppendingInterceptingMP("4"), new AppendingMP("5"), new ReturnNullMP());
197         assertNull(builder.build().process(getTestEventUsingFlow("0")));
198     }
199 
200     @Test
201     public void testNestedMPChain() throws MuleException, Exception
202     {
203         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
204         builder.chain(new AppendingMP("1"),
205             new DefaultMessageProcessorChainBuilder().chain(new AppendingMP("a"), new AppendingMP("b"))
206                 .build(), new AppendingMP("2"));
207         assertEquals("01ab2", builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
208     }
209 
210     @Test
211     public void testNestedMPChainWithNullReturn() throws MuleException, Exception
212     {
213         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
214         builder.chain(
215             new AppendingMP("1"),
216             new DefaultMessageProcessorChainBuilder().chain(new AppendingMP("a"), new ReturnNullMP(),
217                 new AppendingMP("b")).build(), new ReturnNullMP(), new AppendingMP("2"));
218         assertEquals("01ab2", builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
219     }
220 
221     @Test
222     public void testNestedMPChainWithNullReturnAtEndOfNestedChain() throws MuleException, Exception
223     {
224         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
225         builder.chain(
226             new AppendingMP("1"),
227             new DefaultMessageProcessorChainBuilder().chain(new AppendingMP("a"), new AppendingMP("b"),
228                 new ReturnNullMP()).build(), new AppendingMP("2"));
229         assertNull(builder.build().process(getTestEventUsingFlow("0")));
230     }
231 
232     @Test
233     public void testNestedMPChainWithNullReturnAtEndOfNestedChainWithNonInterceptingWrapper() throws MuleException, Exception
234     {
235         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
236         final MessageProcessor nested = new DefaultMessageProcessorChainBuilder().chain(new AppendingMP("a"),
237             new AppendingMP("b"), new ReturnNullMP()).build();
238         builder.chain(new AppendingMP("1"), new MessageProcessor()
239         {
240             public MuleEvent process(MuleEvent event) throws MuleException
241             {
242                 return nested.process(event);
243             }
244         }, new AppendingMP("2"));
245         assertEquals("012", builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
246     }
247 
248     @Test
249     public void testNestedInterceptingMPChain() throws MuleException, Exception
250     {
251         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
252         builder.chain(
253             new AppendingInterceptingMP("1"),
254             new DefaultMessageProcessorChainBuilder().chain(new AppendingInterceptingMP("a"),
255                 new AppendingInterceptingMP("b")).build(), new AppendingInterceptingMP("2"));
256         assertEquals("0before1beforeabeforebafterbafterabefore2after2after1",
257             builder.build().process(getTestEventUsingFlow("0")).getMessageAsString());
258     }
259 
260     @Test
261     public void testNestedInterceptingMPChainWithNullReturn() throws MuleException, Exception
262     {
263         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
264         builder.chain(
265             new AppendingInterceptingMP("1"),
266             new DefaultMessageProcessorChainBuilder().chain(new AppendingInterceptingMP("a"),
267                 new ReturnNullInterceptongMP(), new AppendingInterceptingMP("b")).build(),
268             new AppendingInterceptingMP("2"));
269         assertNull(builder.build().process(getTestEventUsingFlow("0")));
270     }
271 
272     @Test
273     public void testNestedMixedMPChain() throws MuleException, Exception
274     {
275         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
276         builder.chain(
277             new AppendingMP("1"),
278             new DefaultMessageProcessorChainBuilder().chain(new AppendingInterceptingMP("a"),
279                 new AppendingMP("b")).build(), new AppendingInterceptingMP("2"));
280         assertEquals("01beforeabafterabefore2after2", builder.build()
281             .process(getTestEventUsingFlow("0"))
282             .getMessageAsString());
283     }
284 
285     @Test
286     public void testInterceptingMPChainStopFlow() throws MuleException, Exception
287     {
288         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
289         builder.chain(new AppendingInterceptingMP("1"), new AppendingInterceptingMP("2", true),
290             new AppendingInterceptingMP("3"));
291         assertEquals("0before1after1", builder.build()
292             .process(getTestEventUsingFlow("0"))
293             .getMessageAsString());
294     }
295 
296     /**
297      * Note: Stopping the flow of a nested chain causes the nested chain to return early, but does not stop
298      * the flow of the parent chain.
299      */
300     @Test
301     public void testNestedInterceptingMPChainStopFlow() throws MuleException, Exception
302     {
303         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
304         builder.chain(
305             new AppendingInterceptingMP("1"),
306             new DefaultMessageProcessorChainBuilder().chain(new AppendingInterceptingMP("a", true),
307                 new AppendingInterceptingMP("b")).build(), new AppendingInterceptingMP("3"));
308         assertEquals("0before1before3after3after1", builder.build()
309             .process(getTestEventUsingFlow("0"))
310             .getMessageAsString());
311     }
312 
313     @Test
314     public void testMPChainLifecycle() throws MuleException, Exception
315     {
316         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
317         AppendingMP mp1 = new AppendingInterceptingMP("1");
318         AppendingMP mp2 = new AppendingInterceptingMP("2");
319         MessageProcessor chain = builder.chain(mp1, mp2).build();
320         ((Lifecycle) chain).initialise();
321         ((Lifecycle) chain).start();
322         ((Lifecycle) chain).stop();
323         ((Lifecycle) chain).dispose();
324         assertLifecycle(mp1);
325         assertLifecycle(mp2);
326     }
327 
328     @Test
329     public void testNestedMPChainLifecycle() throws MuleException, Exception
330     {
331         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
332         DefaultMessageProcessorChainBuilder nestedBuilder = new DefaultMessageProcessorChainBuilder();
333         AppendingMP mp1 = new AppendingInterceptingMP("1");
334         AppendingMP mp2 = new AppendingInterceptingMP("2");
335         AppendingMP mpa = new AppendingInterceptingMP("a");
336         AppendingMP mpb = new AppendingInterceptingMP("b");
337         MessageProcessor chain = builder.chain(mp1, nestedBuilder.chain(mpa, mpb).build(), mp2).build();
338         ((Lifecycle) chain).initialise();
339         ((Lifecycle) chain).start();
340         ((Lifecycle) chain).stop();
341         ((Lifecycle) chain).dispose();
342         assertLifecycle(mp1);
343         assertLifecycle(mp2);
344         assertLifecycle(mpa);
345         assertLifecycle(mpb);
346     }
347 
348     @Test
349     public void testNoneIntercepting() throws Exception
350     {
351         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
352         builder.chain(new TestNonIntercepting(), new TestNonIntercepting(), new TestNonIntercepting());
353         MuleEvent restul = builder.build().process(getTestEventUsingFlow(""));
354         assertEquals("MessageProcessorMessageProcessorMessageProcessor", restul.getMessageAsString());
355     }
356 
357     @Test
358     public void testAllIntercepting() throws Exception
359     {
360         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
361         builder.chain(new TestIntercepting(), new TestIntercepting(), new TestIntercepting());
362         MuleEvent restul = builder.build().process(getTestEventUsingFlow(""));
363         assertEquals("InterceptingMessageProcessorInterceptingMessageProcessorInterceptingMessageProcessor",
364             restul.getMessageAsString());
365     }
366 
367     @Test
368     public void testMix() throws Exception
369     {
370         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
371         builder.chain(new TestIntercepting(), new TestNonIntercepting(), new TestNonIntercepting(),
372             new TestIntercepting(), new TestNonIntercepting(), new TestNonIntercepting());
373         MuleEvent restul = builder.build().process(getTestEventUsingFlow(""));
374         assertEquals(
375             "InterceptingMessageProcessorMessageProcessorMessageProcessorInterceptingMessageProcessorMessageProcessorMessageProcessor",
376             restul.getMessageAsString());
377     }
378 
379     @Test
380     public void testMixStaticFactoryt() throws Exception
381     {
382         MessageProcessorChain chain = DefaultMessageProcessorChain.from(new TestIntercepting(),
383             new TestNonIntercepting(), new TestNonIntercepting(), new TestIntercepting(),
384             new TestNonIntercepting(), new TestNonIntercepting());
385         MuleEvent restul = chain.process(getTestEventUsingFlow(""));
386         assertEquals(
387             "InterceptingMessageProcessorMessageProcessorMessageProcessorInterceptingMessageProcessorMessageProcessorMessageProcessor",
388             restul.getMessageAsString());
389     }
390 
391     @Test
392     public void testMix2() throws Exception
393     {
394         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
395         builder.chain(new TestNonIntercepting(), new TestIntercepting(), new TestNonIntercepting(),
396             new TestNonIntercepting(), new TestNonIntercepting(), new TestIntercepting());
397         MuleEvent restul = builder.build().process(getTestEventUsingFlow(""));
398         assertEquals(
399             "MessageProcessorInterceptingMessageProcessorMessageProcessorMessageProcessorMessageProcessorInterceptingMessageProcessor",
400             restul.getMessageAsString());
401     }
402 
403     @Test
404     public void testMix2StaticFactory() throws Exception
405     {
406         MessageProcessorChain chain = DefaultMessageProcessorChain.from(new TestNonIntercepting(),
407             new TestIntercepting(), new TestNonIntercepting(), new TestNonIntercepting(),
408             new TestNonIntercepting(), new TestIntercepting());
409         MuleEvent restul = chain.process(getTestEventUsingFlow(""));
410         assertEquals(
411             "MessageProcessorInterceptingMessageProcessorMessageProcessorMessageProcessorMessageProcessorInterceptingMessageProcessor",
412             restul.getMessageAsString());
413     }
414 
415     static class TestNonIntercepting implements MessageProcessor
416     {
417         public MuleEvent process(MuleEvent event) throws MuleException
418         {
419             return new StringAppendTransformer("MessageProcessor").process(event);
420         }
421     }
422 
423     static class TestIntercepting extends AbstractInterceptingMessageProcessor
424     {
425         public MuleEvent process(MuleEvent event) throws MuleException
426         {
427             return processNext(new StringAppendTransformer("InterceptingMessageProcessor").process(event));
428         }
429     }
430 
431     private void assertLifecycle(AppendingMP mp)
432     {
433         assertTrue(mp.initialised);
434         assertTrue(mp.started);
435         assertTrue(mp.stopped);
436         assertTrue(mp.disposed);
437     }
438 
439     private static class AppendingMP implements MessageProcessor, Lifecycle
440     {
441         String appendString;
442         boolean initialised;
443         boolean started;
444         boolean stopped;
445         boolean disposed;
446         MuleEvent event;
447         MuleEvent resultEvent;
448 
449         public AppendingMP(String append)
450         {
451             this.appendString = append;
452         }
453 
454         public MuleEvent process(MuleEvent event) throws MuleException
455         {
456             this.event = event;
457             MuleEvent result = new DefaultMuleEvent(new DefaultMuleMessage(event.getMessageAsString() + appendString,
458                 muleContext), event);
459             this.resultEvent = result;
460             return result;
461         }
462 
463         public void initialise() throws InitialisationException
464         {
465             initialised = true;
466         }
467 
468         public void start() throws MuleException
469         {
470             started = true;
471         }
472 
473         public void stop() throws MuleException
474         {
475             stopped = true;
476         }
477 
478         public void dispose()
479         {
480             disposed = true;
481         }
482 
483         @Override
484         public String toString()
485         {
486             return ObjectUtils.toString(this);
487         }
488     }
489 
490     private static class AppendingInterceptingMP extends AppendingMP implements InterceptingMessageProcessor
491     {
492         private boolean stopProcessing;
493         private MessageProcessor next;
494         boolean invoked = false;
495 
496         public AppendingInterceptingMP(String append)
497         {
498             this(append, false);
499         }
500 
501         public AppendingInterceptingMP(String append, boolean stopProcessing)
502         {
503             super(append);
504             this.stopProcessing = stopProcessing;
505         }
506 
507         public MuleEvent process(MuleEvent event) throws MuleException
508         {
509             invoked = true;
510             this.event = event;
511 
512             if (stopProcessing)
513             {
514                 return event;
515             }
516 
517             MuleEvent intermediateEvent = new DefaultMuleEvent(new DefaultMuleMessage(
518                 event.getMessageAsString() + "before" + appendString, muleContext), event);
519             if (next != null)
520             {
521                 intermediateEvent = next.process(intermediateEvent);
522             }
523             if (intermediateEvent != null)
524             {
525                 return new DefaultMuleEvent(new DefaultMuleMessage(intermediateEvent.getMessageAsString()
526                                                                    + "after" + appendString, muleContext),
527                     intermediateEvent);
528             }
529             else
530             {
531                 return null;
532             }
533         }
534 
535         public void setListener(MessageProcessor mp)
536         {
537             next = mp;
538         }
539 
540         @Override
541         public String toString()
542         {
543             return ObjectUtils.toString(this);
544         }
545     }
546 
547     private static class ReturnNullMP implements MessageProcessor
548     {
549         MuleEvent event;
550 
551         public MuleEvent process(MuleEvent event) throws MuleException
552         {
553             this.event = event;
554             event.getMessage().setPayload("RUBBISH");
555             return null;
556         }
557     }
558 
559     private static class ReturnNullInterceptongMP extends AbstractInterceptingMessageProcessor
560     {
561         public MuleEvent process(MuleEvent event) throws MuleException
562         {
563             return null;
564         }
565     }
566 
567 }