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