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