View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.work;
8   
9   import org.mule.DefaultMuleMessage;
10  import org.mule.OptimizedRequestContext;
11  import org.mule.RequestContext;
12  import org.mule.api.MuleEvent;
13  import org.mule.api.ThreadSafeAccess;
14  import org.mule.tck.junit4.AbstractMuleContextTestCase;
15  import org.mule.util.concurrent.Latch;
16  
17  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
18  import org.junit.Test;
19  
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertNotSame;
22  import static org.junit.Assert.assertSame;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  /**
27   * Test case to reproduce issue described in MULE-4407 and validate fix.
28   */
29  public class MuleEventWorkTestCase extends AbstractMuleContextTestCase
30  {
31  
32      protected MuleEvent originalEvent;
33      protected Latch latch = new Latch();
34  
35      @Override
36      protected void doSetUp() throws Exception
37      {
38          super.doSetUp();
39          // Create a dummy event and give it some properties
40          originalEvent = getTestEvent("test");
41          originalEvent.getMessage().setOutboundProperty("test", "val");
42          originalEvent.getMessage().setOutboundProperty("test2", "val2");
43          OptimizedRequestContext.unsafeSetEvent(originalEvent);
44      }
45  
46      @Test
47      public void testScheduleMuleEventWork() throws Exception
48      {
49          muleContext.getWorkManager().scheduleWork(new TestMuleEventWork(originalEvent));
50  
51          assertTrue("Timed out waiting for latch", latch.await(2000, TimeUnit.MILLISECONDS));
52  
53          assertSame(originalEvent, RequestContext.getEvent());
54  
55          try
56          {
57              // Ensure that even after Work has been created, scheduled and executed
58              // the original event instance is still owned by this thread and still
59              // mutable.
60              ((DefaultMuleMessage) originalEvent.getMessage()).assertAccess(ThreadSafeAccess.WRITE);
61          }
62          catch (Exception e)
63          {
64              fail(e.getMessage());
65          }
66      }
67  
68      @Test
69      public void testRunMuleEventWork() throws Exception
70      {
71          new TestMuleEventWork(originalEvent).run();
72  
73          // NOTE: This assertion documents/tests current behaviour but does not seem
74          // correct.
75          // In scenarios where Work implementations are run in the same thread rather
76          // than being scheduled then the RequestContext ThreadLocal value is
77          // overwritten with a new copy which is not desirable.
78          // See: MULE-4409
79          assertNotSame(originalEvent, RequestContext.getEvent());
80  
81          try
82          {
83              // Ensure that even after Work has been created, scheduled and executed
84              // the original event instance is still owned by this thread and still
85              // mutable.
86              ((DefaultMuleMessage) originalEvent.getMessage()).assertAccess(ThreadSafeAccess.WRITE);
87          }
88          catch (Exception e)
89          {
90              fail(e.getMessage());
91          }
92  
93      }
94  
95      private class TestMuleEventWork extends AbstractMuleEventWork
96      {
97  
98          public TestMuleEventWork(MuleEvent event)
99          {
100             super(event);
101         }
102 
103         @Override
104         protected void doRun()
105         {
106             assertNotSame("MuleEvent", event, originalEvent);
107             assertNotNull("RequestContext.getEvent() is null", RequestContext.getEvent());
108 
109             try
110             {
111                 // Ensure that the new event copied for this event is owned by the
112                 // thread that is executing this work and is mutable
113                 ((DefaultMuleMessage) event.getMessage()).assertAccess(ThreadSafeAccess.WRITE);
114             }
115             catch (Exception e)
116             {
117                 fail(e.getMessage());
118             }
119             latch.countDown();
120         }
121     }
122 
123 }