View Javadoc

1   /*
2    * $Id$
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;
12  
13  import org.mule.api.MessagingException;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.MuleException;
16  import org.mule.api.MuleRuntimeException;
17  import org.mule.api.config.ThreadingProfile;
18  import org.mule.api.context.WorkManager;
19  import org.mule.api.context.WorkManagerSource;
20  import org.mule.api.lifecycle.Startable;
21  import org.mule.api.lifecycle.Stoppable;
22  import org.mule.api.processor.MessageProcessor;
23  import org.mule.config.i18n.CoreMessages;
24  import org.mule.work.AbstractMuleEventWork;
25  import org.mule.work.MuleWorkManager;
26  
27  import javax.resource.spi.work.WorkEvent;
28  import javax.resource.spi.work.WorkListener;
29  
30  /**
31   * Processes {@link MuleEvent}'s asynchronously using a {@link MuleWorkManager} to
32   * schedule asynchronous processing of the next {@link MessageProcessor}. The next
33   * {@link MessageProcessor} is therefore be executed in a different thread regardless
34   * of the exchange-pattern configured on the inbound endpoint. If a transaction is
35   * present then an exception is thrown.
36   */
37  public class AsyncInterceptingMessageProcessor extends AbstractInterceptingMessageProcessor
38      implements WorkListener, Startable, Stoppable
39  {
40      protected WorkManagerSource workManagerSource;
41      protected boolean doThreading = true;
42      protected WorkManager workManager;
43  
44      public AsyncInterceptingMessageProcessor(WorkManagerSource workManagerSource)
45      {
46          this.workManagerSource = workManagerSource;
47      }
48  
49      @Deprecated
50      public AsyncInterceptingMessageProcessor(WorkManagerSource workManagerSource, boolean doThreading)
51      {
52          this.workManagerSource = workManagerSource;
53          this.doThreading = doThreading;
54      }
55  
56      public AsyncInterceptingMessageProcessor(ThreadingProfile threadingProfile,
57                                               String name,
58                                               int shutdownTimeout)
59      {
60          this.doThreading = threadingProfile.isDoThreading();
61          workManager = threadingProfile.createWorkManager(name, shutdownTimeout);
62          workManagerSource = new WorkManagerSource()
63          {
64              public WorkManager getWorkManager() throws MuleException
65              {
66                  return workManager;
67              }
68          };
69      }
70  
71      public void start() throws MuleException
72      {
73          if (workManager != null)
74          {
75              workManager.start();
76          }
77      }
78  
79      public void stop() throws MuleException
80      {
81          if (workManager != null)
82          {
83              workManager.dispose();
84          }
85      }
86  
87      public MuleEvent process(MuleEvent event) throws MuleException
88      {
89          if (next == null)
90          {
91              return event;
92          }
93          else if (isProcessAsync(event))
94          {
95              processNextAsync(event);
96              return null;
97          }
98          else
99          {
100             return processNext(event);
101         }
102     }
103 
104     protected boolean isProcessAsync(MuleEvent event) throws MessagingException
105     {
106         // We do not support transactions and async
107         if (event.getEndpoint().getTransactionConfig().isTransacted())
108         {
109             throw new MessagingException(CoreMessages.asyncDoesNotSupportTransactions(), event);
110         }
111         return doThreading;
112     }
113 
114     protected void processNextAsync(MuleEvent event) throws MuleException
115     {
116         try
117         {
118             workManagerSource.getWorkManager().scheduleWork(new AsyncMessageProcessorWorker(event),
119                 WorkManager.INDEFINITE, null, this);
120         }
121         catch (Exception e)
122         {
123             new MessagingException(CoreMessages.errorSchedulingMessageProcessorForAsyncInvocation(next),
124                 event, e);
125         }
126     }
127 
128     public void workAccepted(WorkEvent event)
129     {
130         this.handleWorkException(event, "workAccepted");
131     }
132 
133     public void workRejected(WorkEvent event)
134     {
135         this.handleWorkException(event, "workRejected");
136     }
137 
138     public void workStarted(WorkEvent event)
139     {
140         this.handleWorkException(event, "workStarted");
141     }
142 
143     public void workCompleted(WorkEvent event)
144     {
145         this.handleWorkException(event, "workCompleted");
146     }
147 
148     protected void handleWorkException(WorkEvent event, String type)
149     {
150         if (event == null)
151         {
152             return;
153         }
154 
155         Throwable e = event.getException();
156 
157         if (e == null)
158         {
159             return;
160         }
161 
162         if (e.getCause() != null)
163         {
164             e = e.getCause();
165         }
166 
167         logger.error("Work caused exception on '" + type + "'. Work being executed was: "
168                      + event.getWork().toString());
169         throw new MuleRuntimeException(CoreMessages.errorInvokingMessageProcessorAsynchronously(next), e);
170     }
171 
172     class AsyncMessageProcessorWorker extends AbstractMuleEventWork
173     {
174         public AsyncMessageProcessorWorker(MuleEvent event)
175         {
176             super(event);
177         }
178 
179         @Override
180         protected void doRun()
181         {
182             try
183             {
184                 processNext(event);
185             }
186             catch (MuleException e)
187             {
188                 event.getFlowConstruct().getExceptionListener().handleException(e, event);
189             }
190         }
191     }
192 
193 }