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