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.spring; 018 019 import java.util.ArrayList; 020 import java.util.List; 021 import javax.xml.bind.annotation.XmlAccessType; 022 import javax.xml.bind.annotation.XmlAccessorType; 023 import javax.xml.bind.annotation.XmlAttribute; 024 import javax.xml.bind.annotation.XmlElement; 025 import javax.xml.bind.annotation.XmlElements; 026 import javax.xml.bind.annotation.XmlRootElement; 027 import javax.xml.bind.annotation.XmlTransient; 028 029 import org.apache.camel.CamelException; 030 import org.apache.camel.Routes; 031 import org.apache.camel.builder.ErrorHandlerBuilder; 032 import org.apache.camel.builder.RouteBuilder; 033 import org.apache.camel.impl.DefaultLifecycleStrategy; 034 import org.apache.camel.management.DefaultInstrumentationAgent; 035 import org.apache.camel.management.InstrumentationLifecycleStrategy; 036 import org.apache.camel.model.FromDefinition; 037 import org.apache.camel.model.IdentifiedType; 038 import org.apache.camel.model.InterceptDefinition; 039 import org.apache.camel.model.InterceptFromDefinition; 040 import org.apache.camel.model.InterceptSendToEndpointDefinition; 041 import org.apache.camel.model.OnCompletionDefinition; 042 import org.apache.camel.model.OnExceptionDefinition; 043 import org.apache.camel.model.PolicyDefinition; 044 import org.apache.camel.model.ProcessorDefinition; 045 import org.apache.camel.model.RouteBuilderDefinition; 046 import org.apache.camel.model.RouteContainer; 047 import org.apache.camel.model.RouteDefinition; 048 import org.apache.camel.model.TransactedDefinition; 049 import org.apache.camel.model.config.PropertiesDefinition; 050 import org.apache.camel.model.dataformat.DataFormatsDefinition; 051 import org.apache.camel.processor.interceptor.Debugger; 052 import org.apache.camel.processor.interceptor.Delayer; 053 import org.apache.camel.processor.interceptor.HandleFault; 054 import org.apache.camel.processor.interceptor.TraceFormatter; 055 import org.apache.camel.processor.interceptor.Tracer; 056 import org.apache.camel.spi.ClassResolver; 057 import org.apache.camel.spi.FactoryFinderResolver; 058 import org.apache.camel.spi.LifecycleStrategy; 059 import org.apache.camel.spi.PackageScanClassResolver; 060 import org.apache.camel.spi.Registry; 061 import org.apache.camel.util.EndpointHelper; 062 import org.apache.camel.util.ObjectHelper; 063 import org.apache.commons.logging.Log; 064 import org.apache.commons.logging.LogFactory; 065 import org.springframework.beans.factory.DisposableBean; 066 import org.springframework.beans.factory.FactoryBean; 067 import org.springframework.beans.factory.InitializingBean; 068 import org.springframework.beans.factory.config.BeanPostProcessor; 069 import org.springframework.context.ApplicationContext; 070 import org.springframework.context.ApplicationContextAware; 071 import org.springframework.context.ApplicationEvent; 072 import org.springframework.context.ApplicationListener; 073 import org.springframework.context.event.ContextRefreshedEvent; 074 import static org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException; 075 076 /** 077 * A Spring {@link FactoryBean} to create and initialize a 078 * {@link SpringCamelContext} and install routes either explicitly configured in 079 * Spring XML or found by searching the classpath for Java classes which extend 080 * {@link RouteBuilder} using the nested {@link #setPackages(String[])}. 081 * 082 * @version $Revision: 781349 $ 083 */ 084 @XmlRootElement(name = "camelContext") 085 @XmlAccessorType(XmlAccessType.FIELD) 086 public class CamelContextFactoryBean extends IdentifiedType implements RouteContainer, FactoryBean, InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener { 087 private static final Log LOG = LogFactory.getLog(CamelContextFactoryBean.class); 088 089 @XmlAttribute(required = false) 090 private Boolean trace; 091 @XmlAttribute(required = false) 092 private Boolean streamCache = Boolean.TRUE; 093 @XmlAttribute(required = false) 094 private Long delay; 095 @XmlAttribute(required = false) 096 private Boolean handleFault; 097 @XmlAttribute(required = false) 098 private String errorHandlerRef; 099 @XmlAttribute(required = false) 100 private Boolean shouldStartContext = Boolean.TRUE; 101 @XmlElement(name = "properties", required = false) 102 private PropertiesDefinition properties; 103 @XmlElement(name = "package", required = false) 104 private String[] packages = {}; 105 @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class, required = false) 106 private CamelJMXAgentDefinition camelJMXAgent; 107 @XmlElements({ 108 @XmlElement(name = "beanPostProcessor", type = CamelBeanPostProcessor.class, required = false), 109 @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false), 110 @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class, required = false), 111 @XmlElement(name = "proxy", type = CamelProxyFactoryDefinition.class, required = false), 112 @XmlElement(name = "export", type = CamelServiceExporterDefinition.class, required = false)}) 113 private List beans; 114 @XmlElement(name = "routeBuilder", required = false) 115 private List<RouteBuilderDefinition> builderRefs = new ArrayList<RouteBuilderDefinition>(); 116 @XmlElement(name = "endpoint", required = false) 117 private List<CamelEndpointFactoryBean> endpoints; 118 @XmlElement(name = "dataFormats", required = false) 119 private DataFormatsDefinition dataFormats; 120 @XmlElement(name = "onException", required = false) 121 private List<OnExceptionDefinition> onExceptions = new ArrayList<OnExceptionDefinition>(); 122 @XmlElement(name = "onCompletion", required = false) 123 private List<OnCompletionDefinition> onCompletions = new ArrayList<OnCompletionDefinition>(); 124 @XmlElement(name = "intercept", required = false) 125 private List<InterceptDefinition> intercepts = new ArrayList<InterceptDefinition>(); 126 @XmlElement(name = "interceptFrom", required = false) 127 private List<InterceptFromDefinition> interceptFroms = new ArrayList<InterceptFromDefinition>(); 128 @XmlElement(name = "interceptSendToEndpoint", required = false) 129 private List<InterceptSendToEndpointDefinition> interceptSendToEndpoints = new ArrayList<InterceptSendToEndpointDefinition>(); 130 @XmlElement(name = "route", required = false) 131 private List<RouteDefinition> routes = new ArrayList<RouteDefinition>(); 132 @XmlTransient 133 private SpringCamelContext context; 134 @XmlTransient 135 private RouteBuilder routeBuilder; 136 @XmlTransient 137 private List<Routes> additionalBuilders = new ArrayList<Routes>(); 138 @XmlTransient 139 private ApplicationContext applicationContext; 140 @XmlTransient 141 private ClassLoader contextClassLoaderOnStart; 142 @XmlTransient 143 private BeanPostProcessor beanPostProcessor; 144 145 public CamelContextFactoryBean() { 146 // Lets keep track of the class loader for when we actually do start things up 147 contextClassLoaderOnStart = Thread.currentThread().getContextClassLoader(); 148 } 149 150 public Object getObject() throws Exception { 151 return getContext(); 152 } 153 154 public Class getObjectType() { 155 return SpringCamelContext.class; 156 } 157 158 public boolean isSingleton() { 159 return true; 160 } 161 162 public ClassLoader getContextClassLoaderOnStart() { 163 return contextClassLoaderOnStart; 164 } 165 166 public List<Routes> getAdditionalBuilders() { 167 return additionalBuilders; 168 } 169 170 public void afterPropertiesSet() throws Exception { 171 if (properties != null) { 172 getContext().setProperties(properties.asMap()); 173 } 174 // set the resolvers first 175 PackageScanClassResolver packageResolver = getBeanForType(PackageScanClassResolver.class); 176 if (packageResolver != null) { 177 getContext().setPackageScanClassResolver(packageResolver); 178 } 179 ClassResolver classResolver = getBeanForType(ClassResolver.class); 180 if (classResolver != null) { 181 getContext().setClassResolver(classResolver); 182 } 183 FactoryFinderResolver factoryFinderResolver = getBeanForType(FactoryFinderResolver.class); 184 if (factoryFinderResolver != null) { 185 getContext().setFactoryFinderResolver(factoryFinderResolver); 186 } 187 188 Debugger debugger = getBeanForType(Debugger.class); 189 if (debugger != null) { 190 getContext().addInterceptStrategy(debugger); 191 } 192 193 Tracer tracer = getBeanForType(Tracer.class); 194 if (tracer != null) { 195 // use formatter if there is a TraceFormatter bean defined 196 TraceFormatter formatter = getBeanForType(TraceFormatter.class); 197 if (formatter != null) { 198 tracer.setFormatter(formatter); 199 } 200 getContext().addInterceptStrategy(tracer); 201 } 202 203 HandleFault handleFault = getBeanForType(HandleFault.class); 204 if (handleFault != null) { 205 getContext().addInterceptStrategy(handleFault); 206 } 207 208 Delayer delayer = getBeanForType(Delayer.class); 209 if (delayer != null) { 210 getContext().addInterceptStrategy(delayer); 211 } 212 213 // set the lifecycle strategy if defined 214 LifecycleStrategy lifecycleStrategy = getBeanForType(LifecycleStrategy.class); 215 if (lifecycleStrategy != null) { 216 getContext().setLifecycleStrategy(lifecycleStrategy); 217 } 218 219 // set the strategy if defined 220 Registry registry = getBeanForType(Registry.class); 221 if (registry != null) { 222 getContext().setRegistry(registry); 223 } 224 225 // Set the application context and camelContext for the beanPostProcessor 226 if (beanPostProcessor != null) { 227 if (beanPostProcessor instanceof ApplicationContextAware) { 228 ((ApplicationContextAware)beanPostProcessor).setApplicationContext(applicationContext); 229 } 230 if (beanPostProcessor instanceof CamelBeanPostProcessor) { 231 ((CamelBeanPostProcessor)beanPostProcessor).setCamelContext(getContext()); 232 } 233 } 234 235 // do special preparation for some concepts such as interceptors and policies 236 // this is needed as JAXB does not build excaclty the same model definition as Spring DSL would do 237 // using route builders. So we have here a little custom code to fix the JAXB gaps 238 for (RouteDefinition route : routes) { 239 // interceptors should be first 240 initInterceptors(route); 241 // then on completion 242 initOnCompletions(route); 243 // then polices 244 initPolicies(route); 245 // and last on exception 246 initOnExceptions(route); 247 } 248 249 if (dataFormats != null) { 250 getContext().setDataFormats(dataFormats.asMap()); 251 } 252 253 // lets force any lazy creation 254 getContext().addRouteDefinitions(routes); 255 256 // setup JMX agent 257 initJMXAgent(); 258 259 if (LOG.isDebugEnabled()) { 260 LOG.debug("Found JAXB created routes: " + getRoutes()); 261 } 262 findRouteBuilders(); 263 installRoutes(); 264 } 265 266 private void initOnExceptions(RouteDefinition route) { 267 List<ProcessorDefinition<?>> outputs = new ArrayList<ProcessorDefinition<?>>(); 268 List<ProcessorDefinition<?>> exceptionHandlers = new ArrayList<ProcessorDefinition<?>>(); 269 270 // add global on exceptions if any 271 if (onExceptions != null && !onExceptions.isEmpty()) { 272 // on exceptions must be added at top, so the route flow is correct as 273 // on exceptions should be the first outputs 274 route.getOutputs().addAll(0, onExceptions); 275 } 276 277 for (ProcessorDefinition output : route.getOutputs()) { 278 // split into on exception and regular outputs 279 if (output instanceof OnExceptionDefinition) { 280 exceptionHandlers.add(output); 281 } else { 282 outputs.add(output); 283 } 284 } 285 286 // clearing the outputs 287 route.clearOutput(); 288 289 // add exception handlers as top children 290 route.getOutputs().addAll(exceptionHandlers); 291 292 // and the remaining outputs 293 route.getOutputs().addAll(outputs); 294 } 295 296 private void initInterceptors(RouteDefinition route) { 297 298 // configure intercept 299 for (InterceptDefinition intercept : getIntercepts()) { 300 intercept.afterPropertiesSet(); 301 // add as first output so intercept is handled before the acutal route and that gives 302 // us the needed head start to init and be able to intercept all the remaining processing steps 303 route.getOutputs().add(0, intercept); 304 } 305 306 // configure intercept from 307 for (InterceptFromDefinition intercept : getInterceptFroms()) { 308 309 // should we only apply interceptor for a given endpoint uri 310 boolean match = true; 311 if (intercept.getUri() != null) { 312 match = false; 313 for (FromDefinition input : route.getInputs()) { 314 if (EndpointHelper.matchEndpoint(input.getUri(), intercept.getUri())) { 315 match = true; 316 break; 317 } 318 } 319 } 320 321 if (match) { 322 intercept.afterPropertiesSet(); 323 // add as first output so intercept is handled before the acutal route and that gives 324 // us the needed head start to init and be able to intercept all the remaining processing steps 325 route.getOutputs().add(0, intercept); 326 } 327 } 328 329 // configure intercept send to endpoint 330 for (InterceptSendToEndpointDefinition intercept : getInterceptSendToEndpoints()) { 331 intercept.afterPropertiesSet(); 332 // add as first output so intercept is handled before the acutal route and that gives 333 // us the needed head start to init and be able to intercept all the remaining processing steps 334 route.getOutputs().add(0, intercept); 335 } 336 337 } 338 339 private void initOnCompletions(RouteDefinition route) { 340 // only add global onCompletion if there are no route alredy 341 boolean hasRouteScope = false; 342 for (ProcessorDefinition out : route.getOutputs()) { 343 if (out instanceof OnCompletionDefinition) { 344 hasRouteScope = true; 345 break; 346 } 347 } 348 // only add global onCompletion if we do *not* have any route onCompletion defined in the route 349 // add onCompletion *after* intercept, as its important intercept is first 350 if (!hasRouteScope) { 351 int index = 0; 352 for (int i = 0; i < route.getOutputs().size(); i++) { 353 index = i; 354 ProcessorDefinition out = route.getOutputs().get(i); 355 if (!(out instanceof InterceptDefinition)) { 356 break; 357 } 358 } 359 route.getOutputs().addAll(index, getOnCompletions()); 360 } 361 } 362 363 private void initPolicies(RouteDefinition route) { 364 // setup the policies as JAXB yet again have not created a correct model for us 365 List<ProcessorDefinition> types = route.getOutputs(); 366 // we need to types as transacted cannot extend policy due JAXB limitations 367 PolicyDefinition policy = null; 368 TransactedDefinition transacted = null; 369 for (ProcessorDefinition type : types) { 370 if (type instanceof PolicyDefinition) { 371 policy = (PolicyDefinition) type; 372 } else if (type instanceof TransactedDefinition) { 373 transacted = (TransactedDefinition) type; 374 } else if (policy != null) { 375 // the outputs should be moved to the policy 376 policy.addOutput(type); 377 } else if (transacted != null) { 378 // the outputs should be moved to the transacted policy 379 transacted.addOutput(type); 380 } 381 } 382 // did we find a policy if so replace it as the only output on the route 383 if (policy != null) { 384 route.clearOutput(); 385 route.addOutput(policy); 386 } else if (transacted != null) { 387 route.clearOutput(); 388 route.addOutput(transacted); 389 } 390 } 391 392 private void initJMXAgent() throws Exception { 393 if (camelJMXAgent != null && camelJMXAgent.isDisabled()) { 394 LOG.info("JMXAgent disabled"); 395 getContext().setLifecycleStrategy(new DefaultLifecycleStrategy()); 396 } else if (camelJMXAgent != null) { 397 DefaultInstrumentationAgent agent = new DefaultInstrumentationAgent(); 398 agent.setConnectorPort(camelJMXAgent.getConnectorPort()); 399 agent.setCreateConnector(camelJMXAgent.isCreateConnector()); 400 agent.setMBeanObjectDomainName(camelJMXAgent.getMbeanObjectDomainName()); 401 agent.setMBeanServerDefaultDomain(camelJMXAgent.getMbeanServerDefaultDomain()); 402 agent.setRegistryPort(camelJMXAgent.getRegistryPort()); 403 agent.setServiceUrlPath(camelJMXAgent.getServiceUrlPath()); 404 agent.setUsePlatformMBeanServer(camelJMXAgent.isUsePlatformMBeanServer()); 405 agent.setOnlyRegisterProcessorWithCustomId(camelJMXAgent.getOnlyRegisterProcessorWithCustomId()); 406 407 LOG.info("JMXAgent enabled: " + camelJMXAgent); 408 getContext().setLifecycleStrategy(new InstrumentationLifecycleStrategy(agent)); 409 } 410 } 411 412 @SuppressWarnings("unchecked") 413 private <T> T getBeanForType(Class<T> clazz) { 414 T bean = null; 415 String[] names = getApplicationContext().getBeanNamesForType(clazz, true, true); 416 if (names.length == 1) { 417 bean = (T) getApplicationContext().getBean(names[0], clazz); 418 } 419 if (bean == null) { 420 ApplicationContext parentContext = getApplicationContext().getParent(); 421 if (parentContext != null) { 422 names = parentContext.getBeanNamesForType(clazz, true, true); 423 if (names.length == 1) { 424 bean = (T) parentContext.getBean(names[0], clazz); 425 } 426 } 427 } 428 return bean; 429 430 } 431 432 public void destroy() throws Exception { 433 getContext().stop(); 434 } 435 436 public void onApplicationEvent(ApplicationEvent event) { 437 if (context != null) { 438 // let the spring camel context handle the events 439 context.onApplicationEvent(event); 440 } else { 441 if (LOG.isDebugEnabled()) { 442 LOG.debug("Publishing spring-event: " + event); 443 } 444 445 if (event instanceof ContextRefreshedEvent) { 446 // now lets start the CamelContext so that all its possible 447 // dependencies are initialized 448 try { 449 LOG.debug("Starting the context now!"); 450 getContext().start(); 451 } catch (Exception e) { 452 throw wrapRuntimeCamelException(e); 453 } 454 } 455 } 456 } 457 458 // Properties 459 // ------------------------------------------------------------------------- 460 public SpringCamelContext getContext() throws Exception { 461 if (context == null) { 462 context = createContext(); 463 } 464 return context; 465 } 466 467 public void setContext(SpringCamelContext context) { 468 this.context = context; 469 } 470 471 public List<RouteDefinition> getRoutes() { 472 return routes; 473 } 474 475 public void setRoutes(List<RouteDefinition> routes) { 476 this.routes = routes; 477 } 478 479 public List<InterceptDefinition> getIntercepts() { 480 return intercepts; 481 } 482 483 public void setIntercepts(List<InterceptDefinition> intercepts) { 484 this.intercepts = intercepts; 485 } 486 487 public List<InterceptFromDefinition> getInterceptFroms() { 488 return interceptFroms; 489 } 490 491 public void setInterceptFroms(List<InterceptFromDefinition> interceptFroms) { 492 this.interceptFroms = interceptFroms; 493 } 494 495 public List<InterceptSendToEndpointDefinition> getInterceptSendToEndpoints() { 496 return interceptSendToEndpoints; 497 } 498 499 public void setInterceptSendToEndpoints(List<InterceptSendToEndpointDefinition> interceptSendToEndpoints) { 500 this.interceptSendToEndpoints = interceptSendToEndpoints; 501 } 502 503 public RouteBuilder getRouteBuilder() { 504 return routeBuilder; 505 } 506 507 /** 508 * Set a single {@link RouteBuilder} to be used to create the default routes 509 * on startup 510 */ 511 public void setRouteBuilder(RouteBuilder routeBuilder) { 512 this.routeBuilder = routeBuilder; 513 } 514 515 /** 516 * Set a collection of {@link RouteBuilder} instances to be used to create 517 * the default routes on startup 518 */ 519 public void setRouteBuilders(RouteBuilder[] builders) { 520 for (RouteBuilder builder : builders) { 521 additionalBuilders.add(builder); 522 } 523 } 524 525 public ApplicationContext getApplicationContext() { 526 if (applicationContext == null) { 527 throw new IllegalArgumentException("No applicationContext has been injected!"); 528 } 529 return applicationContext; 530 } 531 532 public void setApplicationContext(ApplicationContext applicationContext) { 533 this.applicationContext = applicationContext; 534 } 535 536 public PropertiesDefinition getProperties() { 537 return properties; 538 } 539 540 public void setProperties(PropertiesDefinition properties) { 541 this.properties = properties; 542 } 543 544 public String[] getPackages() { 545 return packages; 546 } 547 548 /** 549 * Sets the package names to be recursively searched for Java classes which 550 * extend {@link RouteBuilder} to be auto-wired up to the 551 * {@link SpringCamelContext} as a route. Note that classes are excluded if 552 * they are specifically configured in the spring.xml 553 * 554 * @param packages the package names which are recursively searched 555 */ 556 public void setPackages(String[] packages) { 557 this.packages = packages; 558 } 559 560 public void setBeanPostProcessor(BeanPostProcessor postProcessor) { 561 this.beanPostProcessor = postProcessor; 562 } 563 564 public BeanPostProcessor getBeanPostProcessor() { 565 return beanPostProcessor; 566 } 567 568 public void setCamelJMXAgent(CamelJMXAgentDefinition agent) { 569 camelJMXAgent = agent; 570 } 571 572 public Boolean getTrace() { 573 return trace; 574 } 575 576 public void setTrace(Boolean trace) { 577 this.trace = trace; 578 } 579 580 public Boolean getStreamCache() { 581 return streamCache; 582 } 583 584 public void setStreamCache(Boolean streamCache) { 585 this.streamCache = streamCache; 586 } 587 588 public Long getDelay() { 589 return delay; 590 } 591 592 public void setDelay(Long delay) { 593 this.delay = delay; 594 } 595 596 public Boolean getHandleFault() { 597 return handleFault; 598 } 599 600 public void setHandleFault(Boolean handleFault) { 601 this.handleFault = handleFault; 602 } 603 604 public CamelJMXAgentDefinition getCamelJMXAgent() { 605 return camelJMXAgent; 606 } 607 608 public List<RouteBuilderDefinition> getBuilderRefs() { 609 return builderRefs; 610 } 611 612 public void setBuilderRefs(List<RouteBuilderDefinition> builderRefs) { 613 this.builderRefs = builderRefs; 614 } 615 616 public String getErrorHandlerRef() { 617 return errorHandlerRef; 618 } 619 620 /** 621 * Sets the name of the error handler object used to default the error handling strategy 622 * 623 * @param errorHandlerRef the Spring bean ref of the error handler 624 */ 625 public void setErrorHandlerRef(String errorHandlerRef) { 626 this.errorHandlerRef = errorHandlerRef; 627 } 628 629 public Boolean getShouldStartContext() { 630 return shouldStartContext; 631 } 632 633 public void setShouldStartContext(Boolean shouldStartContext) { 634 this.shouldStartContext = shouldStartContext; 635 } 636 637 public void setDataFormats(DataFormatsDefinition dataFormats) { 638 this.dataFormats = dataFormats; 639 } 640 641 public DataFormatsDefinition getDataFormats() { 642 return dataFormats; 643 } 644 645 public void setOnExceptions(List<OnExceptionDefinition> onExceptions) { 646 this.onExceptions = onExceptions; 647 } 648 649 public List<OnExceptionDefinition> getOnExceptions() { 650 return onExceptions; 651 } 652 653 public List<OnCompletionDefinition> getOnCompletions() { 654 return onCompletions; 655 } 656 657 public void setOnCompletions(List<OnCompletionDefinition> onCompletions) { 658 this.onCompletions = onCompletions; 659 } 660 661 // Implementation methods 662 // ------------------------------------------------------------------------- 663 664 /** 665 * Create the context 666 */ 667 protected SpringCamelContext createContext() { 668 SpringCamelContext ctx = new SpringCamelContext(getApplicationContext()); 669 ctx.setName(getId()); 670 if (streamCache != null) { 671 ctx.setStreamCaching(streamCache); 672 } 673 if (trace != null) { 674 ctx.setTrace(trace); 675 } 676 if (delay != null) { 677 ctx.setDelay(delay); 678 } 679 if (handleFault != null) { 680 ctx.setHandleFault(handleFault); 681 } 682 if (errorHandlerRef != null) { 683 ErrorHandlerBuilder errorHandlerBuilder = (ErrorHandlerBuilder) getApplicationContext().getBean(errorHandlerRef, ErrorHandlerBuilder.class); 684 if (errorHandlerBuilder == null) { 685 throw new IllegalArgumentException("Could not find bean: " + errorHandlerRef); 686 } 687 ctx.setErrorHandlerBuilder(errorHandlerBuilder); 688 } 689 690 if (shouldStartContext != null) { 691 ctx.setShouldStartContext(shouldStartContext); 692 } 693 694 return ctx; 695 } 696 697 /** 698 * Strategy to install all available routes into the context 699 */ 700 @SuppressWarnings("unchecked") 701 protected void installRoutes() throws Exception { 702 List<RouteBuilder> builders = new ArrayList<RouteBuilder>(); 703 704 if (routeBuilder != null) { 705 builders.add(routeBuilder); 706 } 707 708 // lets add route builders added from references 709 if (builderRefs != null) { 710 for (RouteBuilderDefinition builderRef : builderRefs) { 711 RouteBuilder builder = builderRef.createRouteBuilder(getContext()); 712 if (builder != null) { 713 builders.add(builder); 714 } else { 715 // support to get the route here 716 Routes routes = builderRef.createRoutes(getContext()); 717 if (routes != null) { 718 additionalBuilders.add(routes); 719 } else { 720 // Throw the exception that we can't find any build here 721 throw new CamelException("Cannot find any routes with this RouteBuilder reference: " + builderRef); 722 } 723 } 724 725 } 726 } 727 728 // install already configured routes 729 for (Routes routeBuilder : additionalBuilders) { 730 getContext().addRoutes(routeBuilder); 731 } 732 733 // install builders 734 for (RouteBuilder builder : builders) { 735 if (beanPostProcessor != null) { 736 // Inject the annotated resource 737 beanPostProcessor.postProcessBeforeInitialization(builder, builder.toString()); 738 } 739 getContext().addRoutes(builder); 740 } 741 } 742 743 /** 744 * Strategy method to try find {@link RouteBuilder} instances on the classpath 745 */ 746 protected void findRouteBuilders() throws Exception { 747 List<String> packages = new ArrayList<String>(); 748 749 if (getPackages() != null && getPackages().length > 0) { 750 751 // normalize packages as end user can have inserted spaces or \n or the likes 752 for (String name : getPackages()) { 753 name = ObjectHelper.normalizeClassName(name); 754 if (ObjectHelper.isNotEmpty(name)) { 755 packages.add(name); 756 } 757 } 758 String[] normalized = packages.toArray(new String[packages.size()]); 759 760 RouteBuilderFinder finder = new RouteBuilderFinder(getContext(), normalized, getContextClassLoaderOnStart(), 761 getBeanPostProcessor(), getContext().getPackageScanClassResolver()); 762 finder.appendBuilders(getAdditionalBuilders()); 763 } 764 } 765 766 }