1
2
3
4
5
6
7
8
9
10
11 package org.mule.routing.outbound;
12
13 import org.mule.api.MuleException;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.MuleSession;
16 import org.mule.api.config.MuleProperties;
17 import org.mule.api.endpoint.ImmutableEndpoint;
18 import org.mule.api.endpoint.InvalidEndpointTypeException;
19 import org.mule.api.endpoint.OutboundEndpoint;
20 import org.mule.api.routing.MessageInfoMapping;
21 import org.mule.api.routing.OutboundRouter;
22 import org.mule.api.routing.RoutingException;
23 import org.mule.api.transaction.TransactionCallback;
24 import org.mule.api.transaction.TransactionConfig;
25 import org.mule.config.i18n.CoreMessages;
26 import org.mule.routing.AbstractRouter;
27 import org.mule.routing.MuleMessageInfoMapping;
28 import org.mule.transaction.TransactionTemplate;
29 import org.mule.util.StringMessageUtils;
30 import org.mule.util.SystemUtils;
31
32 import java.util.Iterator;
33 import java.util.List;
34
35 import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40
41
42
43
44
45 public abstract class AbstractOutboundRouter extends AbstractRouter implements OutboundRouter
46 {
47 public static final int ENABLE_CORRELATION_IF_NOT_SET = 0;
48 public static final int ENABLE_CORRELATION_ALWAYS = 1;
49 public static final int ENABLE_CORRELATION_NEVER = 2;
50
51
52
53 protected transient Log logger = LogFactory.getLog(getClass());
54
55 protected List endpoints = new CopyOnWriteArrayList();
56
57 protected String replyTo = null;
58
59 protected int enableCorrelation = ENABLE_CORRELATION_IF_NOT_SET;
60
61 protected MessageInfoMapping messageInfoMapping = new MuleMessageInfoMapping();
62
63 protected TransactionConfig transactionConfig;
64
65 public void dispatch(final MuleSession session, final MuleMessage message, final OutboundEndpoint endpoint) throws MuleException
66 {
67 setMessageProperties(session, message, endpoint);
68
69 if (logger.isDebugEnabled())
70 {
71 try
72 {
73 logger.debug("Message being sent to: " + endpoint.getEndpointURI() + " Message payload: \n"
74 + StringMessageUtils.truncate(message.getPayloadAsString(), 100, false)
75 + "\n outbound transformer is: " + endpoint.getTransformers());
76 }
77 catch (Exception e)
78 {
79 logger.debug("Message being sent to: " + endpoint.getEndpointURI()
80 + " Message payload: \n(unable to retrieve payload: " + e.getMessage()
81 + "\n outbound transformer is: " + endpoint.getTransformers());
82 }
83 }
84
85 TransactionTemplate tt = createTransactionTemplate(session, endpoint);
86 TransactionCallback cb = new TransactionCallback()
87 {
88 public Object doInTransaction() throws Exception
89 {
90 session.dispatchEvent(message, endpoint);
91 return null;
92 }
93 };
94
95 try
96 {
97 tt.execute(cb);
98 }
99 catch (Exception e)
100 {
101 throw new RoutingException(message, null, e);
102 }
103
104
105 if (getRouterStatistics() != null)
106 {
107 if (getRouterStatistics().isEnabled())
108 {
109 getRouterStatistics().incrementRoutedMessage(endpoint);
110 }
111 }
112 }
113
114 public MuleMessage send(final MuleSession session, final MuleMessage message, final OutboundEndpoint endpoint) throws MuleException
115 {
116 if (replyTo != null)
117 {
118 logger.debug("event was dispatched synchronously, but there is a ReplyTo endpoint set, so using asynchronous dispatch");
119 dispatch(session, message, endpoint);
120 return null;
121 }
122
123 this.setMessageProperties(session, message, endpoint);
124
125 if (logger.isDebugEnabled())
126 {
127 logger.debug("Message being sent to: " + endpoint.getEndpointURI());
128 logger.debug(message);
129 }
130
131 if (logger.isTraceEnabled())
132 {
133 try
134 {
135 logger.trace("Message payload: \n" + message.getPayloadAsString());
136 }
137 catch (Exception e)
138 {
139
140 }
141 }
142
143 TransactionTemplate tt = createTransactionTemplate(session, endpoint);
144 TransactionCallback cb = new TransactionCallback()
145 {
146 public Object doInTransaction() throws Exception
147 {
148 return session.sendEvent(message, endpoint);
149 }
150 };
151
152 MuleMessage result;
153 try
154 {
155 result = (MuleMessage) tt.execute(cb);
156 }
157 catch (Exception e)
158 {
159 throw new RoutingException(message, null, e);
160 }
161
162 if (getRouterStatistics() != null)
163 {
164 if (getRouterStatistics().isEnabled())
165 {
166 getRouterStatistics().incrementRoutedMessage(endpoint);
167 }
168 }
169
170 if (logger.isDebugEnabled())
171 {
172 logger.debug("Response message from sending to: " + endpoint.getEndpointURI());
173 logger.debug(result);
174 }
175
176 if (logger.isTraceEnabled())
177 {
178 try
179 {
180 logger.trace("Message payload: \n" + result.getPayloadAsString());
181 }
182 catch (Exception e)
183 {
184
185 }
186 }
187
188 return result;
189 }
190
191 protected TransactionTemplate createTransactionTemplate(MuleSession session, ImmutableEndpoint endpoint)
192 {
193 return new TransactionTemplate(endpoint.getTransactionConfig(),
194 session.getService().getExceptionListener(), muleContext);
195 }
196
197 protected void setMessageProperties(MuleSession session, MuleMessage message, OutboundEndpoint endpoint)
198 {
199 if (replyTo != null)
200 {
201
202
203 message.setReplyTo(replyTo);
204 message.setProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY, session.getService().getName());
205 if (logger.isDebugEnabled())
206 {
207 logger.debug("Setting replyTo=" + replyTo + " for outbound endpoint: "
208 + endpoint.getEndpointURI());
209 }
210 }
211 if (enableCorrelation != ENABLE_CORRELATION_NEVER)
212 {
213 boolean correlationSet = message.getCorrelationId() != null;
214 if (correlationSet && (enableCorrelation == ENABLE_CORRELATION_IF_NOT_SET))
215 {
216 if (logger.isDebugEnabled())
217 {
218 logger.debug("CorrelationId is already set to '" + message.getCorrelationId()
219 + "' , not setting it again");
220 }
221 return;
222 }
223 else if (correlationSet)
224 {
225 if (logger.isDebugEnabled())
226 {
227 logger.debug("CorrelationId is already set to '" + message.getCorrelationId()
228 + "', but router is configured to overwrite it");
229 }
230 }
231 else
232 {
233 if (logger.isDebugEnabled())
234 {
235 logger.debug("No CorrelationId is set on the message, will set a new Id");
236 }
237 }
238
239 String correlation;
240 correlation = messageInfoMapping.getCorrelationId(message);
241 if (logger.isDebugEnabled())
242 {
243 logger.debug("Extracted correlation Id as: " + correlation);
244 }
245
246 if (logger.isDebugEnabled())
247 {
248 StringBuffer buf = new StringBuffer();
249 buf.append("Setting Correlation info on Outbound router for endpoint: ").append(
250 endpoint.getEndpointURI());
251 buf.append(SystemUtils.LINE_SEPARATOR).append("Id=").append(correlation);
252
253
254 logger.debug(buf.toString());
255 }
256 message.setCorrelationId(correlation);
257
258
259 }
260 }
261
262 public List getEndpoints()
263 {
264 return endpoints;
265 }
266
267 public void setEndpoints(List endpoints)
268 {
269 this.endpoints.clear();
270
271
272
273 for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
274 {
275 ImmutableEndpoint umoEndpoint = (ImmutableEndpoint) iterator.next();
276 if (!(umoEndpoint instanceof OutboundEndpoint))
277 {
278 throw new InvalidEndpointTypeException(CoreMessages.outboundRouterMustUseOutboudEndpoints(
279 this, umoEndpoint));
280 }
281 else
282 {
283 addEndpoint((OutboundEndpoint) umoEndpoint);
284 }
285 }
286 }
287
288 public void addEndpoint(OutboundEndpoint endpoint)
289 {
290 endpoints.add(endpoint);
291 }
292
293 public boolean removeEndpoint(OutboundEndpoint endpoint)
294 {
295 return endpoints.remove(endpoint);
296 }
297
298 public String getReplyTo()
299 {
300 return replyTo;
301 }
302
303 public void setReplyTo(String replyTo)
304 {
305 this.replyTo = replyTo;
306 }
307
308 public int getEnableCorrelation()
309 {
310 return enableCorrelation;
311 }
312
313 public void setEnableCorrelation(int enableCorrelation)
314 {
315 this.enableCorrelation = enableCorrelation;
316 }
317
318 public void setEnableCorrelationAsString(String enableCorrelation)
319 {
320 if (enableCorrelation != null)
321 {
322 if (enableCorrelation.equals("ALWAYS"))
323 {
324 this.enableCorrelation = ENABLE_CORRELATION_ALWAYS;
325 }
326 else if (enableCorrelation.equals("NEVER"))
327 {
328 this.enableCorrelation = ENABLE_CORRELATION_NEVER;
329 }
330 else if (enableCorrelation.equals("IF_NOT_SET"))
331 {
332 this.enableCorrelation = ENABLE_CORRELATION_IF_NOT_SET;
333 }
334 else
335 {
336 throw new IllegalArgumentException("Value for enableCorrelation not recognised: "
337 + enableCorrelation);
338 }
339 }
340 }
341
342 public MessageInfoMapping getMessageInfoMapping()
343 {
344 return messageInfoMapping;
345 }
346
347 public void setMessageInfoMapping(MessageInfoMapping messageInfoMapping)
348 {
349 this.messageInfoMapping = messageInfoMapping;
350 }
351
352 public TransactionConfig getTransactionConfig()
353 {
354 return transactionConfig;
355 }
356
357 public void setTransactionConfig(TransactionConfig transactionConfig)
358 {
359 this.transactionConfig = transactionConfig;
360 }
361
362 public boolean isDynamicEndpoints()
363 {
364 return false;
365 }
366
367
368
369
370
371
372 public OutboundEndpoint getEndpoint(String name)
373 {
374 OutboundEndpoint endpointDescriptor;
375 for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
376 {
377 endpointDescriptor = (OutboundEndpoint) iterator.next();
378 if (endpointDescriptor.getName().equals(name))
379 {
380 return endpointDescriptor;
381 }
382 }
383 return null;
384 }
385 }