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