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