001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.impl;
018
019 import java.util.Map;
020 import java.util.concurrent.Callable;
021 import java.util.concurrent.ExecutorService;
022 import java.util.concurrent.Future;
023 import java.util.concurrent.TimeUnit;
024 import java.util.concurrent.TimeoutException;
025
026 import org.apache.camel.CamelContext;
027 import org.apache.camel.CamelExecutionException;
028 import org.apache.camel.Endpoint;
029 import org.apache.camel.Exchange;
030 import org.apache.camel.ExchangePattern;
031 import org.apache.camel.Message;
032 import org.apache.camel.NoSuchEndpointException;
033 import org.apache.camel.Processor;
034 import org.apache.camel.ProducerTemplate;
035 import org.apache.camel.spi.Synchronization;
036 import org.apache.camel.support.ServiceSupport;
037 import org.apache.camel.util.CamelContextHelper;
038 import org.apache.camel.util.ExchangeHelper;
039 import org.apache.camel.util.ObjectHelper;
040 import org.apache.camel.util.ServiceHelper;
041
042 /**
043 * Template (named like Spring's TransactionTemplate & JmsTemplate
044 * et al) for working with Camel and sending {@link Message} instances in an
045 * {@link Exchange} to an {@link Endpoint}.
046 *
047 * @version
048 */
049 public class DefaultProducerTemplate extends ServiceSupport implements ProducerTemplate {
050 private final CamelContext context;
051 private volatile ProducerCache producerCache;
052 private volatile ExecutorService executor;
053 private Endpoint defaultEndpoint;
054 private int maximumCacheSize;
055
056 public DefaultProducerTemplate(CamelContext context) {
057 this.context = context;
058 }
059
060 public DefaultProducerTemplate(CamelContext context, ExecutorService executor) {
061 this.context = context;
062 this.executor = executor;
063 }
064
065 public DefaultProducerTemplate(CamelContext context, Endpoint defaultEndpoint) {
066 this(context);
067 this.defaultEndpoint = defaultEndpoint;
068 }
069
070 public static DefaultProducerTemplate newInstance(CamelContext camelContext, String defaultEndpointUri) {
071 Endpoint endpoint = CamelContextHelper.getMandatoryEndpoint(camelContext, defaultEndpointUri);
072 return new DefaultProducerTemplate(camelContext, endpoint);
073 }
074
075 public int getMaximumCacheSize() {
076 return maximumCacheSize;
077 }
078
079 public void setMaximumCacheSize(int maximumCacheSize) {
080 this.maximumCacheSize = maximumCacheSize;
081 }
082
083 public int getCurrentCacheSize() {
084 if (producerCache == null) {
085 return 0;
086 }
087 return producerCache.size();
088 }
089
090 public Exchange send(String endpointUri, Exchange exchange) {
091 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
092 return send(endpoint, exchange);
093 }
094
095 public Exchange send(String endpointUri, Processor processor) {
096 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
097 return send(endpoint, processor);
098 }
099
100 public Exchange send(String endpointUri, ExchangePattern pattern, Processor processor) {
101 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
102 return send(endpoint, pattern, processor);
103 }
104
105 public Exchange send(Endpoint endpoint, Exchange exchange) {
106 getProducerCache().send(endpoint, exchange);
107 return exchange;
108 }
109
110 public Exchange send(Endpoint endpoint, Processor processor) {
111 return getProducerCache().send(endpoint, processor);
112 }
113
114 public Exchange send(Endpoint endpoint, ExchangePattern pattern, Processor processor) {
115 return getProducerCache().send(endpoint, pattern, processor);
116 }
117
118 public Object sendBody(Endpoint endpoint, ExchangePattern pattern, Object body) {
119 Exchange result = send(endpoint, pattern, createSetBodyProcessor(body));
120 return extractResultBody(result, pattern);
121 }
122
123 public void sendBody(Endpoint endpoint, Object body) throws CamelExecutionException {
124 Exchange result = send(endpoint, createSetBodyProcessor(body));
125 // must invoke extract result body in case of exception to be rethrown
126 extractResultBody(result);
127 }
128
129 public void sendBody(String endpointUri, Object body) throws CamelExecutionException {
130 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
131 sendBody(endpoint, body);
132 }
133
134 public Object sendBody(String endpointUri, ExchangePattern pattern, Object body) throws CamelExecutionException {
135 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
136 Object result = sendBody(endpoint, pattern, body);
137 if (pattern.isOutCapable()) {
138 return result;
139 } else {
140 // return null if not OUT capable
141 return null;
142 }
143 }
144
145 public void sendBodyAndHeader(String endpointUri, final Object body, final String header, final Object headerValue) throws CamelExecutionException {
146 sendBodyAndHeader(resolveMandatoryEndpoint(endpointUri), body, header, headerValue);
147 }
148
149 public void sendBodyAndHeader(Endpoint endpoint, final Object body, final String header, final Object headerValue) throws CamelExecutionException {
150 Exchange result = send(endpoint, createBodyAndHeaderProcessor(body, header, headerValue));
151 // must invoke extract result body in case of exception to be rethrown
152 extractResultBody(result);
153 }
154
155 public Object sendBodyAndHeader(Endpoint endpoint, ExchangePattern pattern, final Object body,
156 final String header, final Object headerValue) throws CamelExecutionException {
157 Exchange exchange = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
158 Object result = extractResultBody(exchange, pattern);
159 if (pattern.isOutCapable()) {
160 return result;
161 } else {
162 // return null if not OUT capable
163 return null;
164 }
165 }
166
167 public Object sendBodyAndHeader(String endpoint, ExchangePattern pattern, final Object body,
168 final String header, final Object headerValue) throws CamelExecutionException {
169 Exchange exchange = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
170 Object result = extractResultBody(exchange, pattern);
171 if (pattern.isOutCapable()) {
172 return result;
173 } else {
174 // return null if not OUT capable
175 return null;
176 }
177 }
178
179 public void sendBodyAndProperty(String endpointUri, final Object body,
180 final String property, final Object propertyValue) throws CamelExecutionException {
181 sendBodyAndProperty(resolveMandatoryEndpoint(endpointUri), body, property, propertyValue);
182 }
183
184 public void sendBodyAndProperty(Endpoint endpoint, final Object body,
185 final String property, final Object propertyValue) throws CamelExecutionException {
186 Exchange result = send(endpoint, createBodyAndPropertyProcessor(body, property, propertyValue));
187 // must invoke extract result body in case of exception to be rethrown
188 extractResultBody(result);
189 }
190
191 public Object sendBodyAndProperty(Endpoint endpoint, ExchangePattern pattern, final Object body,
192 final String property, final Object propertyValue) throws CamelExecutionException {
193 Exchange exchange = send(endpoint, pattern, createBodyAndPropertyProcessor(body, property, propertyValue));
194 Object result = extractResultBody(exchange, pattern);
195 if (pattern.isOutCapable()) {
196 return result;
197 } else {
198 // return null if not OUT capable
199 return null;
200 }
201 }
202
203 public Object sendBodyAndProperty(String endpoint, ExchangePattern pattern, final Object body,
204 final String property, final Object propertyValue) throws CamelExecutionException {
205 Exchange exchange = send(endpoint, pattern, createBodyAndPropertyProcessor(body, property, propertyValue));
206 Object result = extractResultBody(exchange, pattern);
207 if (pattern.isOutCapable()) {
208 return result;
209 } else {
210 // return null if not OUT capable
211 return null;
212 }
213 }
214
215 public void sendBodyAndHeaders(String endpointUri, final Object body, final Map<String, Object> headers) throws CamelExecutionException {
216 sendBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers);
217 }
218
219 public void sendBodyAndHeaders(Endpoint endpoint, final Object body, final Map<String, Object> headers) throws CamelExecutionException {
220 Exchange result = send(endpoint, new Processor() {
221 public void process(Exchange exchange) {
222 Message in = exchange.getIn();
223 for (Map.Entry<String, Object> header : headers.entrySet()) {
224 in.setHeader(header.getKey(), header.getValue());
225 }
226 in.setBody(body);
227 }
228 });
229 // must invoke extract result body in case of exception to be rethrown
230 extractResultBody(result);
231 }
232
233 public Object sendBodyAndHeaders(String endpointUri, ExchangePattern pattern, Object body, Map<String, Object> headers) throws CamelExecutionException {
234 return sendBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), pattern, body, headers);
235 }
236
237 public Object sendBodyAndHeaders(Endpoint endpoint, ExchangePattern pattern, final Object body, final Map<String, Object> headers) throws CamelExecutionException {
238 Exchange exchange = send(endpoint, pattern, new Processor() {
239 public void process(Exchange exchange) throws Exception {
240 Message in = exchange.getIn();
241 for (Map.Entry<String, Object> header : headers.entrySet()) {
242 in.setHeader(header.getKey(), header.getValue());
243 }
244 in.setBody(body);
245 }
246 });
247 Object result = extractResultBody(exchange, pattern);
248 if (pattern.isOutCapable()) {
249 return result;
250 } else {
251 // return null if not OUT capable
252 return null;
253 }
254 }
255
256 // Methods using an InOut ExchangePattern
257 // -----------------------------------------------------------------------
258
259 public Exchange request(Endpoint endpoint, Processor processor) {
260 return send(endpoint, ExchangePattern.InOut, processor);
261 }
262
263 public Object requestBody(Object body) throws CamelExecutionException {
264 return sendBody(getMandatoryDefaultEndpoint(), ExchangePattern.InOut, body);
265 }
266
267 public Object requestBody(Endpoint endpoint, Object body) throws CamelExecutionException {
268 return sendBody(endpoint, ExchangePattern.InOut, body);
269 }
270
271 public Object requestBodyAndHeader(Object body, String header, Object headerValue) throws CamelExecutionException {
272 return sendBodyAndHeader(getMandatoryDefaultEndpoint(), ExchangePattern.InOut, body, header, headerValue);
273 }
274
275 public Object requestBodyAndHeader(Endpoint endpoint, Object body, String header, Object headerValue) throws CamelExecutionException {
276 return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
277 }
278
279 public Exchange request(String endpoint, Processor processor) throws CamelExecutionException {
280 return send(endpoint, ExchangePattern.InOut, processor);
281 }
282
283 public Object requestBody(String endpoint, Object body) throws CamelExecutionException {
284 return sendBody(endpoint, ExchangePattern.InOut, body);
285 }
286
287 public Object requestBodyAndHeader(String endpoint, Object body, String header, Object headerValue) throws CamelExecutionException {
288 return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
289 }
290
291 public Object requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) {
292 return requestBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers);
293 }
294
295 public Object requestBodyAndHeaders(Endpoint endpoint, final Object body, final Map<String, Object> headers) {
296 return sendBodyAndHeaders(endpoint, ExchangePattern.InOut, body, headers);
297 }
298
299 public Object requestBodyAndHeaders(final Object body, final Map<String, Object> headers) {
300 return sendBodyAndHeaders(getDefaultEndpoint(), ExchangePattern.InOut, body, headers);
301 }
302
303 public <T> T requestBody(Object body, Class<T> type) {
304 Object answer = requestBody(body);
305 return context.getTypeConverter().convertTo(type, answer);
306 }
307
308 public <T> T requestBody(Endpoint endpoint, Object body, Class<T> type) {
309 Object answer = requestBody(endpoint, body);
310 return context.getTypeConverter().convertTo(type, answer);
311 }
312
313 public <T> T requestBody(String endpointUri, Object body, Class<T> type) {
314 Object answer = requestBody(endpointUri, body);
315 return context.getTypeConverter().convertTo(type, answer);
316 }
317
318 public <T> T requestBodyAndHeader(Endpoint endpoint, Object body, String header, Object headerValue, Class<T> type) {
319 Object answer = requestBodyAndHeader(endpoint, body, header, headerValue);
320 return context.getTypeConverter().convertTo(type, answer);
321 }
322
323 public <T> T requestBodyAndHeader(String endpointUri, Object body, String header, Object headerValue, Class<T> type) {
324 Object answer = requestBodyAndHeader(endpointUri, body, header, headerValue);
325 return context.getTypeConverter().convertTo(type, answer);
326 }
327
328 public <T> T requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers, Class<T> type) {
329 Object answer = requestBodyAndHeaders(endpointUri, body, headers);
330 return context.getTypeConverter().convertTo(type, answer);
331 }
332
333 public <T> T requestBodyAndHeaders(Endpoint endpoint, Object body, Map<String, Object> headers, Class<T> type) {
334 Object answer = requestBodyAndHeaders(endpoint, body, headers);
335 return context.getTypeConverter().convertTo(type, answer);
336 }
337
338 // Methods using the default endpoint
339 // -----------------------------------------------------------------------
340
341 public void sendBody(Object body) {
342 sendBody(getMandatoryDefaultEndpoint(), body);
343 }
344
345 public Exchange send(Exchange exchange) {
346 return send(getMandatoryDefaultEndpoint(), exchange);
347 }
348
349 public Exchange send(Processor processor) {
350 return send(getMandatoryDefaultEndpoint(), processor);
351 }
352
353 public void sendBodyAndHeader(Object body, String header, Object headerValue) {
354 sendBodyAndHeader(getMandatoryDefaultEndpoint(), body, header, headerValue);
355 }
356
357 public void sendBodyAndProperty(Object body, String property, Object propertyValue) {
358 sendBodyAndProperty(getMandatoryDefaultEndpoint(), body, property, propertyValue);
359 }
360
361 public void sendBodyAndHeaders(Object body, Map<String, Object> headers) {
362 sendBodyAndHeaders(getMandatoryDefaultEndpoint(), body, headers);
363 }
364
365 // Properties
366 // -----------------------------------------------------------------------
367
368 public CamelContext getContext() {
369 return context;
370 }
371
372 public Endpoint getDefaultEndpoint() {
373 return defaultEndpoint;
374 }
375
376 public void setDefaultEndpoint(Endpoint defaultEndpoint) {
377 this.defaultEndpoint = defaultEndpoint;
378 }
379
380 /**
381 * Sets the default endpoint to use if none is specified
382 */
383 public void setDefaultEndpointUri(String endpointUri) {
384 setDefaultEndpoint(getContext().getEndpoint(endpointUri));
385 }
386
387 public <T extends Endpoint> T getResolvedEndpoint(String endpointUri, Class<T> expectedClass) {
388 return context.getEndpoint(endpointUri, expectedClass);
389 }
390
391 // Implementation methods
392 // -----------------------------------------------------------------------
393
394 protected Processor createBodyAndHeaderProcessor(final Object body, final String header, final Object headerValue) {
395 return new Processor() {
396 public void process(Exchange exchange) {
397 Message in = exchange.getIn();
398 in.setHeader(header, headerValue);
399 in.setBody(body);
400 }
401 };
402 }
403
404 protected Processor createBodyAndPropertyProcessor(final Object body, final String property, final Object propertyValue) {
405 return new Processor() {
406 public void process(Exchange exchange) {
407 exchange.setProperty(property, propertyValue);
408 Message in = exchange.getIn();
409 in.setBody(body);
410 }
411 };
412 }
413
414 protected Processor createSetBodyProcessor(final Object body) {
415 return new Processor() {
416 public void process(Exchange exchange) {
417 Message in = exchange.getIn();
418 in.setBody(body);
419 }
420 };
421 }
422
423 protected Endpoint resolveMandatoryEndpoint(String endpointUri) {
424 Endpoint endpoint = context.getEndpoint(endpointUri);
425 if (endpoint == null) {
426 throw new NoSuchEndpointException(endpointUri);
427 }
428 return endpoint;
429 }
430
431 protected Endpoint getMandatoryDefaultEndpoint() {
432 Endpoint answer = getDefaultEndpoint();
433 ObjectHelper.notNull(answer, "defaultEndpoint");
434 return answer;
435 }
436
437 protected Object extractResultBody(Exchange result) {
438 return extractResultBody(result, null);
439 }
440
441 protected Object extractResultBody(Exchange result, ExchangePattern pattern) {
442 return ExchangeHelper.extractResultBody(result, pattern);
443 }
444
445 public void setExecutorService(ExecutorService executorService) {
446 this.executor = executorService;
447 }
448
449 public Future<Exchange> asyncSend(final String uri, final Exchange exchange) {
450 return asyncSend(resolveMandatoryEndpoint(uri), exchange);
451 }
452
453 public Future<Exchange> asyncSend(final String uri, final Processor processor) {
454 return asyncSend(resolveMandatoryEndpoint(uri), processor);
455 }
456
457 public Future<Object> asyncSendBody(final String uri, final Object body) {
458 return asyncSendBody(resolveMandatoryEndpoint(uri), body);
459 }
460
461 public Future<Object> asyncRequestBody(final String uri, final Object body) {
462 return asyncRequestBody(resolveMandatoryEndpoint(uri), body);
463 }
464
465 public <T> Future<T> asyncRequestBody(final String uri, final Object body, final Class<T> type) {
466 return asyncRequestBody(resolveMandatoryEndpoint(uri), body, type);
467 }
468
469 public Future<Object> asyncRequestBodyAndHeader(final String endpointUri, final Object body, final String header, final Object headerValue) {
470 return asyncRequestBodyAndHeader(resolveMandatoryEndpoint(endpointUri), body, header, headerValue);
471 }
472
473 public <T> Future<T> asyncRequestBodyAndHeader(final String endpointUri, final Object body, final String header, final Object headerValue, final Class<T> type) {
474 return asyncRequestBodyAndHeader(resolveMandatoryEndpoint(endpointUri), body, header, headerValue, type);
475 }
476
477 public Future<Object> asyncRequestBodyAndHeaders(final String endpointUri, final Object body, final Map<String, Object> headers) {
478 return asyncRequestBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers);
479 }
480
481 public <T> Future<T> asyncRequestBodyAndHeaders(final String endpointUri, final Object body, final Map<String, Object> headers, final Class<T> type) {
482 return asyncRequestBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers, type);
483 }
484
485 public <T> T extractFutureBody(Future<Object> future, Class<T> type) {
486 return ExchangeHelper.extractFutureBody(context, future, type);
487 }
488
489 public <T> T extractFutureBody(Future<Object> future, long timeout, TimeUnit unit, Class<T> type) throws TimeoutException {
490 return ExchangeHelper.extractFutureBody(context, future, timeout, unit, type);
491 }
492
493 public Future<Object> asyncCallbackSendBody(String uri, Object body, Synchronization onCompletion) {
494 return asyncCallbackSendBody(resolveMandatoryEndpoint(uri), body, onCompletion);
495 }
496
497 public Future<Object> asyncCallbackSendBody(Endpoint endpoint, Object body, Synchronization onCompletion) {
498 return asyncCallback(endpoint, ExchangePattern.InOnly, body, onCompletion);
499 }
500
501 public Future<Object> asyncCallbackRequestBody(String uri, Object body, Synchronization onCompletion) {
502 return asyncCallbackRequestBody(resolveMandatoryEndpoint(uri), body, onCompletion);
503 }
504
505 public Future<Object> asyncCallbackRequestBody(Endpoint endpoint, Object body, Synchronization onCompletion) {
506 return asyncCallback(endpoint, ExchangePattern.InOut, body, onCompletion);
507 }
508
509 public Future<Exchange> asyncCallback(String uri, Exchange exchange, Synchronization onCompletion) {
510 return asyncCallback(resolveMandatoryEndpoint(uri), exchange, onCompletion);
511 }
512
513 public Future<Exchange> asyncCallback(String uri, Processor processor, Synchronization onCompletion) {
514 return asyncCallback(resolveMandatoryEndpoint(uri), processor, onCompletion);
515 }
516
517 public Future<Object> asyncRequestBody(final Endpoint endpoint, final Object body) {
518 Callable<Object> task = new Callable<Object>() {
519 public Object call() throws Exception {
520 return requestBody(endpoint, body);
521 }
522 };
523 return getExecutorService().submit(task);
524 }
525
526 public <T> Future<T> asyncRequestBody(final Endpoint endpoint, final Object body, final Class<T> type) {
527 Callable<T> task = new Callable<T>() {
528 public T call() throws Exception {
529 return requestBody(endpoint, body, type);
530 }
531 };
532 return getExecutorService().submit(task);
533 }
534
535 public Future<Object> asyncRequestBodyAndHeader(final Endpoint endpoint, final Object body, final String header,
536 final Object headerValue) {
537 Callable<Object> task = new Callable<Object>() {
538 public Object call() throws Exception {
539 return requestBodyAndHeader(endpoint, body, header, headerValue);
540 }
541 };
542 return getExecutorService().submit(task);
543 }
544
545 public <T> Future<T> asyncRequestBodyAndHeader(final Endpoint endpoint, final Object body, final String header,
546 final Object headerValue, final Class<T> type) {
547 Callable<T> task = new Callable<T>() {
548 public T call() throws Exception {
549 return requestBodyAndHeader(endpoint, body, header, headerValue, type);
550 }
551 };
552 return getExecutorService().submit(task);
553 }
554
555 public Future<Object> asyncRequestBodyAndHeaders(final Endpoint endpoint, final Object body,
556 final Map<String, Object> headers) {
557 Callable<Object> task = new Callable<Object>() {
558 public Object call() throws Exception {
559 return requestBodyAndHeaders(endpoint, body, headers);
560 }
561 };
562 return getExecutorService().submit(task);
563 }
564
565 public <T> Future<T> asyncRequestBodyAndHeaders(final Endpoint endpoint, final Object body,
566 final Map<String, Object> headers, final Class<T> type) {
567 Callable<T> task = new Callable<T>() {
568 public T call() throws Exception {
569 return requestBodyAndHeaders(endpoint, body, headers, type);
570 }
571 };
572 return getExecutorService().submit(task);
573 }
574
575 public Future<Exchange> asyncSend(final Endpoint endpoint, final Exchange exchange) {
576 Callable<Exchange> task = new Callable<Exchange>() {
577 public Exchange call() throws Exception {
578 return send(endpoint, exchange);
579 }
580 };
581 return getExecutorService().submit(task);
582 }
583
584 public Future<Exchange> asyncSend(final Endpoint endpoint, final Processor processor) {
585 Callable<Exchange> task = new Callable<Exchange>() {
586 public Exchange call() throws Exception {
587 return send(endpoint, processor);
588 }
589 };
590 return getExecutorService().submit(task);
591 }
592
593 public Future<Object> asyncSendBody(final Endpoint endpoint, final Object body) {
594 Callable<Object> task = new Callable<Object>() {
595 public Object call() throws Exception {
596 sendBody(endpoint, body);
597 // its InOnly, so no body to return
598 return null;
599 }
600 };
601 return getExecutorService().submit(task);
602 }
603
604 private Future<Object> asyncCallback(final Endpoint endpoint, final ExchangePattern pattern, final Object body, final Synchronization onCompletion) {
605 Callable<Object> task = new Callable<Object>() {
606 public Object call() throws Exception {
607 Exchange answer = send(endpoint, pattern, createSetBodyProcessor(body));
608
609 // invoke callback before returning answer
610 // as it allows callback to be used without UnitOfWorkProcessor invoking it
611 // and thus it works directly from a producer template as well, as opposed
612 // to the UnitOfWorkProcessor that is injected in routes
613 if (answer.isFailed()) {
614 onCompletion.onFailure(answer);
615 } else {
616 onCompletion.onComplete(answer);
617 }
618
619 Object result = extractResultBody(answer, pattern);
620 if (pattern.isOutCapable()) {
621 return result;
622 } else {
623 // return null if not OUT capable
624 return null;
625 }
626 }
627 };
628 return getExecutorService().submit(task);
629 }
630
631 public Future<Exchange> asyncCallback(final Endpoint endpoint, final Exchange exchange, final Synchronization onCompletion) {
632 Callable<Exchange> task = new Callable<Exchange>() {
633 public Exchange call() throws Exception {
634 // process the exchange, any exception occurring will be caught and set on the exchange
635 send(endpoint, exchange);
636
637 // invoke callback before returning answer
638 // as it allows callback to be used without UnitOfWorkProcessor invoking it
639 // and thus it works directly from a producer template as well, as opposed
640 // to the UnitOfWorkProcessor that is injected in routes
641 if (exchange.isFailed()) {
642 onCompletion.onFailure(exchange);
643 } else {
644 onCompletion.onComplete(exchange);
645 }
646 return exchange;
647 }
648 };
649 return getExecutorService().submit(task);
650 }
651
652 public Future<Exchange> asyncCallback(final Endpoint endpoint, final Processor processor, final Synchronization onCompletion) {
653 Callable<Exchange> task = new Callable<Exchange>() {
654 public Exchange call() throws Exception {
655 // process the exchange, any exception occurring will be caught and set on the exchange
656 Exchange answer = send(endpoint, processor);
657
658 // invoke callback before returning answer
659 // as it allows callback to be used without UnitOfWorkProcessor invoking it
660 // and thus it works directly from a producer template as well, as opposed
661 // to the UnitOfWorkProcessor that is injected in routes
662 if (answer.isFailed()) {
663 onCompletion.onFailure(answer);
664 } else {
665 onCompletion.onComplete(answer);
666 }
667 return answer;
668 }
669 };
670 return getExecutorService().submit(task);
671 }
672
673 private ProducerCache getProducerCache() {
674 if (!isStarted()) {
675 throw new IllegalStateException("ProducerTemplate has not been started");
676 }
677 return producerCache;
678 }
679
680 private ExecutorService getExecutorService() {
681 if (!isStarted()) {
682 throw new IllegalStateException("ProducerTemplate has not been started");
683 }
684
685 if (executor != null) {
686 return executor;
687 }
688
689 // create a default executor which must be synchronized
690 synchronized (this) {
691 if (executor != null) {
692 return executor;
693 }
694 executor = context.getExecutorServiceManager().newDefaultThreadPool(this, "ProducerTemplate");
695 }
696
697 ObjectHelper.notNull(executor, "ExecutorService");
698 return executor;
699 }
700
701 protected void doStart() throws Exception {
702 if (producerCache == null) {
703 if (maximumCacheSize > 0) {
704 producerCache = new ProducerCache(this, context, maximumCacheSize);
705 } else {
706 producerCache = new ProducerCache(this, context);
707 }
708 }
709 ServiceHelper.startService(producerCache);
710 }
711
712 protected void doStop() throws Exception {
713 ServiceHelper.stopService(producerCache);
714 producerCache = null;
715
716 if (executor != null) {
717 context.getExecutorServiceManager().shutdownNow(executor);
718 executor = null;
719 }
720 }
721
722 }