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.List; 021import java.util.stream.Collectors; 022 023import javax.xml.bind.annotation.XmlAccessType; 024import javax.xml.bind.annotation.XmlAccessorType; 025import javax.xml.bind.annotation.XmlAttribute; 026import javax.xml.bind.annotation.XmlElement; 027import javax.xml.bind.annotation.XmlElementRef; 028import javax.xml.bind.annotation.XmlRootElement; 029import javax.xml.bind.annotation.XmlTransient; 030 031import org.apache.camel.Expression; 032import org.apache.camel.LoggingLevel; 033import org.apache.camel.Predicate; 034import org.apache.camel.Processor; 035import org.apache.camel.builder.ExpressionBuilder; 036import org.apache.camel.processor.errorhandler.RedeliveryPolicy; 037import org.apache.camel.spi.AsPredicate; 038import org.apache.camel.spi.Metadata; 039import org.apache.camel.support.ExpressionToPredicateAdapter; 040import org.apache.camel.util.ObjectHelper; 041 042/** 043 * Route to be executed when an exception is thrown 044 */ 045@Metadata(label = "error") 046@XmlRootElement(name = "onException") 047@XmlAccessorType(XmlAccessType.FIELD) 048public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefinition> implements OutputNode { 049 @XmlElement(name = "exception", required = true) 050 private List<String> exceptions = new ArrayList<>(); 051 @XmlElement(name = "onWhen") 052 @AsPredicate 053 private WhenDefinition onWhen; 054 @XmlElement(name = "retryWhile") 055 @AsPredicate 056 private ExpressionSubElementDefinition retryWhile; 057 @XmlElement(name = "redeliveryPolicy") 058 private RedeliveryPolicyDefinition redeliveryPolicyType; 059 @XmlAttribute(name = "redeliveryPolicyRef") 060 private String redeliveryPolicyRef; 061 @XmlElement(name = "handled") 062 @AsPredicate 063 private ExpressionSubElementDefinition handled; 064 @XmlElement(name = "continued") 065 @AsPredicate 066 private ExpressionSubElementDefinition continued; 067 @XmlAttribute(name = "onRedeliveryRef") 068 private String onRedeliveryRef; 069 @XmlAttribute(name = "onExceptionOccurredRef") 070 private String onExceptionOccurredRef; 071 @XmlAttribute(name = "useOriginalMessage") 072 private Boolean useOriginalMessagePolicy; 073 @XmlAttribute(name = "useOriginalBody") 074 private Boolean useOriginalBodyPolicy; 075 @XmlElementRef 076 private List<ProcessorDefinition<?>> outputs = new ArrayList<>(); 077 @XmlTransient 078 private Predicate handledPolicy; 079 @XmlTransient 080 private Predicate continuedPolicy; 081 @XmlTransient 082 private Predicate retryWhilePolicy; 083 @XmlTransient 084 private Processor onRedelivery; 085 @XmlTransient 086 private Processor onExceptionOccurred; 087 @XmlTransient 088 private Boolean routeScoped; 089 090 public OnExceptionDefinition() { 091 } 092 093 public OnExceptionDefinition(List<Class<? extends Throwable>> exceptionClasses) { 094 this.exceptions.addAll(exceptionClasses.stream().map(Class::getName).collect(Collectors.toList())); 095 } 096 097 public OnExceptionDefinition(Class<? extends Throwable> exceptionType) { 098 this.exceptions.add(exceptionType.getName()); 099 } 100 101 public void setRouteScoped(boolean routeScoped) { 102 this.routeScoped = routeScoped; 103 } 104 105 public boolean isRouteScoped() { 106 // is context scoped by default 107 return routeScoped != null ? routeScoped : false; 108 } 109 110 public Boolean getRouteScoped() { 111 return routeScoped; 112 } 113 114 @Override 115 public String toString() { 116 return "OnException[" + description() + " -> " + getOutputs() + "]"; 117 } 118 119 protected String description() { 120 return getExceptions() + (onWhen != null ? " " + onWhen : ""); 121 } 122 123 @Override 124 public String getShortName() { 125 return "onException"; 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 @Override 139 public boolean isTopLevelOnly() { 140 return true; 141 } 142 143 public void validateConfiguration() { 144 if (isInheritErrorHandler() != null && isInheritErrorHandler()) { 145 throw new IllegalArgumentException(this + " cannot have the inheritErrorHandler option set to true"); 146 } 147 148 if (exceptions == null || exceptions.isEmpty()) { 149 throw new IllegalArgumentException("At least one exception must be configured on " + this); 150 } 151 152 // only one of handled or continued is allowed 153 if (getHandledPolicy() != null && getContinuedPolicy() != null) { 154 throw new IllegalArgumentException("Only one of handled or continued is allowed to be configured on: " + this); 155 } 156 157 // you cannot turn on both of them 158 if (useOriginalMessagePolicy != null && useOriginalMessagePolicy && useOriginalBodyPolicy != null && useOriginalBodyPolicy) { 159 throw new IllegalArgumentException("Cannot set both useOriginalMessage and useOriginalBody on: " + this); 160 } 161 162 // validate that at least some option is set as you cannot just have 163 // onException(Exception.class); 164 if (outputs == null || getOutputs().isEmpty()) { 165 // no outputs so there should be some sort of configuration 166 ObjectHelper.firstNotNull(handledPolicy, continuedPolicy, retryWhilePolicy, redeliveryPolicyType, useOriginalMessagePolicy, useOriginalBodyPolicy, onRedeliveryRef, 167 onRedelivery, onExceptionOccurred) 168 .orElseThrow(() -> new IllegalArgumentException(this + " is not configured.")); 169 } 170 } 171 172 // Fluent API 173 // ------------------------------------------------------------------------- 174 175 @Override 176 public OnExceptionDefinition onException(Class<? extends Throwable> exceptionType) { 177 getExceptions().add(exceptionType.getName()); 178 return this; 179 } 180 181 /** 182 * Sets whether the exchange should be marked as handled or not. 183 * 184 * @param handled handled or not 185 * @return the builder 186 */ 187 public OnExceptionDefinition handled(boolean handled) { 188 Expression expression = ExpressionBuilder.constantExpression(Boolean.toString(handled)); 189 return handled(expression); 190 } 191 192 /** 193 * Sets whether the exchange should be marked as handled or not. 194 * 195 * @param handled predicate that determines true or false 196 * @return the builder 197 */ 198 public OnExceptionDefinition handled(@AsPredicate Predicate handled) { 199 setHandledPolicy(handled); 200 return this; 201 } 202 203 /** 204 * Sets whether the exchange should be marked as handled or not. 205 * 206 * @param handled expression that determines true or false 207 * @return the builder 208 */ 209 public OnExceptionDefinition handled(@AsPredicate Expression handled) { 210 setHandledPolicy(ExpressionToPredicateAdapter.toPredicate(handled)); 211 return this; 212 } 213 214 /** 215 * Sets whether the exchange should handle and continue routing from the 216 * point of failure. 217 * <p/> 218 * If this option is enabled then its considered handled as well. 219 * 220 * @param continued continued or not 221 * @return the builder 222 */ 223 public OnExceptionDefinition continued(boolean continued) { 224 Expression expression = ExpressionBuilder.constantExpression(Boolean.toString(continued)); 225 return continued(expression); 226 } 227 228 /** 229 * Sets whether the exchange should be marked as handled or not. 230 * <p/> 231 * If this option is enabled then its considered handled as well. 232 * 233 * @param continued predicate that determines true or false 234 * @return the builder 235 */ 236 public OnExceptionDefinition continued(@AsPredicate Predicate continued) { 237 setContinuedPolicy(continued); 238 return this; 239 } 240 241 /** 242 * Sets whether the exchange should be marked as handled or not. 243 * <p/> 244 * If this option is enabled then its considered handled as well. 245 * 246 * @param continued expression that determines true or false 247 * @return the builder 248 */ 249 public OnExceptionDefinition continued(@AsPredicate Expression continued) { 250 setContinuedPolicy(ExpressionToPredicateAdapter.toPredicate(continued)); 251 return this; 252 } 253 254 /** 255 * Sets an additional predicate that should be true before the onException 256 * is triggered. 257 * <p/> 258 * To be used for fine grained controlling whether a thrown exception should 259 * be intercepted by this exception type or not. 260 * 261 * @param predicate predicate that determines true or false 262 * @return the builder 263 */ 264 public OnExceptionDefinition onWhen(@AsPredicate Predicate predicate) { 265 setOnWhen(new WhenDefinition(predicate)); 266 return this; 267 } 268 269 /** 270 * Sets the retry while predicate. 271 * <p/> 272 * Will continue retrying until predicate returns <tt>false</tt>. 273 * 274 * @param retryWhile predicate that determines when to stop retrying 275 * @return the builder 276 */ 277 public OnExceptionDefinition retryWhile(@AsPredicate Predicate retryWhile) { 278 setRetryWhilePolicy(retryWhile); 279 return this; 280 } 281 282 /** 283 * Sets the back off multiplier 284 * 285 * @param backOffMultiplier the back off multiplier 286 * @return the builder 287 */ 288 public OnExceptionDefinition backOffMultiplier(double backOffMultiplier) { 289 getOrCreateRedeliveryPolicy().useExponentialBackOff(); 290 getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier); 291 return this; 292 } 293 294 /** 295 * Sets the back off multiplier (supports property placeholders) 296 * 297 * @param backOffMultiplier the back off multiplier 298 * @return the builder 299 */ 300 public OnExceptionDefinition backOffMultiplier(String backOffMultiplier) { 301 getOrCreateRedeliveryPolicy().useExponentialBackOff(); 302 getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier); 303 return this; 304 } 305 306 /** 307 * Sets the collision avoidance factor 308 * 309 * @param collisionAvoidanceFactor the factor 310 * @return the builder 311 */ 312 public OnExceptionDefinition collisionAvoidanceFactor(double collisionAvoidanceFactor) { 313 getOrCreateRedeliveryPolicy().useCollisionAvoidance(); 314 getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor); 315 return this; 316 } 317 318 /** 319 * Sets the collision avoidance factor (supports property placeholders) 320 * 321 * @param collisionAvoidanceFactor the factor 322 * @return the builder 323 */ 324 public OnExceptionDefinition collisionAvoidanceFactor(String collisionAvoidanceFactor) { 325 getOrCreateRedeliveryPolicy().useCollisionAvoidance(); 326 getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor); 327 return this; 328 } 329 330 /** 331 * Sets the collision avoidance percentage 332 * 333 * @param collisionAvoidancePercent the percentage 334 * @return the builder 335 */ 336 public OnExceptionDefinition collisionAvoidancePercent(double collisionAvoidancePercent) { 337 getOrCreateRedeliveryPolicy().useCollisionAvoidance(); 338 getOrCreateRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent); 339 return this; 340 } 341 342 /** 343 * Sets the initial redelivery delay 344 * 345 * @param delay delay in millis 346 * @return the builder 347 */ 348 public OnExceptionDefinition redeliveryDelay(long delay) { 349 getOrCreateRedeliveryPolicy().redeliveryDelay(delay); 350 return this; 351 } 352 353 /** 354 * Sets the initial redelivery delay (supports property placeholders) 355 * 356 * @param delay delay in millis 357 * @return the builder 358 */ 359 public OnExceptionDefinition redeliveryDelay(String delay) { 360 getOrCreateRedeliveryPolicy().redeliveryDelay(delay); 361 return this; 362 } 363 364 /** 365 * Allow synchronous delayed redelivery. 366 * 367 * @see RedeliveryPolicy#setAsyncDelayedRedelivery(boolean) 368 * @return the builder 369 */ 370 public OnExceptionDefinition asyncDelayedRedelivery() { 371 getOrCreateRedeliveryPolicy().asyncDelayedRedelivery(); 372 return this; 373 } 374 375 /** 376 * Sets the logging level to use when retries has exhausted 377 * 378 * @param retriesExhaustedLogLevel the logging level 379 * @return the builder 380 */ 381 public OnExceptionDefinition retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) { 382 getOrCreateRedeliveryPolicy().retriesExhaustedLogLevel(retriesExhaustedLogLevel); 383 return this; 384 } 385 386 /** 387 * Sets the logging level to use for logging retry attempts 388 * 389 * @param retryAttemptedLogLevel the logging level 390 * @return the builder 391 */ 392 public OnExceptionDefinition retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) { 393 getOrCreateRedeliveryPolicy().retryAttemptedLogLevel(retryAttemptedLogLevel); 394 return this; 395 } 396 397 /** 398 * Sets whether to log stacktrace for failed messages. 399 */ 400 public OnExceptionDefinition logStackTrace(boolean logStackTrace) { 401 getOrCreateRedeliveryPolicy().logStackTrace(logStackTrace); 402 return this; 403 } 404 405 /** 406 * Sets whether to log stacktrace for failed messages (supports property 407 * placeholders) 408 */ 409 public OnExceptionDefinition logStackTrace(String logStackTrace) { 410 getOrCreateRedeliveryPolicy().logStackTrace(logStackTrace); 411 return this; 412 } 413 414 /** 415 * Sets whether to log stacktrace for failed redelivery attempts 416 */ 417 public OnExceptionDefinition logRetryStackTrace(boolean logRetryStackTrace) { 418 getOrCreateRedeliveryPolicy().logRetryStackTrace(logRetryStackTrace); 419 return this; 420 } 421 422 /** 423 * Sets whether to log stacktrace for failed redelivery attempts (supports 424 * property placeholders) 425 */ 426 public OnExceptionDefinition logRetryStackTrace(String logRetryStackTrace) { 427 getOrCreateRedeliveryPolicy().logRetryStackTrace(logRetryStackTrace); 428 return this; 429 } 430 431 /** 432 * Sets whether to log errors even if its handled 433 */ 434 public OnExceptionDefinition logHandled(boolean logHandled) { 435 getOrCreateRedeliveryPolicy().logHandled(logHandled); 436 return this; 437 } 438 439 /** 440 * Sets whether to log errors even if its handled (supports property 441 * placeholders) 442 */ 443 public OnExceptionDefinition logHandled(String logHandled) { 444 getOrCreateRedeliveryPolicy().logHandled(logHandled); 445 return this; 446 } 447 448 /** 449 * Sets whether new exceptions should be logged or not (supports property 450 * placeholders). Can be used to include or reduce verbose. 451 * <p/> 452 * A new exception is an exception that was thrown while handling a previous 453 * exception. 454 */ 455 public OnExceptionDefinition logNewException(boolean logNewException) { 456 getOrCreateRedeliveryPolicy().logNewException(logNewException); 457 return this; 458 } 459 460 /** 461 * Sets whether new exceptions should be logged or not (supports property 462 * placeholders). Can be used to include or reduce verbose. 463 * <p/> 464 * A new exception is an exception that was thrown while handling a previous 465 * exception. 466 */ 467 public OnExceptionDefinition logNewException(String logNewException) { 468 getOrCreateRedeliveryPolicy().logNewException(logNewException); 469 return this; 470 } 471 472 /** 473 * Sets whether to log errors even if its continued 474 */ 475 public OnExceptionDefinition logContinued(boolean logContinued) { 476 getOrCreateRedeliveryPolicy().logContinued(logContinued); 477 return this; 478 } 479 480 /** 481 * Sets whether to log errors even if its continued (supports property 482 * placeholders) 483 */ 484 public OnExceptionDefinition logContinued(String logContinued) { 485 getOrCreateRedeliveryPolicy().logContinued(logContinued); 486 return this; 487 } 488 489 /** 490 * Sets whether to log retry attempts 491 */ 492 public OnExceptionDefinition logRetryAttempted(boolean logRetryAttempted) { 493 getOrCreateRedeliveryPolicy().logRetryAttempted(logRetryAttempted); 494 return this; 495 } 496 497 /** 498 * Sets whether to log retry attempts (supports property placeholders) 499 */ 500 public OnExceptionDefinition logRetryAttempted(String logRetryAttempted) { 501 getOrCreateRedeliveryPolicy().logRetryAttempted(logRetryAttempted); 502 return this; 503 } 504 505 /** 506 * Sets whether to log exhausted exceptions 507 */ 508 public OnExceptionDefinition logExhausted(boolean logExhausted) { 509 getOrCreateRedeliveryPolicy().logExhausted(logExhausted); 510 return this; 511 } 512 513 /** 514 * Sets whether to log exhausted exceptions (supports property placeholders) 515 */ 516 public OnExceptionDefinition logExhausted(String logExhausted) { 517 getOrCreateRedeliveryPolicy().logExhausted(logExhausted); 518 return this; 519 } 520 521 /** 522 * Sets whether to log exhausted exceptions with message history 523 */ 524 public OnExceptionDefinition logExhaustedMessageHistory(boolean logExhaustedMessageHistory) { 525 getOrCreateRedeliveryPolicy().logExhaustedMessageHistory(logExhaustedMessageHistory); 526 return this; 527 } 528 529 /** 530 * Sets whether to log exhausted exceptions with message history 531 */ 532 public OnExceptionDefinition logExhaustedMessageHistory(String logExhaustedMessageHistory) { 533 getOrCreateRedeliveryPolicy().logExhaustedMessageHistory(logExhaustedMessageHistory); 534 return this; 535 } 536 537 /** 538 * Sets whether to log exhausted message body with message history. Requires 539 * <tt>logExhaustedMessageHistory</tt> to be enabled. 540 */ 541 public OnExceptionDefinition logExhaustedMessageBody(boolean logExhaustedMessageBody) { 542 getOrCreateRedeliveryPolicy().logExhaustedMessageBody(logExhaustedMessageBody); 543 return this; 544 } 545 546 /** 547 * Sets whether to log exhausted message body with message history. Requires 548 * <tt>logExhaustedMessageHistory</tt> to be enabled. 549 */ 550 public OnExceptionDefinition logExhaustedMessageBody(String logExhaustedMessageBody) { 551 getOrCreateRedeliveryPolicy().logExhaustedMessageBody(logExhaustedMessageBody); 552 return this; 553 } 554 555 /** 556 * Sets the maximum redeliveries 557 * <ul> 558 * <li>5 = default value</li> 559 * <li>0 = no redeliveries</li> 560 * <li>-1 = redeliver forever</li> 561 * </ul> 562 * 563 * @param maximumRedeliveries the value 564 * @return the builder 565 */ 566 public OnExceptionDefinition maximumRedeliveries(int maximumRedeliveries) { 567 getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries); 568 return this; 569 } 570 571 /** 572 * Sets the maximum redeliveries (supports property placeholders) 573 * <ul> 574 * <li>5 = default value</li> 575 * <li>0 = no redeliveries</li> 576 * <li>-1 = redeliver forever</li> 577 * </ul> 578 * 579 * @param maximumRedeliveries the value 580 * @return the builder 581 */ 582 public OnExceptionDefinition maximumRedeliveries(String maximumRedeliveries) { 583 getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries); 584 return this; 585 } 586 587 /** 588 * Turn on collision avoidance. 589 * 590 * @return the builder 591 */ 592 public OnExceptionDefinition useCollisionAvoidance() { 593 getOrCreateRedeliveryPolicy().useCollisionAvoidance(); 594 return this; 595 } 596 597 /** 598 * Turn on exponential back off 599 * 600 * @return the builder 601 */ 602 public OnExceptionDefinition useExponentialBackOff() { 603 getOrCreateRedeliveryPolicy().useExponentialBackOff(); 604 return this; 605 } 606 607 /** 608 * Sets the maximum delay between redelivery 609 * 610 * @param maximumRedeliveryDelay the delay in millis 611 * @return the builder 612 */ 613 public OnExceptionDefinition maximumRedeliveryDelay(long maximumRedeliveryDelay) { 614 getOrCreateRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay); 615 return this; 616 } 617 618 /** 619 * Sets the maximum delay between redelivery (supports property 620 * placeholders) 621 * 622 * @param maximumRedeliveryDelay the delay in millis 623 * @return the builder 624 */ 625 public OnExceptionDefinition maximumRedeliveryDelay(String maximumRedeliveryDelay) { 626 getOrCreateRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay); 627 return this; 628 } 629 630 /** 631 * Sets a reference to a {@link RedeliveryPolicy} to lookup in the 632 * {@link org.apache.camel.spi.Registry} to be used. 633 * 634 * @param redeliveryPolicyRef reference to use for lookup 635 * @return the builder 636 */ 637 public OnExceptionDefinition redeliveryPolicyRef(String redeliveryPolicyRef) { 638 setRedeliveryPolicyRef(redeliveryPolicyRef); 639 return this; 640 } 641 642 /** 643 * Sets the delay pattern with delay intervals. 644 * 645 * @param delayPattern the delay pattern 646 * @return the builder 647 */ 648 public OnExceptionDefinition delayPattern(String delayPattern) { 649 getOrCreateRedeliveryPolicy().setDelayPattern(delayPattern); 650 return this; 651 } 652 653 /** 654 * Will use the original input {@link org.apache.camel.Message} (original 655 * body and headers) when an {@link org.apache.camel.Exchange} is moved to 656 * the dead letter queue. 657 * <p/> 658 * <b>Notice:</b> this only applies when all redeliveries attempt have 659 * failed and the {@link org.apache.camel.Exchange} is doomed for failure. 660 * <br/> 661 * Instead of using the current inprogress {@link org.apache.camel.Exchange} 662 * IN message we use the original IN message instead. This allows you to 663 * store the original input in the dead letter queue instead of the 664 * inprogress snapshot of the IN message. For instance if you route 665 * transform the IN body during routing and then failed. With the original 666 * exchange store in the dead letter queue it might be easier to manually re 667 * submit the {@link org.apache.camel.Exchange} again as the IN message is 668 * the same as when Camel received it. So you should be able to send the 669 * {@link org.apache.camel.Exchange} to the same input. 670 * <p/> 671 * The difference between useOriginalMessage and useOriginalBody is that the 672 * former includes both the original body and headers, where as the latter 673 * only includes the original body. You can use the latter to enrich the 674 * message with custom headers and include the original message body. The 675 * former wont let you do this, as its using the original message body and 676 * headers as they are. You cannot enable both useOriginalMessage and 677 * useOriginalBody. 678 * <p/> 679 * <b>Important:</b> The original input means the input message that are 680 * bounded by the current {@link org.apache.camel.spi.UnitOfWork}. An unit 681 * of work typically spans one route, or multiple routes if they are 682 * connected using internal endpoints such as direct or seda. When messages 683 * is passed via external endpoints such as JMS or HTTP then the consumer 684 * will create a new unit of work, with the message it received as input as 685 * the original input. Also some EIP patterns such as splitter, multicast, 686 * will create a new unit of work boundary for the messages in their 687 * sub-route (eg the splitted message); however these EIPs have an option 688 * named <tt>shareUnitOfWork</tt> which allows to combine with the parent 689 * unit of work in regard to error handling and therefore use the parent 690 * original message. 691 * <p/> 692 * By default this feature is off. 693 * 694 * @return the builder 695 * @see #useOriginalBody() 696 */ 697 public OnExceptionDefinition useOriginalMessage() { 698 setUseOriginalMessagePolicy(Boolean.TRUE); 699 return this; 700 } 701 702 /** 703 * Will use the original input {@link org.apache.camel.Message} body 704 * (original body only) when an {@link org.apache.camel.Exchange} is moved 705 * to the dead letter queue. 706 * <p/> 707 * <b>Notice:</b> this only applies when all redeliveries attempt have 708 * failed and the {@link org.apache.camel.Exchange} is doomed for failure. 709 * <br/> 710 * Instead of using the current inprogress {@link org.apache.camel.Exchange} 711 * IN message we use the original IN message instead. This allows you to 712 * store the original input in the dead letter queue instead of the 713 * inprogress snapshot of the IN message. For instance if you route 714 * transform the IN body during routing and then failed. With the original 715 * exchange store in the dead letter queue it might be easier to manually re 716 * submit the {@link org.apache.camel.Exchange} again as the IN message is 717 * the same as when Camel received it. So you should be able to send the 718 * {@link org.apache.camel.Exchange} to the same input. 719 * <p/> 720 * The difference between useOriginalMessage and useOriginalBody is that the 721 * former includes both the original body and headers, where as the latter 722 * only includes the original body. You can use the latter to enrich the 723 * message with custom headers and include the original message body. The 724 * former wont let you do this, as its using the original message body and 725 * headers as they are. You cannot enable both useOriginalMessage and 726 * useOriginalBody. 727 * <p/> 728 * <b>Important:</b> The original input means the input message that are 729 * bounded by the current {@link org.apache.camel.spi.UnitOfWork}. An unit 730 * of work typically spans one route, or multiple routes if they are 731 * connected using internal endpoints such as direct or seda. When messages 732 * is passed via external endpoints such as JMS or HTTP then the consumer 733 * will create a new unit of work, with the message it received as input as 734 * the original input. Also some EIP patterns such as splitter, multicast, 735 * will create a new unit of work boundary for the messages in their 736 * sub-route (eg the splitted message); however these EIPs have an option 737 * named <tt>shareUnitOfWork</tt> which allows to combine with the parent 738 * unit of work in regard to error handling and therefore use the parent 739 * original message. 740 * <p/> 741 * By default this feature is off. 742 * 743 * @return the builder 744 * @see #useOriginalMessage() 745 */ 746 public OnExceptionDefinition useOriginalBody() { 747 setUseOriginalBodyPolicy(Boolean.TRUE); 748 return this; 749 } 750 751 /** 752 * Sets a processor that should be processed <b>before</b> a redelivery 753 * attempt. 754 * <p/> 755 * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b> 756 * its being redelivered. 757 */ 758 public OnExceptionDefinition onRedelivery(Processor processor) { 759 setOnRedelivery(processor); 760 return this; 761 } 762 763 /** 764 * Sets a reference to a processor that should be processed <b>before</b> a 765 * redelivery attempt. 766 * <p/> 767 * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b> 768 * its being redelivered. 769 * 770 * @param ref reference to the processor 771 */ 772 public OnExceptionDefinition onRedeliveryRef(String ref) { 773 setOnRedeliveryRef(ref); 774 return this; 775 } 776 777 /** 778 * Sets a processor that should be processed <b>just after</b> an exception 779 * occurred. Can be used to perform custom logging about the occurred 780 * exception at the exact time it happened. 781 * <p/> 782 * Important: Any exception thrown from this processor will be ignored. 783 */ 784 public OnExceptionDefinition onExceptionOccurred(Processor processor) { 785 setOnExceptionOccurred(processor); 786 return this; 787 } 788 789 /** 790 * Sets a reference to a processor that should be processed <b>just 791 * after</b> an exception occurred. Can be used to perform custom logging 792 * about the occurred exception at the exact time it happened. 793 * <p/> 794 * Important: Any exception thrown from this processor will be ignored. 795 * 796 * @param ref reference to the processor 797 */ 798 public OnExceptionDefinition onExceptionOccurredRef(String ref) { 799 setOnExceptionOccurredRef(ref); 800 return this; 801 } 802 803 // Properties 804 // ------------------------------------------------------------------------- 805 @Override 806 public List<ProcessorDefinition<?>> getOutputs() { 807 return outputs; 808 } 809 810 public void setOutputs(List<ProcessorDefinition<?>> outputs) { 811 this.outputs = outputs; 812 } 813 814 public List<String> getExceptions() { 815 return exceptions; 816 } 817 818 /** 819 * A set of exceptions to react upon. 820 */ 821 public void setExceptions(List<String> exceptions) { 822 this.exceptions = exceptions; 823 } 824 825 public RedeliveryPolicyDefinition getRedeliveryPolicyType() { 826 return redeliveryPolicyType; 827 } 828 829 /** 830 * Used for configuring redelivery options 831 */ 832 public void setRedeliveryPolicyType(RedeliveryPolicyDefinition redeliveryPolicyType) { 833 this.redeliveryPolicyType = redeliveryPolicyType; 834 } 835 836 public String getRedeliveryPolicyRef() { 837 return redeliveryPolicyRef; 838 } 839 840 public void setRedeliveryPolicyRef(String redeliveryPolicyRef) { 841 this.redeliveryPolicyRef = redeliveryPolicyRef; 842 } 843 844 public Predicate getHandledPolicy() { 845 return handledPolicy; 846 } 847 848 public void setHandled(ExpressionSubElementDefinition handled) { 849 this.handled = handled; 850 } 851 852 public ExpressionSubElementDefinition getContinued() { 853 return continued; 854 } 855 856 public void setContinued(ExpressionSubElementDefinition continued) { 857 this.continued = continued; 858 } 859 860 public ExpressionSubElementDefinition getHandled() { 861 return handled; 862 } 863 864 public void setHandledPolicy(Predicate handledPolicy) { 865 this.handledPolicy = handledPolicy; 866 } 867 868 public Predicate getContinuedPolicy() { 869 return continuedPolicy; 870 } 871 872 public void setContinuedPolicy(Predicate continuedPolicy) { 873 this.continuedPolicy = continuedPolicy; 874 } 875 876 public WhenDefinition getOnWhen() { 877 return onWhen; 878 } 879 880 public void setOnWhen(WhenDefinition onWhen) { 881 this.onWhen = onWhen; 882 } 883 884 public ExpressionSubElementDefinition getRetryWhile() { 885 return retryWhile; 886 } 887 888 public void setRetryWhile(ExpressionSubElementDefinition retryWhile) { 889 this.retryWhile = retryWhile; 890 } 891 892 public Predicate getRetryWhilePolicy() { 893 return retryWhilePolicy; 894 } 895 896 public void setRetryWhilePolicy(Predicate retryWhilePolicy) { 897 this.retryWhilePolicy = retryWhilePolicy; 898 } 899 900 public Processor getOnRedelivery() { 901 return onRedelivery; 902 } 903 904 public void setOnRedelivery(Processor onRedelivery) { 905 this.onRedelivery = onRedelivery; 906 } 907 908 public String getOnRedeliveryRef() { 909 return onRedeliveryRef; 910 } 911 912 public void setOnRedeliveryRef(String onRedeliveryRef) { 913 this.onRedeliveryRef = onRedeliveryRef; 914 } 915 916 public Processor getOnExceptionOccurred() { 917 return onExceptionOccurred; 918 } 919 920 public void setOnExceptionOccurred(Processor onExceptionOccurred) { 921 this.onExceptionOccurred = onExceptionOccurred; 922 } 923 924 public String getOnExceptionOccurredRef() { 925 return onExceptionOccurredRef; 926 } 927 928 public void setOnExceptionOccurredRef(String onExceptionOccurredRef) { 929 this.onExceptionOccurredRef = onExceptionOccurredRef; 930 } 931 932 public Boolean getUseOriginalMessagePolicy() { 933 return useOriginalMessagePolicy; 934 } 935 936 public void setUseOriginalMessagePolicy(Boolean useOriginalMessagePolicy) { 937 this.useOriginalMessagePolicy = useOriginalMessagePolicy; 938 } 939 940 public Boolean getUseOriginalBodyPolicy() { 941 return useOriginalBodyPolicy; 942 } 943 944 public void setUseOriginalBodyPolicy(Boolean useOriginalBodyPolicy) { 945 this.useOriginalBodyPolicy = useOriginalBodyPolicy; 946 } 947 948 // Implementation methods 949 // ------------------------------------------------------------------------- 950 951 protected RedeliveryPolicyDefinition getOrCreateRedeliveryPolicy() { 952 if (redeliveryPolicyType == null) { 953 redeliveryPolicyType = new RedeliveryPolicyDefinition(); 954 } 955 return redeliveryPolicyType; 956 } 957 958}