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