001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.model; 018 019 import java.util.ArrayList; 020 import java.util.Collection; 021 import java.util.List; 022 import java.util.StringTokenizer; 023 import java.util.concurrent.atomic.AtomicBoolean; 024 import javax.xml.bind.annotation.XmlAccessType; 025 import javax.xml.bind.annotation.XmlAccessorType; 026 import javax.xml.bind.annotation.XmlAttribute; 027 import javax.xml.bind.annotation.XmlElementRef; 028 import javax.xml.bind.annotation.XmlRootElement; 029 import javax.xml.bind.annotation.XmlTransient; 030 import javax.xml.bind.annotation.XmlType; 031 032 import org.apache.camel.CamelContext; 033 import org.apache.camel.Endpoint; 034 import org.apache.camel.ErrorHandlerFactory; 035 import org.apache.camel.FailedToCreateRouteException; 036 import org.apache.camel.NoSuchEndpointException; 037 import org.apache.camel.Route; 038 import org.apache.camel.ServiceStatus; 039 import org.apache.camel.ShutdownRoute; 040 import org.apache.camel.ShutdownRunningTask; 041 import org.apache.camel.StatefulService; 042 import org.apache.camel.builder.AdviceWithRouteBuilder; 043 import org.apache.camel.builder.AdviceWithTask; 044 import org.apache.camel.builder.ErrorHandlerBuilderRef; 045 import org.apache.camel.builder.RouteBuilder; 046 import org.apache.camel.impl.DefaultRouteContext; 047 import org.apache.camel.processor.interceptor.HandleFault; 048 import org.apache.camel.spi.LifecycleStrategy; 049 import org.apache.camel.spi.RouteContext; 050 import org.apache.camel.spi.RoutePolicy; 051 import org.apache.camel.util.CamelContextHelper; 052 import org.apache.camel.util.ObjectHelper; 053 054 /** 055 * Represents an XML <route/> element 056 * 057 * @version 058 */ 059 @XmlRootElement(name = "route") 060 @XmlType(propOrder = {"inputs", "outputs"}) 061 @XmlAccessorType(XmlAccessType.PROPERTY) 062 public class RouteDefinition extends ProcessorDefinition<RouteDefinition> { 063 private final AtomicBoolean prepared = new AtomicBoolean(false); 064 private List<FromDefinition> inputs = new ArrayList<FromDefinition>(); 065 private List<ProcessorDefinition<?>> outputs = new ArrayList<ProcessorDefinition<?>>(); 066 private String group; 067 private String streamCache; 068 private String trace; 069 private String messageHistory; 070 private String handleFault; 071 private String delayer; 072 private String autoStartup; 073 private Integer startupOrder; 074 private List<RoutePolicy> routePolicies; 075 private String routePolicyRef; 076 private ShutdownRoute shutdownRoute; 077 private ShutdownRunningTask shutdownRunningTask; 078 private String errorHandlerRef; 079 private ErrorHandlerFactory errorHandlerBuilder; 080 // keep state whether the error handler is context scoped or not 081 // (will by default be context scoped of no explicit error handler configured) 082 private boolean contextScopedErrorHandler = true; 083 084 public RouteDefinition() { 085 } 086 087 public RouteDefinition(String uri) { 088 from(uri); 089 } 090 091 public RouteDefinition(Endpoint endpoint) { 092 from(endpoint); 093 } 094 095 /** 096 * Prepares the route definition to be ready to be added to {@link CamelContext} 097 * 098 * @param context the camel context 099 */ 100 public void prepare(ModelCamelContext context) { 101 if (prepared.compareAndSet(false, true)) { 102 RouteDefinitionHelper.prepareRoute(context, this); 103 } 104 } 105 106 /** 107 * Marks the route definition as prepared. 108 * <p/> 109 * This is needed if routes have been created by components such as 110 * <tt>camel-spring</tt> or <tt>camel-blueprint</tt>. 111 * Usually they share logic in the <tt>camel-core-xml</tt> module which prepares the routes. 112 */ 113 public void markPrepared() { 114 prepared.set(true); 115 } 116 117 @Override 118 public String toString() { 119 if (getId() != null) { 120 return "Route(" + getId() + ")[" + inputs + " -> " + outputs + "]"; 121 } else { 122 return "Route[" + inputs + " -> " + outputs + "]"; 123 } 124 } 125 126 @Override 127 public String getShortName() { 128 return "route"; 129 } 130 131 /** 132 * Returns the status of the route if it has been registered with a {@link CamelContext} 133 */ 134 public ServiceStatus getStatus(CamelContext camelContext) { 135 if (camelContext != null) { 136 ServiceStatus answer = camelContext.getRouteStatus(this.getId()); 137 if (answer == null) { 138 answer = ServiceStatus.Stopped; 139 } 140 return answer; 141 } 142 return null; 143 } 144 145 public boolean isStartable(CamelContext camelContext) { 146 ServiceStatus status = getStatus(camelContext); 147 if (status == null) { 148 return true; 149 } else { 150 return status.isStartable(); 151 } 152 } 153 154 public boolean isStoppable(CamelContext camelContext) { 155 ServiceStatus status = getStatus(camelContext); 156 if (status == null) { 157 return false; 158 } else { 159 return status.isStoppable(); 160 } 161 } 162 163 public List<RouteContext> addRoutes(ModelCamelContext camelContext, Collection<Route> routes) throws Exception { 164 List<RouteContext> answer = new ArrayList<RouteContext>(); 165 166 @SuppressWarnings("deprecation") 167 ErrorHandlerFactory handler = camelContext.getErrorHandlerBuilder(); 168 if (handler != null) { 169 setErrorHandlerBuilderIfNull(handler); 170 } 171 172 for (FromDefinition fromType : inputs) { 173 RouteContext routeContext; 174 try { 175 routeContext = addRoutes(camelContext, routes, fromType); 176 } catch (FailedToCreateRouteException e) { 177 throw e; 178 } catch (Exception e) { 179 // wrap in exception which provide more details about which route was failing 180 throw new FailedToCreateRouteException(getId(), toString(), e); 181 } 182 answer.add(routeContext); 183 } 184 return answer; 185 } 186 187 188 public Endpoint resolveEndpoint(CamelContext camelContext, String uri) throws NoSuchEndpointException { 189 ObjectHelper.notNull(camelContext, "CamelContext"); 190 return CamelContextHelper.getMandatoryEndpoint(camelContext, uri); 191 } 192 193 @Deprecated 194 public RouteDefinition adviceWith(CamelContext camelContext, RouteBuilder builder) throws Exception { 195 return adviceWith((ModelCamelContext)camelContext, builder); 196 } 197 198 /** 199 * Advices this route with the route builder. 200 * <p/> 201 * <b>Important:</b> It is recommended to only advice a given route once (you can of course advice multiple routes). 202 * If you do it multiple times, then it may not work as expected, especially when any kind of error handling is involved. 203 * The Camel team plan for Camel 3.0 to support this as internal refactorings in the routing engine is needed to support this properly. 204 * <p/> 205 * You can use a regular {@link RouteBuilder} but the specialized {@link org.apache.camel.builder.AdviceWithRouteBuilder} 206 * has additional features when using the <a href="http://camel.apache.org/advicewith.html">advice with</a> feature. 207 * We therefore suggest you to use the {@link org.apache.camel.builder.AdviceWithRouteBuilder}. 208 * <p/> 209 * The advice process will add the interceptors, on exceptions, on completions etc. configured 210 * from the route builder to this route. 211 * <p/> 212 * This is mostly used for testing purpose to add interceptors and the likes to an existing route. 213 * <p/> 214 * Will stop and remove the old route from camel context and add and start this new advised route. 215 * 216 * @param camelContext the camel context 217 * @param builder the route builder 218 * @return a new route which is this route merged with the route builder 219 * @throws Exception can be thrown from the route builder 220 * @see AdviceWithRouteBuilder 221 */ 222 @SuppressWarnings("deprecation") 223 public RouteDefinition adviceWith(ModelCamelContext camelContext, RouteBuilder builder) throws Exception { 224 ObjectHelper.notNull(camelContext, "CamelContext"); 225 ObjectHelper.notNull(builder, "RouteBuilder"); 226 227 log.debug("AdviceWith route before: {}", this); 228 229 // inject this route into the advice route builder so it can access this route 230 // and offer features to manipulate the route directly 231 if (builder instanceof AdviceWithRouteBuilder) { 232 ((AdviceWithRouteBuilder) builder).setOriginalRoute(this); 233 } 234 235 // configure and prepare the routes from the builder 236 RoutesDefinition routes = builder.configureRoutes(camelContext); 237 238 log.debug("AdviceWith routes: {}", routes); 239 240 // we can only advice with a route builder without any routes 241 if (!builder.getRouteCollection().getRoutes().isEmpty()) { 242 throw new IllegalArgumentException("You can only advice from a RouteBuilder which has no existing routes." 243 + " Remove all routes from the route builder."); 244 } 245 // we can not advice with error handlers (if you added a new error handler in the route builder) 246 // we must check the error handler on builder is not the same as on camel context, as that would be the default 247 // context scoped error handler, in case no error handlers was configured 248 if (builder.getRouteCollection().getErrorHandlerBuilder() != null 249 && camelContext.getErrorHandlerBuilder() != builder.getRouteCollection().getErrorHandlerBuilder()) { 250 throw new IllegalArgumentException("You can not advice with error handlers. Remove the error handlers from the route builder."); 251 } 252 253 // stop and remove this existing route 254 camelContext.removeRouteDefinition(this); 255 256 // any advice with tasks we should execute first? 257 if (builder instanceof AdviceWithRouteBuilder) { 258 List<AdviceWithTask> tasks = ((AdviceWithRouteBuilder) builder).getAdviceWithTasks(); 259 for (AdviceWithTask task : tasks) { 260 task.task(); 261 } 262 } 263 264 // now merge which also ensures that interceptors and the likes get mixed in correctly as well 265 RouteDefinition merged = routes.route(this); 266 267 // add the new merged route 268 camelContext.getRouteDefinitions().add(0, merged); 269 270 // log the merged route at info level to make it easier to end users to spot any mistakes they may have made 271 log.info("AdviceWith route after: " + merged); 272 273 // If the camel context is started then we start the route 274 if (camelContext instanceof StatefulService) { 275 StatefulService service = (StatefulService) camelContext; 276 if (service.isStarted()) { 277 camelContext.startRoute(merged); 278 } 279 } 280 return merged; 281 } 282 283 // Fluent API 284 // ----------------------------------------------------------------------- 285 286 /** 287 * Creates an input to the route 288 * 289 * @param uri the from uri 290 * @return the builder 291 */ 292 public RouteDefinition from(String uri) { 293 getInputs().add(new FromDefinition(uri)); 294 return this; 295 } 296 297 /** 298 * Creates an input to the route 299 * 300 * @param endpoint the from endpoint 301 * @return the builder 302 */ 303 public RouteDefinition from(Endpoint endpoint) { 304 getInputs().add(new FromDefinition(endpoint)); 305 return this; 306 } 307 308 /** 309 * Creates inputs to the route 310 * 311 * @param uris the from uris 312 * @return the builder 313 */ 314 public RouteDefinition from(String... uris) { 315 for (String uri : uris) { 316 getInputs().add(new FromDefinition(uri)); 317 } 318 return this; 319 } 320 321 /** 322 * Creates inputs to the route 323 * 324 * @param endpoints the from endpoints 325 * @return the builder 326 */ 327 public RouteDefinition from(Endpoint... endpoints) { 328 for (Endpoint endpoint : endpoints) { 329 getInputs().add(new FromDefinition(endpoint)); 330 } 331 return this; 332 } 333 334 /** 335 * Set the group name for this route 336 * 337 * @param name the group name 338 * @return the builder 339 */ 340 public RouteDefinition group(String name) { 341 setGroup(name); 342 return this; 343 } 344 345 /** 346 * Set the route id for this route 347 * 348 * @param id the route id 349 * @return the builder 350 */ 351 public RouteDefinition routeId(String id) { 352 setId(id); 353 return this; 354 } 355 356 /** 357 * Disable stream caching for this route. 358 * 359 * @return the builder 360 */ 361 public RouteDefinition noStreamCaching() { 362 setStreamCache("false"); 363 return this; 364 } 365 366 /** 367 * Enable stream caching for this route. 368 * 369 * @return the builder 370 */ 371 public RouteDefinition streamCaching() { 372 setStreamCache("true"); 373 return this; 374 } 375 376 /** 377 * Disable tracing for this route. 378 * 379 * @return the builder 380 */ 381 public RouteDefinition noTracing() { 382 setTrace("false"); 383 return this; 384 } 385 386 /** 387 * Enable tracing for this route. 388 * 389 * @return the builder 390 */ 391 public RouteDefinition tracing() { 392 setTrace("true"); 393 return this; 394 } 395 396 /** 397 * Enable message history for this route. 398 * 399 * @return the builder 400 */ 401 public RouteDefinition messageHistory() { 402 setMessageHistory("true"); 403 return this; 404 } 405 406 /** 407 * Disable message history for this route. 408 * 409 * @return the builder 410 */ 411 public RouteDefinition noMessageHistory() { 412 setMessageHistory("false"); 413 return this; 414 } 415 416 /** 417 * Disable handle fault for this route. 418 * 419 * @return the builder 420 */ 421 public RouteDefinition noHandleFault() { 422 setHandleFault("false"); 423 return this; 424 } 425 426 /** 427 * Enable handle fault for this route. 428 * 429 * @return the builder 430 */ 431 public RouteDefinition handleFault() { 432 setHandleFault("true"); 433 return this; 434 } 435 436 /** 437 * Disable delayer for this route. 438 * 439 * @return the builder 440 */ 441 public RouteDefinition noDelayer() { 442 setDelayer("0"); 443 return this; 444 } 445 446 /** 447 * Enable delayer for this route. 448 * 449 * @param delay delay in millis 450 * @return the builder 451 */ 452 public RouteDefinition delayer(long delay) { 453 setDelayer("" + delay); 454 return this; 455 } 456 457 /** 458 * Installs the given <a href="http://camel.apache.org/error-handler.html">error handler</a> builder. 459 * 460 * @param errorHandlerBuilder the error handler to be used by default for all child routes 461 * @return the current builder with the error handler configured 462 */ 463 public RouteDefinition errorHandler(ErrorHandlerFactory errorHandlerBuilder) { 464 setErrorHandlerBuilder(errorHandlerBuilder); 465 // we are now using a route scoped error handler 466 contextScopedErrorHandler = false; 467 return this; 468 } 469 470 /** 471 * Disables this route from being auto started when Camel starts. 472 * 473 * @return the builder 474 */ 475 public RouteDefinition noAutoStartup() { 476 setAutoStartup("false"); 477 return this; 478 } 479 480 /** 481 * Sets the auto startup property on this route. 482 * 483 * @param autoStartup - String indicator ("true" or "false") 484 * @return the builder 485 */ 486 public RouteDefinition autoStartup(String autoStartup) { 487 setAutoStartup(autoStartup); 488 return this; 489 } 490 491 /** 492 * Sets the auto startup property on this route. 493 * 494 * @param autoStartup - boolean indicator 495 * @return the builder 496 */ 497 public RouteDefinition autoStartup(boolean autoStartup) { 498 setAutoStartup(Boolean.toString(autoStartup)); 499 return this; 500 } 501 502 /** 503 * Configures the startup order for this route 504 * <p/> 505 * Camel will reorder routes and star them ordered by 0..N where 0 is the lowest number and N the highest number. 506 * Camel will stop routes in reverse order when its stopping. 507 * 508 * @param order the order represented as a number 509 * @return the builder 510 */ 511 public RouteDefinition startupOrder(int order) { 512 setStartupOrder(order); 513 return this; 514 } 515 516 /** 517 * Configures route policies for this route 518 * 519 * @param policies the route policies 520 * @return the builder 521 */ 522 public RouteDefinition routePolicy(RoutePolicy... policies) { 523 if (routePolicies == null) { 524 routePolicies = new ArrayList<RoutePolicy>(); 525 } 526 for (RoutePolicy policy : policies) { 527 routePolicies.add(policy); 528 } 529 return this; 530 } 531 532 /** 533 * Configures a route policy for this route 534 * 535 * @param routePolicyRef reference to a {@link RoutePolicy} to lookup and use. 536 * You can specify multiple references by separating using comma. 537 * @return the builder 538 */ 539 public RouteDefinition routePolicyRef(String routePolicyRef) { 540 setRoutePolicyRef(routePolicyRef); 541 return this; 542 } 543 544 /** 545 * Configures a shutdown route option. 546 * 547 * @param shutdownRoute the option to use when shutting down this route 548 * @return the builder 549 */ 550 public RouteDefinition shutdownRoute(ShutdownRoute shutdownRoute) { 551 setShutdownRoute(shutdownRoute); 552 return this; 553 } 554 555 /** 556 * Configures a shutdown running task option. 557 * 558 * @param shutdownRunningTask the option to use when shutting down and how to act upon running tasks. 559 * @return the builder 560 */ 561 public RouteDefinition shutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 562 setShutdownRunningTask(shutdownRunningTask); 563 return this; 564 } 565 566 // Properties 567 // ----------------------------------------------------------------------- 568 569 public List<FromDefinition> getInputs() { 570 return inputs; 571 } 572 573 @XmlElementRef 574 public void setInputs(List<FromDefinition> inputs) { 575 this.inputs = inputs; 576 } 577 578 public List<ProcessorDefinition<?>> getOutputs() { 579 return outputs; 580 } 581 582 @XmlElementRef 583 public void setOutputs(List<ProcessorDefinition<?>> outputs) { 584 this.outputs = outputs; 585 586 if (outputs != null) { 587 for (ProcessorDefinition<?> output : outputs) { 588 configureChild(output); 589 } 590 } 591 } 592 593 public boolean isOutputSupported() { 594 return true; 595 } 596 597 /** 598 * The group that this route belongs to; could be the name of the RouteBuilder class 599 * or be explicitly configured in the XML. 600 * <p/> 601 * May be null. 602 */ 603 public String getGroup() { 604 return group; 605 } 606 607 @XmlAttribute 608 public void setGroup(String group) { 609 this.group = group; 610 } 611 612 public String getStreamCache() { 613 return streamCache; 614 } 615 616 @XmlAttribute 617 public void setStreamCache(String streamCache) { 618 this.streamCache = streamCache; 619 } 620 621 public String getTrace() { 622 return trace; 623 } 624 625 @XmlAttribute 626 public void setTrace(String trace) { 627 this.trace = trace; 628 } 629 630 public String getMessageHistory() { 631 return messageHistory; 632 } 633 634 @XmlAttribute 635 public void setMessageHistory(String messageHistory) { 636 this.messageHistory = messageHistory; 637 } 638 639 public String getHandleFault() { 640 return handleFault; 641 } 642 643 @XmlAttribute 644 public void setHandleFault(String handleFault) { 645 this.handleFault = handleFault; 646 } 647 648 public String getDelayer() { 649 return delayer; 650 } 651 652 @XmlAttribute 653 public void setDelayer(String delayer) { 654 this.delayer = delayer; 655 } 656 657 public String getAutoStartup() { 658 return autoStartup; 659 } 660 661 public boolean isAutoStartup(CamelContext camelContext) throws Exception { 662 if (getAutoStartup() == null) { 663 // should auto startup by default 664 return true; 665 } 666 Boolean isAutoStartup = CamelContextHelper.parseBoolean(camelContext, getAutoStartup()); 667 return isAutoStartup != null && isAutoStartup; 668 } 669 670 @XmlAttribute 671 public void setAutoStartup(String autoStartup) { 672 this.autoStartup = autoStartup; 673 } 674 675 public Integer getStartupOrder() { 676 return startupOrder; 677 } 678 679 @XmlAttribute 680 public void setStartupOrder(Integer startupOrder) { 681 this.startupOrder = startupOrder; 682 } 683 684 /** 685 * Sets the bean ref name of the error handler builder to use on this route 686 */ 687 @XmlAttribute 688 public void setErrorHandlerRef(String errorHandlerRef) { 689 this.errorHandlerRef = errorHandlerRef; 690 // we use an specific error handler ref (from Spring DSL) then wrap that 691 // with a error handler build ref so Camel knows its not just the default one 692 setErrorHandlerBuilder(new ErrorHandlerBuilderRef(errorHandlerRef)); 693 } 694 695 public String getErrorHandlerRef() { 696 return errorHandlerRef; 697 } 698 699 /** 700 * Sets the error handler if one is not already set 701 */ 702 public void setErrorHandlerBuilderIfNull(ErrorHandlerFactory errorHandlerBuilder) { 703 if (this.errorHandlerBuilder == null) { 704 setErrorHandlerBuilder(errorHandlerBuilder); 705 } 706 } 707 708 @XmlAttribute 709 public void setRoutePolicyRef(String routePolicyRef) { 710 this.routePolicyRef = routePolicyRef; 711 } 712 713 public String getRoutePolicyRef() { 714 return routePolicyRef; 715 } 716 717 public List<RoutePolicy> getRoutePolicies() { 718 return routePolicies; 719 } 720 721 @XmlTransient 722 public void setRoutePolicies(List<RoutePolicy> routePolicies) { 723 this.routePolicies = routePolicies; 724 } 725 726 public ShutdownRoute getShutdownRoute() { 727 return shutdownRoute; 728 } 729 730 @XmlAttribute 731 public void setShutdownRoute(ShutdownRoute shutdownRoute) { 732 this.shutdownRoute = shutdownRoute; 733 } 734 735 public ShutdownRunningTask getShutdownRunningTask() { 736 return shutdownRunningTask; 737 } 738 739 @XmlAttribute 740 public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 741 this.shutdownRunningTask = shutdownRunningTask; 742 } 743 744 private ErrorHandlerFactory createErrorHandlerBuilder() { 745 if (errorHandlerRef != null) { 746 return new ErrorHandlerBuilderRef(errorHandlerRef); 747 } 748 749 // return a reference to the default error handler 750 return new ErrorHandlerBuilderRef(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER); 751 } 752 753 @XmlTransient 754 public ErrorHandlerFactory getErrorHandlerBuilder() { 755 if (errorHandlerBuilder == null) { 756 errorHandlerBuilder = createErrorHandlerBuilder(); 757 } 758 return errorHandlerBuilder; 759 } 760 761 /** 762 * Sets the error handler to use with processors created by this builder 763 */ 764 public void setErrorHandlerBuilder(ErrorHandlerFactory errorHandlerBuilder) { 765 this.errorHandlerBuilder = errorHandlerBuilder; 766 } 767 768 @SuppressWarnings("deprecation") 769 public boolean isContextScopedErrorHandler(CamelContext context) { 770 if (!contextScopedErrorHandler) { 771 return false; 772 } 773 // if error handler ref is configured it may refer to a context scoped, so we need to check this first 774 // the XML DSL will configure error handlers using refs, so we need this additional test 775 if (errorHandlerRef != null) { 776 ErrorHandlerFactory routeScoped = getErrorHandlerBuilder(); 777 ErrorHandlerFactory contextScoped = context.getErrorHandlerBuilder(); 778 return routeScoped != null && contextScoped != null && routeScoped == contextScoped; 779 } 780 781 return contextScopedErrorHandler; 782 } 783 784 // Implementation methods 785 // ------------------------------------------------------------------------- 786 protected RouteContext addRoutes(CamelContext camelContext, Collection<Route> routes, FromDefinition fromType) throws Exception { 787 RouteContext routeContext = new DefaultRouteContext(camelContext, this, fromType, routes); 788 789 // configure tracing 790 if (trace != null) { 791 Boolean isTrace = CamelContextHelper.parseBoolean(camelContext, getTrace()); 792 if (isTrace != null) { 793 routeContext.setTracing(isTrace); 794 if (isTrace) { 795 log.debug("Tracing is enabled on route: {}", getId()); 796 // tracing is added in the DefaultChannel so we can enable it on the fly 797 } 798 } 799 } 800 801 // configure message history 802 if (messageHistory != null) { 803 Boolean isMessageHistory = CamelContextHelper.parseBoolean(camelContext, getMessageHistory()); 804 if (isMessageHistory != null) { 805 routeContext.setMessageHistory(isMessageHistory); 806 if (isMessageHistory) { 807 log.debug("Message history is enabled on route: {}", getId()); 808 } 809 } 810 } 811 812 // configure stream caching 813 if (streamCache != null) { 814 Boolean isStreamCache = CamelContextHelper.parseBoolean(camelContext, getStreamCache()); 815 if (isStreamCache != null) { 816 routeContext.setStreamCaching(isStreamCache); 817 if (isStreamCache) { 818 log.debug("StreamCaching is enabled on route: {}", getId()); 819 } 820 } 821 } 822 823 // configure handle fault 824 if (handleFault != null) { 825 Boolean isHandleFault = CamelContextHelper.parseBoolean(camelContext, getHandleFault()); 826 if (isHandleFault != null) { 827 routeContext.setHandleFault(isHandleFault); 828 if (isHandleFault) { 829 log.debug("HandleFault is enabled on route: {}", getId()); 830 // only add a new handle fault if not already a global configured on camel context 831 if (HandleFault.getHandleFault(camelContext) == null) { 832 addInterceptStrategy(new HandleFault()); 833 } 834 } 835 } 836 } 837 838 // configure delayer 839 if (delayer != null) { 840 Long delayer = CamelContextHelper.parseLong(camelContext, getDelayer()); 841 if (delayer != null) { 842 routeContext.setDelayer(delayer); 843 if (delayer > 0) { 844 log.debug("Delayer is enabled with: {} ms. on route: {}", delayer, getId()); 845 } else { 846 log.debug("Delayer is disabled on route: {}", getId()); 847 } 848 } 849 } 850 851 // configure route policy 852 if (routePolicies != null && !routePolicies.isEmpty()) { 853 for (RoutePolicy policy : routePolicies) { 854 log.debug("RoutePolicy is enabled: {} on route: {}", policy, getId()); 855 routeContext.getRoutePolicyList().add(policy); 856 } 857 } 858 if (routePolicyRef != null) { 859 StringTokenizer policyTokens = new StringTokenizer(routePolicyRef, ","); 860 while (policyTokens.hasMoreTokens()) { 861 String ref = policyTokens.nextToken().trim(); 862 RoutePolicy policy = CamelContextHelper.mandatoryLookup(camelContext, ref, RoutePolicy.class); 863 log.debug("RoutePolicy is enabled: {} on route: {}", policy, getId()); 864 routeContext.getRoutePolicyList().add(policy); 865 } 866 } 867 868 // configure auto startup 869 Boolean isAutoStartup = CamelContextHelper.parseBoolean(camelContext, getAutoStartup()); 870 if (isAutoStartup != null) { 871 log.debug("Using AutoStartup {} on route: {}", isAutoStartup, getId()); 872 routeContext.setAutoStartup(isAutoStartup); 873 } 874 875 // configure shutdown 876 if (shutdownRoute != null) { 877 log.debug("Using ShutdownRoute {} on route: {}", getShutdownRoute(), getId()); 878 routeContext.setShutdownRoute(getShutdownRoute()); 879 } 880 if (shutdownRunningTask != null) { 881 log.debug("Using ShutdownRunningTask {} on route: {}", getShutdownRunningTask(), getId()); 882 routeContext.setShutdownRunningTask(getShutdownRunningTask()); 883 } 884 885 // should inherit the intercept strategies we have defined 886 routeContext.setInterceptStrategies(this.getInterceptStrategies()); 887 // force endpoint resolution 888 routeContext.getEndpoint(); 889 if (camelContext != null) { 890 for (LifecycleStrategy strategy : camelContext.getLifecycleStrategies()) { 891 strategy.onRouteContextCreate(routeContext); 892 } 893 } 894 895 // validate route has output processors 896 if (!ProcessorDefinitionHelper.hasOutputs(outputs, true)) { 897 RouteDefinition route = routeContext.getRoute(); 898 String at = fromType.toString(); 899 Exception cause = new IllegalArgumentException("Route " + route.getId() + " has no output processors." 900 + " You need to add outputs to the route such as to(\"log:foo\")."); 901 throw new FailedToCreateRouteException(route.getId(), route.toString(), at, cause); 902 } 903 904 List<ProcessorDefinition<?>> list = new ArrayList<ProcessorDefinition<?>>(outputs); 905 for (ProcessorDefinition<?> output : list) { 906 try { 907 output.addRoutes(routeContext, routes); 908 } catch (Exception e) { 909 RouteDefinition route = routeContext.getRoute(); 910 throw new FailedToCreateRouteException(route.getId(), route.toString(), output.toString(), e); 911 } 912 } 913 914 routeContext.commit(); 915 return routeContext; 916 } 917 }