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