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