View Javadoc

1   /*
2    * $Id: AsyncInterceptingMessageProcessor.java 23126 2011-10-07 01:06:45Z dfeist $
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.config.ThreadingProfile;
17  import org.mule.api.context.WorkManager;
18  import org.mule.api.context.WorkManagerSource;
19  import org.mule.api.lifecycle.Startable;
20  import org.mule.api.lifecycle.Stoppable;
21  import org.mule.api.processor.MessageProcessor;
22  import org.mule.config.i18n.CoreMessages;
23  import org.mule.interceptor.ProcessingTimeInterceptor;
24  import org.mule.work.AbstractMuleEventWork;
25  import org.mule.work.MuleWorkManager;
26  
27  /**
28   * Processes {@link MuleEvent}'s asynchronously using a {@link MuleWorkManager} to
29   * schedule asynchronous processing of the next {@link MessageProcessor}. The next
30   * {@link MessageProcessor} is therefore be executed in a different thread regardless
31   * of the exchange-pattern configured on the inbound endpoint. If a transaction is
32   * present then an exception is thrown.
33   */
34  public class AsyncInterceptingMessageProcessor extends AbstractInterceptingMessageProcessor
35      implements Startable, Stoppable
36  {
37      protected WorkManagerSource workManagerSource;
38      protected boolean doThreading = true;
39      protected WorkManager workManager;
40  
41      public AsyncInterceptingMessageProcessor(WorkManagerSource workManagerSource)
42      {
43          this.workManagerSource = workManagerSource;
44      }
45  
46      public AsyncInterceptingMessageProcessor(ThreadingProfile threadingProfile,
47                                               String name,
48                                               int shutdownTimeout)
49      {
50          this.doThreading = threadingProfile.isDoThreading();
51          workManager = threadingProfile.createWorkManager(name, shutdownTimeout);
52          workManagerSource = new WorkManagerSource()
53          {
54              public WorkManager getWorkManager() throws MuleException
55              {
56                  return workManager;
57              }
58          };
59      }
60  
61      public void start() throws MuleException
62      {
63          if (workManager != null)
64          {
65              workManager.start();
66          }
67      }
68  
69      public void stop() throws MuleException
70      {
71          if (workManager != null)
72          {
73              workManager.dispose();
74          }
75      }
76  
77      public MuleEvent process(MuleEvent event) throws MuleException
78      {
79          if (next == null)
80          {
81              return event;
82          }
83          else if (isProcessAsync(event))
84          {
85              processNextAsync(event);
86              return null;
87          }
88          else
89          {
90              MuleEvent response = processNext(event);
91              return response;
92          }
93      }
94  
95      protected MuleEvent processNextTimed(MuleEvent event) throws MuleException
96      {
97          if (next == null)
98          {
99              return event;
100         }
101         else
102         {
103             if (logger.isTraceEnabled())
104             {
105                 logger.trace("Invoking next MessageProcessor: '" + next.getClass().getName() + "' ");
106             }
107 
108             MuleEvent response;
109             if (event.getFlowConstruct() != null)
110             {
111                 response = new ProcessingTimeInterceptor(next, event.getFlowConstruct()).process(event);
112             }
113             else
114             {
115                 response = processNext(event);
116             }
117             return response;
118         }
119     }
120 
121     protected boolean isProcessAsync(MuleEvent event) throws MessagingException
122     {
123         if (event.isSynchronous() || event.isTransacted())
124         {
125             throw new MessagingException(
126                 CoreMessages.createStaticMessage("Unable to process a synchonrous event asyncronously"),
127                 event);
128         }
129         return doThreading && !event.isSynchronous();
130     }
131 
132     protected void processNextAsync(MuleEvent event) throws MuleException
133     {
134         try
135         {
136             workManagerSource.getWorkManager().scheduleWork(new AsyncMessageProcessorWorker(event),
137                 WorkManager.INDEFINITE, null, new AsyncWorkListener(next));
138         }
139         catch (Exception e)
140         {
141             new MessagingException(CoreMessages.errorSchedulingMessageProcessorForAsyncInvocation(next),
142                 event, e);
143         }
144     }
145 
146     class AsyncMessageProcessorWorker extends AbstractMuleEventWork
147     {
148         public AsyncMessageProcessorWorker(MuleEvent event)
149         {
150             super(event);
151         }
152 
153         @Override
154         protected void doRun()
155         {
156             try
157             {
158                 processNextTimed(event);
159             }
160             catch (Exception e)
161             {
162                 event.getFlowConstruct().getExceptionListener().handleException(e, event);
163             }
164         }
165     }
166 
167 }