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