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