1
2
3
4
5
6
7
8
9
10
11 package org.mule.processor;
12
13 import org.mule.DefaultMuleEvent;
14 import org.mule.api.MessagingException;
15 import org.mule.api.MuleEvent;
16 import org.mule.api.MuleException;
17 import org.mule.api.MuleRuntimeException;
18 import org.mule.api.config.ThreadingProfile;
19 import org.mule.api.context.WorkManager;
20 import org.mule.api.context.WorkManagerSource;
21 import org.mule.api.endpoint.OutboundEndpoint;
22 import org.mule.api.lifecycle.Startable;
23 import org.mule.api.lifecycle.Stoppable;
24 import org.mule.api.processor.MessageProcessor;
25 import org.mule.config.i18n.CoreMessages;
26 import org.mule.interceptor.ProcessingTimeInterceptor;
27 import org.mule.work.AbstractMuleEventWork;
28 import org.mule.work.MuleWorkManager;
29
30 import javax.resource.spi.work.WorkEvent;
31 import javax.resource.spi.work.WorkListener;
32
33
34
35
36
37
38
39
40 public class AsyncInterceptingMessageProcessor extends AbstractInterceptingMessageProcessor
41 implements WorkListener, Startable, Stoppable
42 {
43 protected WorkManagerSource workManagerSource;
44 protected boolean doThreading = true;
45 protected WorkManager workManager;
46
47 public AsyncInterceptingMessageProcessor(WorkManagerSource workManagerSource)
48 {
49 this.workManagerSource = workManagerSource;
50 }
51
52 @Deprecated
53 public AsyncInterceptingMessageProcessor(WorkManagerSource workManagerSource, boolean doThreading)
54 {
55 this.workManagerSource = workManagerSource;
56 this.doThreading = doThreading;
57 }
58
59 public AsyncInterceptingMessageProcessor(ThreadingProfile threadingProfile,
60 String name,
61 int shutdownTimeout)
62 {
63 this.doThreading = threadingProfile.isDoThreading();
64 workManager = threadingProfile.createWorkManager(name, shutdownTimeout);
65 workManagerSource = new WorkManagerSource()
66 {
67 public WorkManager getWorkManager() throws MuleException
68 {
69 return workManager;
70 }
71 };
72 }
73
74 public void start() throws MuleException
75 {
76 if (workManager != null)
77 {
78 workManager.start();
79 }
80 }
81
82 public void stop() throws MuleException
83 {
84 if (workManager != null)
85 {
86 workManager.dispose();
87 }
88 }
89
90 public MuleEvent process(MuleEvent event) throws MuleException
91 {
92 if (next == null)
93 {
94 return event;
95 }
96 else if (isProcessAsync(event))
97 {
98 processNextAsync(event);
99 return null;
100 }
101 else
102 {
103 MuleEvent response = processNext(event);
104 return response;
105 }
106 }
107
108 protected MuleEvent processNextTimed(MuleEvent event) throws MuleException
109 {
110 if (next == null)
111 {
112 return event;
113 }
114 else
115 {
116 if (logger.isTraceEnabled())
117 {
118 logger.trace("Invoking next MessageProcessor: '" + next.getClass().getName() + "' ");
119 }
120
121 if (next instanceof OutboundEndpoint)
122 {
123 event = new DefaultMuleEvent(event.getMessage(), (OutboundEndpoint) next, event.getSession());
124 }
125
126 MuleEvent response;
127 if (event.getFlowConstruct() != null)
128 {
129 response = new ProcessingTimeInterceptor(next, event.getFlowConstruct()).process(event);
130 }
131 else
132 {
133 response = next.process(event);
134 }
135 return response;
136 }
137 }
138
139 protected boolean isProcessAsync(MuleEvent event) throws MessagingException
140 {
141
142 if (event.getEndpoint().getTransactionConfig().isTransacted())
143 {
144 throw new MessagingException(CoreMessages.asyncDoesNotSupportTransactions(), event);
145 }
146 return doThreading;
147 }
148
149 protected void processNextAsync(MuleEvent event) throws MuleException
150 {
151 try
152 {
153 workManagerSource.getWorkManager().scheduleWork(new AsyncMessageProcessorWorker(event),
154 WorkManager.INDEFINITE, null, this);
155 }
156 catch (Exception e)
157 {
158 new MessagingException(CoreMessages.errorSchedulingMessageProcessorForAsyncInvocation(next),
159 event, e);
160 }
161 }
162
163 public void workAccepted(WorkEvent event)
164 {
165 this.handleWorkException(event, "workAccepted");
166 }
167
168 public void workRejected(WorkEvent event)
169 {
170 this.handleWorkException(event, "workRejected");
171 }
172
173 public void workStarted(WorkEvent event)
174 {
175 this.handleWorkException(event, "workStarted");
176 }
177
178 public void workCompleted(WorkEvent event)
179 {
180 this.handleWorkException(event, "workCompleted");
181 }
182
183 protected void handleWorkException(WorkEvent event, String type)
184 {
185 if (event == null)
186 {
187 return;
188 }
189
190 Throwable e = event.getException();
191
192 if (e == null)
193 {
194 return;
195 }
196
197 if (e.getCause() != null)
198 {
199 e = e.getCause();
200 }
201
202 logger.error("Work caused exception on '" + type + "'. Work being executed was: "
203 + event.getWork().toString());
204 throw new MuleRuntimeException(CoreMessages.errorInvokingMessageProcessorAsynchronously(next), e);
205 }
206
207 class AsyncMessageProcessorWorker extends AbstractMuleEventWork
208 {
209 public AsyncMessageProcessorWorker(MuleEvent event)
210 {
211 super(event);
212 }
213
214 @Override
215 protected void doRun()
216 {
217 try
218 {
219 processNextTimed(event);
220 }
221 catch (MuleException e)
222 {
223 event.getFlowConstruct().getExceptionListener().handleException(e, event);
224 }
225 }
226 }
227
228 }