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.model;
018
019 import java.util.ArrayList;
020 import java.util.Collection;
021 import java.util.HashMap;
022 import java.util.List;
023 import java.util.Map;
024 import javax.xml.bind.annotation.XmlAccessType;
025 import javax.xml.bind.annotation.XmlAccessorType;
026 import javax.xml.bind.annotation.XmlAttribute;
027 import javax.xml.bind.annotation.XmlElement;
028 import javax.xml.bind.annotation.XmlElementRef;
029 import javax.xml.bind.annotation.XmlRootElement;
030 import javax.xml.bind.annotation.XmlTransient;
031
032 import org.apache.camel.CamelContext;
033 import org.apache.camel.Expression;
034 import org.apache.camel.LoggingLevel;
035 import org.apache.camel.Predicate;
036 import org.apache.camel.Processor;
037 import org.apache.camel.Route;
038 import org.apache.camel.builder.ErrorHandlerBuilder;
039 import org.apache.camel.builder.ExpressionBuilder;
040 import org.apache.camel.processor.CatchProcessor;
041 import org.apache.camel.processor.FatalFallbackErrorHandler;
042 import org.apache.camel.processor.RedeliveryPolicy;
043 import org.apache.camel.spi.ClassResolver;
044 import org.apache.camel.spi.RouteContext;
045 import org.apache.camel.util.CamelContextHelper;
046 import org.apache.camel.util.ExpressionToPredicateAdapter;
047 import org.apache.camel.util.ObjectHelper;
048
049 /**
050 * Represents an XML <onException/> element
051 *
052 * @version
053 */
054 @XmlRootElement(name = "onException")
055 @XmlAccessorType(XmlAccessType.FIELD)
056 public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefinition> {
057 @XmlElement(name = "exception", required = true)
058 private List<String> exceptions = new ArrayList<String>();
059 @XmlElement(name = "onWhen")
060 private WhenDefinition onWhen;
061 @XmlElement(name = "retryWhile")
062 private ExpressionSubElementDefinition retryWhile;
063 @XmlElement(name = "redeliveryPolicy")
064 private RedeliveryPolicyDefinition redeliveryPolicy;
065 @XmlAttribute(name = "redeliveryPolicyRef")
066 private String redeliveryPolicyRef;
067 @XmlElement(name = "handled")
068 private ExpressionSubElementDefinition handled;
069 @XmlElement(name = "continued")
070 private ExpressionSubElementDefinition continued;
071 @XmlAttribute(name = "onRedeliveryRef")
072 private String onRedeliveryRef;
073 @XmlAttribute(name = "useOriginalMessage")
074 private Boolean useOriginalMessagePolicy;
075 @XmlElementRef
076 private List<ProcessorDefinition<?>> outputs = new ArrayList<ProcessorDefinition<?>>();
077 @XmlTransient
078 private List<Class<? extends Throwable>> exceptionClasses;
079 @XmlTransient
080 private Predicate handledPolicy;
081 @XmlTransient
082 private Predicate continuedPolicy;
083 @XmlTransient
084 private Predicate retryWhilePolicy;
085 @XmlTransient
086 private Processor onRedelivery;
087 @XmlTransient
088 private Boolean routeScoped;
089 // TODO: in Camel 3.0 the OnExceptionDefinition should not contain state and ErrorHandler processors
090 @XmlTransient
091 private final Map<String, Processor> errorHandlers = new HashMap<String, Processor>();
092
093 public OnExceptionDefinition() {
094 }
095
096 public OnExceptionDefinition(List<Class<? extends Throwable>> exceptionClasses) {
097 this.exceptionClasses = exceptionClasses;
098 }
099
100 public OnExceptionDefinition(Class<? extends Throwable> exceptionType) {
101 exceptionClasses = new ArrayList<Class<? extends Throwable>>();
102 exceptionClasses.add(exceptionType);
103 }
104
105 public boolean isRouteScoped() {
106 // is context scoped by default
107 return routeScoped != null ? routeScoped : false;
108 }
109
110 @Override
111 public String getShortName() {
112 return "onException";
113 }
114
115 @Override
116 public String toString() {
117 return "OnException[" + description() + " -> " + getOutputs() + "]";
118 }
119
120 protected String description() {
121 return getExceptionClasses() + (onWhen != null ? " " + onWhen : "");
122 }
123
124 @Override
125 public String getLabel() {
126 return "onException[" + description() + "]";
127 }
128
129 @Override
130 public boolean isAbstract() {
131 return true;
132 }
133
134 /**
135 * Allows an exception handler to create a new redelivery policy for this exception type
136 *
137 * @param context the camel context
138 * @param parentPolicy the current redelivery policy, is newer <tt>null</tt>
139 * @return a newly created redelivery policy, or return the original policy if no customization is required
140 * for this exception handler.
141 */
142 public RedeliveryPolicy createRedeliveryPolicy(CamelContext context, RedeliveryPolicy parentPolicy) {
143 if (redeliveryPolicyRef != null) {
144 return CamelContextHelper.mandatoryLookup(context, redeliveryPolicyRef, RedeliveryPolicy.class);
145 } else if (redeliveryPolicy != null) {
146 return redeliveryPolicy.createRedeliveryPolicy(context, parentPolicy);
147 } else if (!outputs.isEmpty() && parentPolicy.getMaximumRedeliveries() > 0) {
148 // if we have outputs, then do not inherit parent maximumRedeliveries
149 // as you would have to explicit configure maximumRedeliveries on this onException to use it
150 // this is the behavior Camel has always had
151 RedeliveryPolicy answer = parentPolicy.copy();
152 answer.setMaximumRedeliveries(0);
153 return answer;
154 } else {
155 return parentPolicy;
156 }
157 }
158
159 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
160 // assign whether this was a route scoped onException or not
161 // we need to know this later when setting the parent, as only route scoped should have parent
162 // Note: this logic can possible be removed when the Camel routing engine decides at runtime
163 // to apply onException in a more dynamic fashion than current code base
164 // and therefore is in a better position to decide among context/route scoped OnException at runtime
165 if (routeScoped == null) {
166 routeScoped = super.getParent() != null;
167 }
168
169 setHandledFromExpressionType(routeContext);
170 setContinuedFromExpressionType(routeContext);
171 setRetryWhileFromExpressionType(routeContext);
172 setOnRedeliveryFromRedeliveryRef(routeContext);
173
174 // load exception classes
175 if (exceptions != null && !exceptions.isEmpty()) {
176 exceptionClasses = createExceptionClasses(routeContext.getCamelContext().getClassResolver());
177 }
178
179 // must validate configuration before creating processor
180 validateConfiguration();
181
182 // lets attach this on exception to the route error handler
183 Processor child = createOutputsProcessor(routeContext);
184 if (child != null) {
185 // wrap in our special safe fallback error handler if OnException have child output
186 Processor errorHandler = new FatalFallbackErrorHandler(child);
187 String id = routeContext.getRoute().getId();
188 errorHandlers.put(id, errorHandler);
189 }
190 // lookup the error handler builder
191 ErrorHandlerBuilder builder = (ErrorHandlerBuilder)routeContext.getRoute().getErrorHandlerBuilder();
192 // and add this as error handlers
193 builder.addErrorHandlers(this);
194 }
195
196 @Override
197 public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
198 // load exception classes
199 if (exceptions != null && !exceptions.isEmpty()) {
200 exceptionClasses = createExceptionClasses(routeContext.getCamelContext().getClassResolver());
201 }
202
203 // must validate configuration before creating processor
204 validateConfiguration();
205
206 Processor childProcessor = this.createChildProcessor(routeContext, false);
207
208 Predicate when = null;
209 if (onWhen != null) {
210 when = onWhen.getExpression().createPredicate(routeContext);
211 }
212
213 Predicate handle = null;
214 if (handled != null) {
215 handle = handled.createPredicate(routeContext);
216 }
217
218 return new CatchProcessor(getExceptionClasses(), childProcessor, when, handle);
219 }
220
221 protected void validateConfiguration() {
222 if (isInheritErrorHandler() != null && isInheritErrorHandler()) {
223 throw new IllegalArgumentException(this + " cannot have the inheritErrorHandler option set to true");
224 }
225
226 List<Class<? extends Throwable>> exceptions = getExceptionClasses();
227 if (exceptions == null || exceptions.isEmpty()) {
228 throw new IllegalArgumentException("At least one exception must be configured on " + this);
229 }
230
231 // only one of handled or continued is allowed
232 if (getHandledPolicy() != null && getContinuedPolicy() != null) {
233 throw new IllegalArgumentException("Only one of handled or continued is allowed to be configured on: " + this);
234 }
235
236 // validate that at least some option is set as you cannot just have onException(Exception.class);
237 if (outputs == null || getOutputs().isEmpty()) {
238 // no outputs so there should be some sort of configuration
239 if (handledPolicy == null && continuedPolicy == null && retryWhilePolicy == null
240 && redeliveryPolicy == null && useOriginalMessagePolicy == null && onRedelivery == null) {
241 throw new IllegalArgumentException(this + " is not configured.");
242 }
243 }
244 }
245
246 // Fluent API
247 //-------------------------------------------------------------------------
248
249 @Override
250 public OnExceptionDefinition onException(Class<? extends Throwable> exceptionType) {
251 getExceptionClasses().add(exceptionType);
252 return this;
253 }
254
255 /**
256 * Sets whether the exchange should be marked as handled or not.
257 *
258 * @param handled handled or not
259 * @return the builder
260 */
261 public OnExceptionDefinition handled(boolean handled) {
262 Expression expression = ExpressionBuilder.constantExpression(Boolean.toString(handled));
263 return handled(expression);
264 }
265
266 /**
267 * Sets whether the exchange should be marked as handled or not.
268 *
269 * @param handled predicate that determines true or false
270 * @return the builder
271 */
272 public OnExceptionDefinition handled(Predicate handled) {
273 setHandledPolicy(handled);
274 return this;
275 }
276
277 /**
278 * Sets whether the exchange should be marked as handled or not.
279 *
280 * @param handled expression that determines true or false
281 * @return the builder
282 */
283 public OnExceptionDefinition handled(Expression handled) {
284 setHandledPolicy(ExpressionToPredicateAdapter.toPredicate(handled));
285 return this;
286 }
287
288 /**
289 * Sets whether the exchange should handle and continue routing from the point of failure.
290 * <p/>
291 * If this option is enabled then its considered handled as well.
292 *
293 * @param continued continued or not
294 * @return the builder
295 */
296 public OnExceptionDefinition continued(boolean continued) {
297 Expression expression = ExpressionBuilder.constantExpression(Boolean.toString(continued));
298 return continued(expression);
299 }
300
301 /**
302 * Sets whether the exchange should be marked as handled or not.
303 * <p/>
304 * If this option is enabled then its considered handled as well.
305 *
306 * @param continued predicate that determines true or false
307 * @return the builder
308 */
309 public OnExceptionDefinition continued(Predicate continued) {
310 setContinuedPolicy(continued);
311 return this;
312 }
313
314 /**
315 * Sets whether the exchange should be marked as handled or not.
316 * <p/>
317 * If this option is enabled then its considered handled as well.
318 *
319 * @param continued expression that determines true or false
320 * @return the builder
321 */
322 public OnExceptionDefinition continued(Expression continued) {
323 setContinuedPolicy(ExpressionToPredicateAdapter.toPredicate(continued));
324 return this;
325 }
326
327 /**
328 * Sets an additional predicate that should be true before the onException is triggered.
329 * <p/>
330 * To be used for fine grained controlling whether a thrown exception should be intercepted
331 * by this exception type or not.
332 *
333 * @param predicate predicate that determines true or false
334 * @return the builder
335 */
336 public OnExceptionDefinition onWhen(Predicate predicate) {
337 setOnWhen(new WhenDefinition(predicate));
338 return this;
339 }
340
341 /**
342 * Sets the retry while predicate.
343 * <p/>
344 * Will continue retrying until predicate returns <tt>false</tt>.
345 *
346 * @param retryWhile predicate that determines when to stop retrying
347 * @return the builder
348 */
349 public OnExceptionDefinition retryWhile(Predicate retryWhile) {
350 setRetryWhilePolicy(retryWhile);
351 return this;
352 }
353
354 /**
355 * Sets the initial redelivery delay
356 *
357 * @param delay the initial redelivery delay
358 * @return the builder
359 * @deprecated will be removed in the near future. Instead use {@link #redeliveryDelay(String)}
360 */
361 @Deprecated
362 public OnExceptionDefinition redeliverDelay(long delay) {
363 getOrCreateRedeliveryPolicy().redeliveryDelay(delay);
364 return this;
365 }
366
367 /**
368 * Sets the back off multiplier
369 *
370 * @param backOffMultiplier the back off multiplier
371 * @return the builder
372 */
373 public OnExceptionDefinition backOffMultiplier(double backOffMultiplier) {
374 getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
375 return this;
376 }
377
378 /**
379 * Sets the back off multiplier (supports property placeholders)
380 *
381 * @param backOffMultiplier the back off multiplier
382 * @return the builder
383 */
384 public OnExceptionDefinition backOffMultiplier(String backOffMultiplier) {
385 getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
386 return this;
387 }
388
389 /**
390 * Sets the collision avoidance factor
391 *
392 * @param collisionAvoidanceFactor the factor
393 * @return the builder
394 */
395 public OnExceptionDefinition collisionAvoidanceFactor(double collisionAvoidanceFactor) {
396 getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor);
397 return this;
398 }
399
400 /**
401 * Sets the collision avoidance factor (supports property placeholders)
402 *
403 * @param collisionAvoidanceFactor the factor
404 * @return the builder
405 */
406 public OnExceptionDefinition collisionAvoidanceFactor(String collisionAvoidanceFactor) {
407 getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor);
408 return this;
409 }
410
411 /**
412 * Sets the collision avoidance percentage
413 *
414 * @param collisionAvoidancePercent the percentage
415 * @return the builder
416 */
417 public OnExceptionDefinition collisionAvoidancePercent(double collisionAvoidancePercent) {
418 getOrCreateRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
419 return this;
420 }
421
422 /**
423 * Sets the initial redelivery delay
424 *
425 * @param delay delay in millis
426 * @return the builder
427 */
428 public OnExceptionDefinition redeliveryDelay(long delay) {
429 getOrCreateRedeliveryPolicy().redeliveryDelay(delay);
430 return this;
431 }
432
433 /**
434 * Sets the initial redelivery delay (supports property placeholders)
435 *
436 * @param delay delay in millis
437 * @return the builder
438 */
439 public OnExceptionDefinition redeliveryDelay(String delay) {
440 getOrCreateRedeliveryPolicy().redeliveryDelay(delay);
441 return this;
442 }
443
444 /**
445 * Allow synchronous delayed redelivery.
446 *
447 * @see org.apache.camel.processor.RedeliveryPolicy#setAsyncDelayedRedelivery(boolean)
448 * @return the builder
449 */
450 public OnExceptionDefinition asyncDelayedRedelivery() {
451 getOrCreateRedeliveryPolicy().asyncDelayedRedelivery();
452 return this;
453 }
454
455 /**
456 * Sets the logging level to use when retries has exhausted
457 *
458 * @param retriesExhaustedLogLevel the logging level
459 * @return the builder
460 */
461 public OnExceptionDefinition retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
462 getOrCreateRedeliveryPolicy().retriesExhaustedLogLevel(retriesExhaustedLogLevel);
463 return this;
464 }
465
466 /**
467 * Sets the logging level to use for logging retry attempts
468 *
469 * @param retryAttemptedLogLevel the logging level
470 * @return the builder
471 */
472 public OnExceptionDefinition retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
473 getOrCreateRedeliveryPolicy().retryAttemptedLogLevel(retryAttemptedLogLevel);
474 return this;
475 }
476
477 /**
478 * Sets whether to log stacktrace for failed messages.
479 */
480 public OnExceptionDefinition logStackTrace(boolean logStackTrace) {
481 getOrCreateRedeliveryPolicy().logStackTrace(logStackTrace);
482 return this;
483 }
484
485 /**
486 * Sets whether to log stacktrace for failed messages (supports property placeholders)
487 */
488 public OnExceptionDefinition logStackTrace(String logStackTrace) {
489 getOrCreateRedeliveryPolicy().logStackTrace(logStackTrace);
490 return this;
491 }
492
493 /**
494 * Sets whether to log stacktrace for failed redelivery attempts
495 */
496 public OnExceptionDefinition logRetryStackTrace(boolean logRetryStackTrace) {
497 getOrCreateRedeliveryPolicy().logRetryStackTrace(logRetryStackTrace);
498 return this;
499 }
500
501 /**
502 * Sets whether to log stacktrace for failed redelivery attempts (supports property placeholders)
503 */
504 public OnExceptionDefinition logRetryStackTrace(String logRetryStackTrace) {
505 getOrCreateRedeliveryPolicy().logRetryStackTrace(logRetryStackTrace);
506 return this;
507 }
508
509 /**
510 * Sets whether to log errors even if its handled
511 */
512 public OnExceptionDefinition logHandled(boolean logHandled) {
513 getOrCreateRedeliveryPolicy().logHandled(logHandled);
514 return this;
515 }
516
517 /**
518 * Sets whether to log errors even if its handled (supports property placeholders)
519 */
520 public OnExceptionDefinition logHandled(String logHandled) {
521 getOrCreateRedeliveryPolicy().logHandled(logHandled);
522 return this;
523 }
524
525 /**
526 * Sets whether to log errors even if its continued
527 */
528 public OnExceptionDefinition logContinued(boolean logContinued) {
529 getOrCreateRedeliveryPolicy().logContinued(logContinued);
530 return this;
531 }
532
533 /**
534 * Sets whether to log errors even if its continued (supports property placeholders)
535 */
536 public OnExceptionDefinition logContinued(String logContinued) {
537 getOrCreateRedeliveryPolicy().logContinued(logContinued);
538 return this;
539 }
540
541 /**
542 * Sets whether to log retry attempts
543 */
544 public OnExceptionDefinition logRetryAttempted(boolean logRetryAttempted) {
545 getOrCreateRedeliveryPolicy().logRetryAttempted(logRetryAttempted);
546 return this;
547 }
548
549 /**
550 * Sets whether to log retry attempts (supports property placeholders)
551 */
552 public OnExceptionDefinition logRetryAttempted(String logRetryAttempted) {
553 getOrCreateRedeliveryPolicy().logRetryAttempted(logRetryAttempted);
554 return this;
555 }
556
557 /**
558 * Sets whether to log exhausted exceptions
559 */
560 public OnExceptionDefinition logExhausted(boolean logExhausted) {
561 getOrCreateRedeliveryPolicy().logExhausted(logExhausted);
562 return this;
563 }
564
565 /**
566 * Sets whether to log exhausted exceptions (supports property placeholders)
567 */
568 public OnExceptionDefinition logExhausted(String logExhausted) {
569 getOrCreateRedeliveryPolicy().logExhausted(logExhausted);
570 return this;
571 }
572
573 /**
574 * Sets the maximum redeliveries
575 * <ul>
576 * <li>5 = default value</li>
577 * <li>0 = no redeliveries</li>
578 * <li>-1 = redeliver forever</li>
579 * </ul>
580 *
581 * @param maximumRedeliveries the value
582 * @return the builder
583 */
584 public OnExceptionDefinition maximumRedeliveries(int maximumRedeliveries) {
585 getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
586 return this;
587 }
588
589 /**
590 * Sets the maximum redeliveries (supports property placeholders)
591 * <ul>
592 * <li>5 = default value</li>
593 * <li>0 = no redeliveries</li>
594 * <li>-1 = redeliver forever</li>
595 * </ul>
596 *
597 * @param maximumRedeliveries the value
598 * @return the builder
599 */
600 public OnExceptionDefinition maximumRedeliveries(String maximumRedeliveries) {
601 getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
602 return this;
603 }
604
605 /**
606 * Turn on collision avoidance.
607 *
608 * @return the builder
609 */
610 public OnExceptionDefinition useCollisionAvoidance() {
611 getOrCreateRedeliveryPolicy().useCollisionAvoidance();
612 return this;
613 }
614
615 /**
616 * Turn on exponential backk off
617 *
618 * @return the builder
619 */
620 public OnExceptionDefinition useExponentialBackOff() {
621 getOrCreateRedeliveryPolicy().useExponentialBackOff();
622 return this;
623 }
624
625 /**
626 * Sets the maximum delay between redelivery
627 *
628 * @param maximumRedeliveryDelay the delay in millis
629 * @return the builder
630 */
631 public OnExceptionDefinition maximumRedeliveryDelay(long maximumRedeliveryDelay) {
632 getOrCreateRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
633 return this;
634 }
635
636 /**
637 * Sets the maximum delay between redelivery (supports property placeholders)
638 *
639 * @param maximumRedeliveryDelay the delay in millis
640 * @return the builder
641 */
642 public OnExceptionDefinition maximumRedeliveryDelay(String maximumRedeliveryDelay) {
643 getOrCreateRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
644 return this;
645 }
646
647 /**
648 * Sets a reference to a {@link RedeliveryPolicy} to lookup in the {@link org.apache.camel.spi.Registry} to be used.
649 *
650 * @param redeliveryPolicyRef reference to use for lookup
651 * @return the builder
652 */
653 public OnExceptionDefinition redeliveryPolicyRef(String redeliveryPolicyRef) {
654 setRedeliveryPolicyRef(redeliveryPolicyRef);
655 return this;
656 }
657
658 /**
659 * Sets the delay pattern with delay intervals.
660 *
661 * @param delayPattern the delay pattern
662 * @return the builder
663 */
664 public OnExceptionDefinition delayPattern(String delayPattern) {
665 getOrCreateRedeliveryPolicy().setDelayPattern(delayPattern);
666 return this;
667 }
668
669 /**
670 * @deprecated this method will be removed in Camel 3.0, please use {@link #useOriginalMessage()}
671 * @see #useOriginalMessage()
672 */
673 @Deprecated
674 public OnExceptionDefinition useOriginalBody() {
675 setUseOriginalMessagePolicy(Boolean.TRUE);
676 return this;
677 }
678
679 /**
680 * Will use the original input message when an {@link org.apache.camel.Exchange} is moved to the dead letter queue.
681 * <p/>
682 * <b>Notice:</b> this only applies when all redeliveries attempt have failed and the {@link org.apache.camel.Exchange} is doomed for failure.
683 * <br/>
684 * Instead of using the current inprogress {@link org.apache.camel.Exchange} IN body we use the original IN body instead. This allows
685 * you to store the original input in the dead letter queue instead of the inprogress snapshot of the IN body.
686 * For instance if you route transform the IN body during routing and then failed. With the original exchange
687 * store in the dead letter queue it might be easier to manually re submit the {@link org.apache.camel.Exchange} again as the IN body
688 * is the same as when Camel received it. So you should be able to send the {@link org.apache.camel.Exchange} to the same input.
689 * <p/>
690 * By default this feature is off.
691 *
692 * @return the builder
693 */
694 public OnExceptionDefinition useOriginalMessage() {
695 setUseOriginalMessagePolicy(Boolean.TRUE);
696 return this;
697 }
698
699 /**
700 * Sets a processor that should be processed <b>before</b> a redelivery attempt.
701 * <p/>
702 * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b> its being redelivered.
703 */
704 public OnExceptionDefinition onRedelivery(Processor processor) {
705 setOnRedelivery(processor);
706 return this;
707 }
708
709 // Properties
710 //-------------------------------------------------------------------------
711 @Override
712 public List<ProcessorDefinition<?>> getOutputs() {
713 return outputs;
714 }
715
716 public void setOutputs(List<ProcessorDefinition<?>> outputs) {
717 this.outputs = outputs;
718 }
719
720 public boolean isOutputSupported() {
721 return true;
722 }
723
724 public List<Class<? extends Throwable>> getExceptionClasses() {
725 return exceptionClasses;
726 }
727
728 public void setExceptionClasses(List<Class<? extends Throwable>> exceptionClasses) {
729 this.exceptionClasses = exceptionClasses;
730 }
731
732 public List<String> getExceptions() {
733 return exceptions;
734 }
735
736 public void setExceptions(List<String> exceptions) {
737 this.exceptions = exceptions;
738 }
739
740 public Processor getErrorHandler(String routeId) {
741 return errorHandlers.get(routeId);
742 }
743
744 public Collection<Processor> getErrorHandlers() {
745 return errorHandlers.values();
746 }
747
748 public RedeliveryPolicyDefinition getRedeliveryPolicy() {
749 return redeliveryPolicy;
750 }
751
752 public void setRedeliveryPolicy(RedeliveryPolicyDefinition redeliveryPolicy) {
753 this.redeliveryPolicy = redeliveryPolicy;
754 }
755
756 public String getRedeliveryPolicyRef() {
757 return redeliveryPolicyRef;
758 }
759
760 public void setRedeliveryPolicyRef(String redeliveryPolicyRef) {
761 this.redeliveryPolicyRef = redeliveryPolicyRef;
762 }
763
764 public Predicate getHandledPolicy() {
765 return handledPolicy;
766 }
767
768 public void setHandled(ExpressionSubElementDefinition handled) {
769 this.handled = handled;
770 }
771
772 public ExpressionSubElementDefinition getContinued() {
773 return continued;
774 }
775
776 public void setContinued(ExpressionSubElementDefinition continued) {
777 this.continued = continued;
778 }
779
780 public ExpressionSubElementDefinition getHandled() {
781 return handled;
782 }
783
784 public void setHandledPolicy(Predicate handledPolicy) {
785 this.handledPolicy = handledPolicy;
786 }
787
788 public Predicate getContinuedPolicy() {
789 return continuedPolicy;
790 }
791
792 public void setContinuedPolicy(Predicate continuedPolicy) {
793 this.continuedPolicy = continuedPolicy;
794 }
795
796 public WhenDefinition getOnWhen() {
797 return onWhen;
798 }
799
800 public void setOnWhen(WhenDefinition onWhen) {
801 this.onWhen = onWhen;
802 }
803
804 public ExpressionSubElementDefinition getRetryWhile() {
805 return retryWhile;
806 }
807
808 public void setRetryWhile(ExpressionSubElementDefinition retryWhile) {
809 this.retryWhile = retryWhile;
810 }
811
812 public Predicate getRetryWhilePolicy() {
813 return retryWhilePolicy;
814 }
815
816 public void setRetryWhilePolicy(Predicate retryWhilePolicy) {
817 this.retryWhilePolicy = retryWhilePolicy;
818 }
819
820 public Processor getOnRedelivery() {
821 return onRedelivery;
822 }
823
824 public void setOnRedelivery(Processor onRedelivery) {
825 this.onRedelivery = onRedelivery;
826 }
827
828 public String getOnRedeliveryRef() {
829 return onRedeliveryRef;
830 }
831
832 public void setOnRedeliveryRef(String onRedeliveryRef) {
833 this.onRedeliveryRef = onRedeliveryRef;
834 }
835
836 public Boolean getUseOriginalMessagePolicy() {
837 return useOriginalMessagePolicy;
838 }
839
840 public void setUseOriginalMessagePolicy(Boolean useOriginalMessagePolicy) {
841 this.useOriginalMessagePolicy = useOriginalMessagePolicy;
842 }
843
844 public boolean isUseOriginalMessage() {
845 return useOriginalMessagePolicy != null && useOriginalMessagePolicy;
846 }
847
848 public boolean isAsyncDelayedRedelivery(CamelContext context) {
849 if (getRedeliveryPolicy() != null) {
850 return getRedeliveryPolicy().isAsyncDelayedRedelivery(context);
851 }
852 return false;
853 }
854
855 // Implementation methods
856 //-------------------------------------------------------------------------
857
858 protected RedeliveryPolicyDefinition getOrCreateRedeliveryPolicy() {
859 if (redeliveryPolicy == null) {
860 redeliveryPolicy = new RedeliveryPolicyDefinition();
861 }
862 return redeliveryPolicy;
863 }
864
865 protected List<Class<? extends Throwable>> createExceptionClasses(ClassResolver resolver) throws ClassNotFoundException {
866 List<String> list = getExceptions();
867 List<Class<? extends Throwable>> answer = new ArrayList<Class<? extends Throwable>>(list.size());
868 for (String name : list) {
869 Class<? extends Throwable> type = resolver.resolveMandatoryClass(name, Throwable.class);
870 answer.add(type);
871 }
872 return answer;
873 }
874
875 private void setHandledFromExpressionType(RouteContext routeContext) {
876 if (getHandled() != null && handledPolicy == null && routeContext != null) {
877 handled(getHandled().createPredicate(routeContext));
878 }
879 }
880
881 private void setContinuedFromExpressionType(RouteContext routeContext) {
882 if (getContinued() != null && continuedPolicy == null && routeContext != null) {
883 continued(getContinued().createPredicate(routeContext));
884 }
885 }
886
887 private void setRetryWhileFromExpressionType(RouteContext routeContext) {
888 if (getRetryWhile() != null && retryWhilePolicy == null && routeContext != null) {
889 retryWhile(getRetryWhile().createPredicate(routeContext));
890 }
891 }
892
893 private void setOnRedeliveryFromRedeliveryRef(RouteContext routeContext) {
894 // lookup onRedelivery if ref is provided
895 if (ObjectHelper.isNotEmpty(onRedeliveryRef)) {
896 // if ref is provided then use mandatory lookup to fail if not found
897 Processor onRedelivery = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), onRedeliveryRef, Processor.class);
898 setOnRedelivery(onRedelivery);
899 }
900 }
901
902 }