You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2018/11/08 15:00:14 UTC

[camel] branch sandbox/camel-3.x updated (1226e01 -> 96ecf2d)

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a change to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from 1226e01  Fix test broken by latest jaxb change
     new e106882  Improve DefaultNodeIdFactory concurrency
     new 11da495  Make the code more homogeneous in ErrorHandleReifier
     new 121fe1d  Cache the JAXBContext in ModelJAXBContextFactory
     new d109908  Split internal services creation
     new 958b12e  Improve TypeConversionException message
     new 7c54a1b  Fix failing test caused by using a static list of converters
     add c35ba20  CAMEL-12899: Added check for LinkedIn CAPTCHA, added accessToken and expiryTime properties to avoid login issues
     add bfdea9e  Merge pull request #2578 from dhirajsb/CAMEL-12899
     add f499ede  CAMEL-12899: Fixed default expiryTime calculation
     add 115624c  Merge pull request #2580 from dhirajsb/CAMEL-12899
     add 3259587  Regen
     add 5420c9b  [CAMEL-12902] SMX version of qpid is no longer needed
     add 3f471f8  Fixed CS
     add dbc6749  Fixed CS
     add bd0f400  Fixed CS
     add 29c7278  polish the camel-jpa codebase a bit
     add 8d5d88e  Fixed typo
     add c71546c  Typo fix
     add d03ac23  Add XML references for release 2.21.3
     add 4c19ba7  Upgrade Owasp Maven Plugin to version 3.3.4
     add 0a0cd90  Upgrade ActiveMQ to version 5.15.7
     add aa69311  Upgrade Atmosphere Websocket to version 2.5.1
     add 738476c  CAMEL-12905: The trigger that starts the SpringCamelContext and that collect to routes to the camel context, needs to be a ContextRefreshedEvent that has been emitted by the ApplicationContext that instantiated the SpringCamelContext instance.
     add 3a42f59  12905: No need to cast ContextRefreshedEvent. Safety applicationContext identity check.
     add cfb6c60  12905: Safety applicationContext identity check.
     add 0d10fad  12905 Fixes missing parentheses
     add 62d947e  Fix link to camel-fhir docs in the components readme file
     add 67fbe5e  Upgrade Flink to version 1.6.2
     add 524c0f4  Add fhir data formats to docs
     add 41ce5f6  Upgrade Brave Zipkin to version 5.5.0
     add e79390d  CAMEL-11497: Migrate User Stories (#2583)
     add bae7698  Upgrade Ahc to version 2.6.0
     add 7915d1d  Upgrade RxJava2 to version 2.2.3
     add 09c8779  Upgrade Commons Configuration 2 to version 2.4.0
     add 8004807  Camel-Shiro Karaf feature now needs commons-text
     add 176e3a6  CAMEL-11497: Remove ^M characters
     add 097bde1  Upgrade Spring-Cloud Commons to version 2.0.2.RELEASE
     add 93878d9  Upgrade Spring-Cloud Netflix to version 2.0.2.RELEASE
     add b765261  Updated readme.txt (#2585)
     add 87d2d98  Upgrade Micrometer to version 1.1.0
     add 8bfc21b  Upgrade Netty to version 4.1.31.Final
     add 6bfc7cd  Upgrade Aspectj to version 1.9.2
     add 35a23cf  Added Http Session Handling docs
     add 1fb56fa  Added http-session-handling to summary
     add 2b8499c  Fixed minor docs
     add be09d0b  Added Service Pool to docs
     add c008810  Added Service Pool to Summary
     add 0177dd2  Added Threading Model to Docs
     add 4a885bf  Added Threading Model to Summary
     add 7c6924d  Updated docs for Threading Model
     add 66f875a  Fixed architecture image
     add 7c68075  Added ComponentConfiguration to docs
     add a41fa41  Added ComponentConfiguration to Summary
     add 31acc4e  Minor fixes to Architecture docs
     add 850e985  Minor Fixes to ComponentConfiguration docs
     add 0786c68  Added the code snippet back to the transactional-client.adoc
     add 666437e  CAMEL-12838 - Camel Twitter Send Direct Message Endpoint not working, use cameltweet user in the test
     add 8e2c9d6  Upgrade Infinispan to version 9.4.1.Final
     add 2c69246  CAMEL-12883: Added unit test
     add 0c46180  CAMEL-12835: Fixed camel-json-validator to deal with streaming content not being re-readable and therefore favour using stream caching.
     add d35b028  Upgrade jSMPP to version 2.3.7
     add dfc2c80  Upgrade Zipkin to version 2.11.8
     add 6d03f40  Changed the version range of Atmosphere Websocket
     add 2b3f416  Removed ServiceMix reference
     add be74b81  Fixed using OSGI blueprint with camel docs
     add 453dd41  Added using OSGi blueprint link to adoc
     add e0aba10  [CAMEL-12911]gzip Content-Encoding problems after upgrading to Jetty 9.4.12
     add c823585  Added Endpoint completer to adoc
     add 26c8c23  Added Endpoint Completer to Summary
     add 09a33b9  Added Uris to Summary
     add db8a577  Merge branch 'master' of github.com:apache/camel
     add ee7a689  [CAMEL-12914]camel-rest-swagger - Unit test fails after jetty upgrade
     add c6eb959  Added Endpoint completer to adoc
     add a79ed22  Added Endpoint Completer to Summary
     add dd87055  Added Uris to Summary
     add b7d81e7  Upgrade Spring framework to 5.1.2.RELEASE
     add de9fab6  Upgrade Spring Boot to 2.1.0.RELEASE
     add db0501e  Upgrade Spring Boot to 2.1.0.RELEASE. The BOM generator needed a code change as SB guys have changed their POM in this new version.
     add 9cbc320  Regen
     add 3c01356  Upgrade Braintree Java to version 2.86.0
     add eca702d  Upgrade TestContainers to version 1.10.0
     add 4d04d2a  Upgrade EhCache to version 2.10.6
     add 79628fe  Merge branch 'master' of github.com:apache/camel
     add 204cdba  Upgrade Spark Core and related bundle to version 2.8.0
     add e7f298e  Upgrade Consul to version 1.2.5
     add 32135ff  Upgrade Fastjson and related bundle to version 1.2.51
     add 4d6be42  Upgrade AWS Java SDK and related bundle to version 1.11.438
     add 2aca2ad  Upgrade Cglib and related bundle to version 3.2.8
     add 06f78b9  Fixed Camel AMQP Spring Boot Itest
     add 41e63bb  Upgrade Spring Integration to version 5.1.0
     add 45556a4  Upgrade InfluxDB and related bundle to version 2.14
     add 83dd49a  Upgrade Spring Data Commons and related bundle to version 2.1.1.RELEASE
     add 1afd4d9  Upgrade Spring Data Keyvalue and related bundle to version 2.1.1.RELEASE
     add e070830  Upgrade Spring Data Redis and related bundle to version 2.1.1.RELEASE
     add 568b228  Add details about not working camel-spring-redis Karaf feature
     add bd20882  Upgrade Libphonenumber and related bundle to version 8.9.16
     add 3d55db7  Regen
     add 99a0b2a  Upgrade JT400 and related bundle to version 9.6
     add 2a1fef6  Upgrade Elasticsearch Rest to version 6.4.2. It actually doesn't work in OSGi.
     add 3ca55ac  Upgrade Lucene and related bundle to version 7.5.0
     add e33d5f8  Upgrade Solr and related bundle to version 7.5.0
     add e78364d  Since camel-elasticsearch-rest doesn't work in Karaf, skipping the Karaf itest
     add 6c851d8  CAMEL-12916: camel-http4 - The sslContextParameters option should be documented on endpoint as well.
     add 6b9fa87  CAMEL-12749 - Added Multisearch Operation to camel-elasticsearch-rest
     add a2e1fc3  CAMEL-12749 - Fixed CS
     add 9fe7baa  CAMEL-12749 - Added docs and removed the converter since it doesn't make sense to have one
     add 3964707  CAMEL-12749 - Fixed docs
     add 152a650  Fixed minor stuff in docs
     add e713a08  Up to latest version
     add a213f0c  Add camel-nsq component.
     add 9eea161  Add camel-nsq component.
     add ccddc07  camel-nsq component can automatically Finish messages.
     add 9ddad3f  camel-nsq component supports TLS setup.
     add 2e98f12  Removed original Synchronization class and corrected test.
     add 858a330  Camel-NSQ: Fixed CS and added the starter
     add 44aa18e  Camel-NSQ: Added the component to kit
     add a6b0f31  Camel-NSQ: Regen
     add e46bf2d  Camel-NSQ: Cleanup the copied docs
     add 9cb832f  Camel-NSQ: Changed the placeholder name for the client version to avoid confusion with nats client
     add 01dc96f  CAMEL-12917 - Camel-NSQ: Add Karaf feature
     add d495bbc  CAMEL-12918 - Camel-NSQ: Add Karaf and Spring Boot Integration tests
     new d21d504  Merge remote-tracking branch 'origin/master' into camel-3.x
     new 96ecf2d  Fix unit tests

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 apache-camel/src/main/descriptors/common-bin.xml   |    2 +
 bom/camel-bom/pom.xml                              |   10 +
 .../org/apache/camel/TypeConversionException.java  |    2 +-
 camel-core/src/main/docs/eips/rollback-eip.adoc    |    2 +-
 .../src/main/docs/eips/transactional-client.adoc   |  154 +-
 ...CamelContext.java => AbstractCamelContext.java} |  857 ++--
 .../org/apache/camel/impl/DefaultCamelContext.java | 4587 +-------------------
 .../org/apache/camel/impl/DefaultDebugger.java     |   17 +-
 .../camel/impl/DefaultModelJAXBContextFactory.java |   11 +-
 .../apache/camel/impl/DefaultNodeIdFactory.java    |   15 +-
 .../java/org/apache/camel/impl/RouteService.java   |    4 +-
 .../java/org/apache/camel/model/ModelHelper.java   |   22 +-
 .../apache/camel/reifier/ErrorHandlerReifier.java  |    4 +-
 .../apache/camel/builder/xml/XPathFeatureTest.java |   27 +-
 .../apache/camel/impl/DefaultComponentTest.java    |    2 +-
 .../camel/impl/MultipleLifecycleStrategyTest.java  |    4 +-
 .../AdviceWithWeaveByTypeOnExceptionTest.java      |   63 +
 ...edProducerRouteAddRemoveRegisterAlwaysTest.java |    2 +-
 .../camel-amqp/src/main/docs/amqp-component.adoc   |    2 +-
 .../BlueprintModelJAXBContextFactory.java          |   19 +-
 .../src/main/docs/consul-component.adoc            |    6 +-
 .../src/main/resources/META-INF/spring.schemas     |    1 +
 .../src/main/docs/disruptor-component.adoc         |    4 +-
 .../src/main/docs/ehcache-component.adoc           |    2 +-
 .../main/docs/elasticsearch-rest-component.adoc    |   37 +-
 .../elasticsearch/ElasticsearchOperation.java      |    1 +
 .../elasticsearch/ElasticsearchProducer.java       |    6 +
 .../ElasticsearchActionRequestConverter.java       |    6 +-
 ...asticsearchGetSearchDeleteExistsUpdateTest.java |   27 +
 .../remote/sftp/SftpConsumerDisconnectTest.java    |    7 +-
 .../org/apache/camel/http/common/CamelServlet.java |    1 -
 .../camel-http4/src/main/docs/http4-component.adoc |    3 +-
 .../apache/camel/component/http4/HttpEndpoint.java |   18 +
 .../src/main/docs/infinispan-component.adoc        |    2 +-
 .../component/jetty9/AttachmentHttpBinding.java    |    7 +
 .../camel-jms/src/main/docs/jms-component.adoc     |    1 +
 .../camel-jpa/src/main/docs/jpa-component.adoc     |    2 +-
 .../apache/camel/component/jpa/JpaEndpoint.java    |    2 +-
 .../apache/camel/component/jpa/JpaProducer.java    |    4 +-
 .../camel/component/jpa/AbstractJpaMethodTest.java |    2 +-
 .../jpa/JpaWithNativeQueryWithResultClassTest.java |    2 +-
 .../jpa/JpaProducerPassingEntityManagerTest.java   |    2 +-
 .../JpaProducerWithQueryParametersHeaderTest.java  |    7 +-
 .../apache/camel/processor/jpa/JpaRouteTest.java   |    2 +-
 .../jsonvalidator/JsonValidatorEndpoint.java       |   42 +-
 .../jsonvalidator/ValidatorInputStreamTest.java    |   53 +
 .../linkedin/api/LinkedInOAuthRequestFilter.java   |   41 +-
 .../api/AbstractResourceIntegrationTest.java       |   23 +-
 .../api/PeopleResourceIntegrationTest.java         |    7 +-
 .../src/test/resources/test-options.properties     |    4 +
 .../src/main/docs/linkedin-component.adoc          |    8 +-
 ...Storage.java => DefaultOAuthSecureStorage.java} |   36 +-
 .../component/linkedin/LinkedInComponent.java      |    7 +-
 .../component/linkedin/LinkedInConfiguration.java  |   26 +
 .../internal/CachingOAuthSecureStorage.java        |    2 +-
 .../src/test/resources/test-options.properties     |    4 +
 .../camel-mllp/src/main/docs/mllp-component.adoc   |    4 +-
 .../component/mybatis/MyBatisTestSupport.java      |    2 +-
 .../src/main/docs/nagios-component.adoc            |    2 +-
 .../src/main/docs/netty4-component.adoc            |   12 +-
 components/camel-nsq/pom.xml                       |  127 +
 .../camel-nsq/src/main/docs/nsq-component.adoc     |  110 +
 .../apache/camel/component/nsq/NsqComponent.java   |   59 +
 .../camel/component/nsq/NsqConfiguration.java      |  242 ++
 .../apache/camel/component/nsq/NsqConstants.java   |   23 +-
 .../apache/camel/component/nsq/NsqConsumer.java    |  124 +
 .../apache/camel/component/nsq/NsqEndpoint.java    |   92 +
 .../apache/camel/component/nsq/NsqProducer.java    |   80 +
 .../camel/component/nsq/NsqSynchronization.java    |   39 +-
 .../src/main/resources/META-INF/LICENSE.txt        |    0
 .../src/main/resources/META-INF/NOTICE.txt         |    0
 .../services/org/apache/camel/component/nsq        |   18 +
 .../camel/component/nsq/NsqConsumerTest.java       |  103 +
 .../camel/component/nsq/NsqProducerTest.java       |   96 +
 .../apache/camel/component/nsq/NsqTestSupport.java |   61 +
 .../src/test/resources/log4j2.properties}          |   23 +-
 .../camel/component/rest/swagger/HttpsTest.java    |    2 +-
 .../rest/swagger/Jetty94ServerFactory.java         |    2 +-
 components/camel-solr/pom.xml                      |    2 +-
 .../src/main/docs/spring-boot.adoc                 |    4 +-
 .../apache/camel/spring/boot/RoutesCollector.java  |    3 +-
 .../cloud/CamelCloudConfigurationProperties.java   |    2 -
 .../boot/CamelAutoConfigurationPropertiesTest.java |    2 +-
 ...amelAutoConfigurationWithContextRunnerTest.java |   54 -
 .../boot/CamelConfigurationLocationsTest.java      |    2 +-
 .../camel/spring/boot/CamelEventNotifierTest.java  |    2 +-
 .../boot/CustomCamelCamelConfigurationTest.java    |    2 +-
 .../spring/boot/CustomShutdownStrategyTest.java    |    2 +-
 .../spring/boot/SpringConverterDelegationTest.java |    2 +-
 .../camel/spring/boot/issues/RestDslPostTest.java  |    2 +-
 .../camel/spring/boot/issues/SimpleOgnlTest.java   |    2 +-
 .../boot/parent/SpringBootRefreshContextTest.java  |    5 +-
 .../src/main/resources/META-INF/spring.schemas     |    1 +
 .../src/main/resources/META-INF/spring.schemas     |    1 +
 .../apache/camel/spring/SpringCamelContext.java    |    2 +-
 .../spring/SpringModelJAXBContextFactory.java      |    4 -
 .../src/main/resources/META-INF/spring.schemas     |    1 +
 .../camel-ssh/src/main/docs/ssh-component.adoc     |    4 +-
 .../apache/camel/swagger/RestSwaggerSupport.java   |    3 +-
 .../twitter/DirectMessageProducerTest.java         |    2 +-
 .../src/main/docs/zookeeper-component.adoc         |    2 +-
 components/pom.xml                                 |    1 +
 components/readme.adoc                             |    9 +-
 docs/user-manual/en/SUMMARY.md                     |   22 +-
 docs/user-manual/en/architecture.adoc              |    8 +-
 .../user-manual/en/commercial-camel-offerings.adoc |    2 +-
 docs/user-manual/en/componentconfiguration.adoc    |   44 +
 docs/user-manual/en/endpoint-completer.adoc        |   27 +
 docs/user-manual/en/http-session-handling.adoc     |  152 +
 docs/user-manual/en/languages.adoc                 |    3 +-
 docs/user-manual/en/mailing-lists.adoc             |    2 +-
 docs/user-manual/en/servicepool.adoc               |   60 +
 docs/user-manual/en/threading-model.adoc           |  244 ++
 docs/user-manual/en/user-stories.adoc              |  342 ++
 .../en/using-osgi-blueprint-with-camel.adoc        |   11 +-
 parent/pom.xml                                     |  120 +-
 .../commands/AbstractLocalCamelController.java     |    4 +-
 .../features/src/main/resources/bundles.properties |    1 -
 .../karaf/features/src/main/resources/features.xml |   18 +-
 .../springboot/LinkedInComponentConfiguration.java |   25 +
 .../components-starter/camel-nsq-starter/pom.xml   |   61 +
 .../springboot/NsqComponentAutoConfiguration.java  |  128 +
 .../nsq/springboot/NsqComponentConfiguration.java  |   67 +
 .../src/main/resources/META-INF/LICENSE.txt        |    0
 .../src/main/resources/META-INF/NOTICE.txt         |    0
 .../src/main/resources/META-INF/spring.factories   |   14 +-
 .../src/main/resources/META-INF/spring.provides    |   14 +-
 platforms/spring-boot/components-starter/pom.xml   |    1 +
 .../camel-spring-boot-dependencies/pom.xml         |   12 +-
 platforms/spring-boot/spring-boot-dm/pom.xml       |    8 +-
 .../itest/karaf/CamelElasticsearchRestTest.java    |   19 +
 ...lasticsearchRestTest.java => CamelNsqTest.java} |    7 +-
 .../camel/itest/springboot/CamelAmqpTest.java      |    1 +
 .../{CamelAmqpTest.java => CamelNsqTest.java}      |    5 +-
 .../camel/itest/springboot/CamelSolrTest.java      |    2 +
 .../maven/bom/generator/BomGeneratorMojo.java      |    4 +
 .../camel/maven/packaging/PrepareCatalogMojo.java  |    4 +
 .../maven/packaging/model/ComponentModel.java      |    2 +
 .../maven/packaging/model/DataFormatModel.java     |    5 +
 139 files changed, 3649 insertions(+), 5338 deletions(-)
 copy camel-core/src/main/java/org/apache/camel/impl/{DefaultCamelContext.java => AbstractCamelContext.java} (90%)
 create mode 100644 camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveByTypeOnExceptionTest.java
 create mode 100644 components/camel-json-validator/src/test/java/org/apache/camel/component/jsonvalidator/ValidatorInputStreamTest.java
 copy components/camel-linkedin/camel-linkedin-component/src/main/java/org/apache/camel/component/linkedin/{internal/CachingOAuthSecureStorage.java => DefaultOAuthSecureStorage.java} (50%)
 create mode 100644 components/camel-nsq/pom.xml
 create mode 100644 components/camel-nsq/src/main/docs/nsq-component.adoc
 create mode 100644 components/camel-nsq/src/main/java/org/apache/camel/component/nsq/NsqComponent.java
 create mode 100644 components/camel-nsq/src/main/java/org/apache/camel/component/nsq/NsqConfiguration.java
 copy tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelElasticsearchRestTest.java => components/camel-nsq/src/main/java/org/apache/camel/component/nsq/NsqConstants.java (65%)
 create mode 100644 components/camel-nsq/src/main/java/org/apache/camel/component/nsq/NsqConsumer.java
 create mode 100644 components/camel-nsq/src/main/java/org/apache/camel/component/nsq/NsqEndpoint.java
 create mode 100644 components/camel-nsq/src/main/java/org/apache/camel/component/nsq/NsqProducer.java
 copy camel-core/src/main/java/org/apache/camel/impl/DefaultModelJAXBContextFactory.java => components/camel-nsq/src/main/java/org/apache/camel/component/nsq/NsqSynchronization.java (52%)
 copy {tooling/maven/camel-package-maven-plugin => components/camel-nsq}/src/main/resources/META-INF/LICENSE.txt (100%)
 copy {tooling/maven/camel-package-maven-plugin => components/camel-nsq}/src/main/resources/META-INF/NOTICE.txt (100%)
 create mode 100644 components/camel-nsq/src/main/resources/META-INF/services/org/apache/camel/component/nsq
 create mode 100644 components/camel-nsq/src/test/java/org/apache/camel/component/nsq/NsqConsumerTest.java
 create mode 100644 components/camel-nsq/src/test/java/org/apache/camel/component/nsq/NsqProducerTest.java
 create mode 100644 components/camel-nsq/src/test/java/org/apache/camel/component/nsq/NsqTestSupport.java
 copy components/{camel-linkedin/camel-linkedin-component/src/test/resources/test-options.properties => camel-nsq/src/test/resources/log4j2.properties} (68%)
 delete mode 100644 components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/CamelAutoConfigurationWithContextRunnerTest.java
 create mode 100644 docs/user-manual/en/componentconfiguration.adoc
 create mode 100644 docs/user-manual/en/endpoint-completer.adoc
 create mode 100644 docs/user-manual/en/http-session-handling.adoc
 create mode 100644 docs/user-manual/en/servicepool.adoc
 create mode 100644 docs/user-manual/en/threading-model.adoc
 create mode 100644 docs/user-manual/en/user-stories.adoc
 create mode 100644 platforms/spring-boot/components-starter/camel-nsq-starter/pom.xml
 create mode 100644 platforms/spring-boot/components-starter/camel-nsq-starter/src/main/java/org/apache/camel/component/nsq/springboot/NsqComponentAutoConfiguration.java
 create mode 100644 platforms/spring-boot/components-starter/camel-nsq-starter/src/main/java/org/apache/camel/component/nsq/springboot/NsqComponentConfiguration.java
 copy {tooling/maven/camel-package-maven-plugin => platforms/spring-boot/components-starter/camel-nsq-starter}/src/main/resources/META-INF/LICENSE.txt (100%)
 copy {tooling/maven/camel-package-maven-plugin => platforms/spring-boot/components-starter/camel-nsq-starter}/src/main/resources/META-INF/NOTICE.txt (100%)
 copy components/camel-linkedin/camel-linkedin-component/src/test/resources/test-options.properties => platforms/spring-boot/components-starter/camel-nsq-starter/src/main/resources/META-INF/spring.factories (73%)
 copy components/camel-linkedin/camel-linkedin-api/src/test/resources/test-options.properties => platforms/spring-boot/components-starter/camel-nsq-starter/src/main/resources/META-INF/spring.provides (73%)
 copy tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/{CamelElasticsearchRestTest.java => CamelNsqTest.java} (87%)
 copy tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/{CamelAmqpTest.java => CamelNsqTest.java} (90%)


[camel] 07/08: Merge remote-tracking branch 'origin/master' into camel-3.x

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d21d5045710b9a74e8dfd2e7970056ec0e8ef893
Merge: 7c54a1b d495bbc
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Nov 8 10:50:02 2018 +0100

    Merge remote-tracking branch 'origin/master' into camel-3.x

 apache-camel/src/main/descriptors/common-bin.xml   |   2 +
 bom/camel-bom/pom.xml                              |  10 +
 camel-core/src/main/docs/eips/rollback-eip.adoc    |   2 +-
 .../src/main/docs/eips/transactional-client.adoc   | 154 +++++++++-
 .../AdviceWithWeaveByTypeOnExceptionTest.java      |  63 ++++
 .../camel-amqp/src/main/docs/amqp-component.adoc   |   2 +-
 .../src/main/docs/consul-component.adoc            |   6 +-
 .../src/main/resources/META-INF/spring.schemas     |   1 +
 .../src/main/docs/disruptor-component.adoc         |   4 +-
 .../src/main/docs/ehcache-component.adoc           |   2 +-
 .../main/docs/elasticsearch-rest-component.adoc    |  37 ++-
 .../elasticsearch/ElasticsearchOperation.java      |   1 +
 .../elasticsearch/ElasticsearchProducer.java       |   6 +
 .../ElasticsearchActionRequestConverter.java       |   6 +-
 ...asticsearchGetSearchDeleteExistsUpdateTest.java |  27 ++
 .../remote/sftp/SftpConsumerDisconnectTest.java    |   7 +-
 .../org/apache/camel/http/common/CamelServlet.java |   1 -
 .../camel-http4/src/main/docs/http4-component.adoc |   3 +-
 .../apache/camel/component/http4/HttpEndpoint.java |  18 ++
 .../src/main/docs/infinispan-component.adoc        |   2 +-
 .../component/jetty9/AttachmentHttpBinding.java    |   7 +
 .../camel-jms/src/main/docs/jms-component.adoc     |   1 +
 .../camel-jpa/src/main/docs/jpa-component.adoc     |   2 +-
 .../apache/camel/component/jpa/JpaEndpoint.java    |   2 +-
 .../apache/camel/component/jpa/JpaProducer.java    |   4 +-
 .../camel/component/jpa/AbstractJpaMethodTest.java |   2 +-
 .../jpa/JpaWithNativeQueryWithResultClassTest.java |   2 +-
 .../jpa/JpaProducerPassingEntityManagerTest.java   |   2 +-
 .../JpaProducerWithQueryParametersHeaderTest.java  |   7 +-
 .../apache/camel/processor/jpa/JpaRouteTest.java   |   2 +-
 .../jsonvalidator/JsonValidatorEndpoint.java       |  42 ++-
 .../jsonvalidator/ValidatorInputStreamTest.java    |  53 ++++
 .../linkedin/api/LinkedInOAuthRequestFilter.java   |  41 ++-
 .../api/AbstractResourceIntegrationTest.java       |  23 +-
 .../api/PeopleResourceIntegrationTest.java         |   7 +-
 .../src/test/resources/test-options.properties     |   4 +
 .../src/main/docs/linkedin-component.adoc          |   8 +-
 ...Storage.java => DefaultOAuthSecureStorage.java} |  36 +--
 .../component/linkedin/LinkedInComponent.java      |   7 +-
 .../component/linkedin/LinkedInConfiguration.java  |  26 ++
 .../internal/CachingOAuthSecureStorage.java        |   2 +-
 .../src/test/resources/test-options.properties     |   4 +
 .../camel-mllp/src/main/docs/mllp-component.adoc   |   4 +-
 .../component/mybatis/MyBatisTestSupport.java      |   2 +-
 .../src/main/docs/nagios-component.adoc            |   2 +-
 .../src/main/docs/netty4-component.adoc            |  12 +-
 components/camel-nsq/pom.xml                       | 127 ++++++++
 .../camel-nsq/src/main/docs/nsq-component.adoc     | 110 +++++++
 .../apache/camel/component/nsq/NsqComponent.java   |  59 ++++
 .../camel/component/nsq/NsqConfiguration.java      | 242 +++++++++++++++
 .../apache/camel/component/nsq/NsqConstants.java   |  23 +-
 .../apache/camel/component/nsq/NsqConsumer.java    | 124 ++++++++
 .../apache/camel/component/nsq/NsqEndpoint.java    |  92 ++++++
 .../apache/camel/component/nsq/NsqProducer.java    |  80 +++++
 .../camel/component/nsq/NsqSynchronization.java    |  35 ++-
 .../src/main/resources/META-INF/LICENSE.txt        | 203 ++++++++++++
 .../src/main/resources/META-INF/NOTICE.txt         |  11 +
 .../services/org/apache/camel/component/nsq        |  18 ++
 .../camel/component/nsq/NsqConsumerTest.java       | 103 +++++++
 .../camel/component/nsq/NsqProducerTest.java       |  96 ++++++
 .../apache/camel/component/nsq/NsqTestSupport.java |  61 ++++
 .../src/test/resources/log4j2.properties}          |  23 +-
 .../camel/component/rest/swagger/HttpsTest.java    |   2 +-
 .../rest/swagger/Jetty94ServerFactory.java         |   2 +-
 components/camel-solr/pom.xml                      |   2 +-
 .../src/main/docs/spring-boot.adoc                 |   4 +-
 .../apache/camel/spring/boot/RoutesCollector.java  |   3 +-
 .../cloud/CamelCloudConfigurationProperties.java   |   2 -
 .../boot/CamelAutoConfigurationPropertiesTest.java |   2 +-
 ...amelAutoConfigurationWithContextRunnerTest.java |  54 ----
 .../boot/CamelConfigurationLocationsTest.java      |   2 +-
 .../camel/spring/boot/CamelEventNotifierTest.java  |   2 +-
 .../boot/CustomCamelCamelConfigurationTest.java    |   2 +-
 .../spring/boot/CustomShutdownStrategyTest.java    |   2 +-
 .../spring/boot/SpringConverterDelegationTest.java |   2 +-
 .../camel/spring/boot/issues/RestDslPostTest.java  |   2 +-
 .../camel/spring/boot/issues/SimpleOgnlTest.java   |   2 +-
 .../boot/parent/SpringBootRefreshContextTest.java  |   5 +-
 .../src/main/resources/META-INF/spring.schemas     |   1 +
 .../src/main/resources/META-INF/spring.schemas     |   1 +
 .../apache/camel/spring/SpringCamelContext.java    |   2 +-
 .../src/main/resources/META-INF/spring.schemas     |   1 +
 .../camel-ssh/src/main/docs/ssh-component.adoc     |   4 +-
 .../apache/camel/swagger/RestSwaggerSupport.java   |   3 +-
 .../twitter/DirectMessageProducerTest.java         |   2 +-
 .../src/main/docs/zookeeper-component.adoc         |   2 +-
 components/pom.xml                                 |   1 +
 components/readme.adoc                             |   9 +-
 docs/user-manual/en/SUMMARY.md                     |  22 +-
 docs/user-manual/en/architecture.adoc              |   8 +-
 .../user-manual/en/commercial-camel-offerings.adoc |   2 +-
 docs/user-manual/en/componentconfiguration.adoc    |  44 +++
 docs/user-manual/en/endpoint-completer.adoc        |  27 ++
 docs/user-manual/en/http-session-handling.adoc     | 152 +++++++++
 docs/user-manual/en/languages.adoc                 |   3 +-
 docs/user-manual/en/mailing-lists.adoc             |   2 +-
 docs/user-manual/en/servicepool.adoc               |  60 ++++
 docs/user-manual/en/threading-model.adoc           | 244 +++++++++++++++
 docs/user-manual/en/user-stories.adoc              | 342 +++++++++++++++++++++
 .../en/using-osgi-blueprint-with-camel.adoc        |  11 +-
 parent/pom.xml                                     | 120 ++++----
 .../features/src/main/resources/bundles.properties |   1 -
 .../karaf/features/src/main/resources/features.xml |  18 +-
 .../springboot/LinkedInComponentConfiguration.java |  25 ++
 .../components-starter/camel-nsq-starter/pom.xml   |  61 ++++
 .../springboot/NsqComponentAutoConfiguration.java  | 128 ++++++++
 .../nsq/springboot/NsqComponentConfiguration.java  |  67 ++++
 .../src/main/resources/META-INF/LICENSE.txt        | 203 ++++++++++++
 .../src/main/resources/META-INF/NOTICE.txt         |  11 +
 .../src/main/resources/META-INF/spring.factories   |  14 +-
 .../src/main/resources/META-INF/spring.provides    |  14 +-
 platforms/spring-boot/components-starter/pom.xml   |   1 +
 .../camel-spring-boot-dependencies/pom.xml         |  12 +-
 platforms/spring-boot/spring-boot-dm/pom.xml       |   8 +-
 .../itest/karaf/CamelElasticsearchRestTest.java    |  19 ++
 ...lasticsearchRestTest.java => CamelNsqTest.java} |   7 +-
 .../camel/itest/springboot/CamelAmqpTest.java      |   1 +
 .../{CamelSolrTest.java => CamelNsqTest.java}      |   5 +-
 .../camel/itest/springboot/CamelSolrTest.java      |   2 +
 .../maven/bom/generator/BomGeneratorMojo.java      |   4 +
 .../camel/maven/packaging/PrepareCatalogMojo.java  |   4 +
 .../maven/packaging/model/ComponentModel.java      |   2 +
 .../maven/packaging/model/DataFormatModel.java     |   5 +
 123 files changed, 3487 insertions(+), 343 deletions(-)

diff --cc apache-camel/src/main/descriptors/common-bin.xml
index d47e45d,8c63bdb..2e18886
--- a/apache-camel/src/main/descriptors/common-bin.xml
+++ b/apache-camel/src/main/descriptors/common-bin.xml
@@@ -173,8 -196,11 +173,9 @@@
          <include>org.apache.camel:camel-mvel</include>
          <include>org.apache.camel:camel-mybatis</include>
          <include>org.apache.camel:camel-nagios</include>
 -        <include>org.apache.camel:camel-netty</include>
          <include>org.apache.camel:camel-netty4</include>
 -        <include>org.apache.camel:camel-netty-http</include>
          <include>org.apache.camel:camel-netty4-http</include>
+         <include>org.apache.camel:camel-nsq</include>
          <include>org.apache.camel:camel-ognl</include>
          <include>org.apache.camel:camel-olingo2-api</include>
          <include>org.apache.camel:camel-olingo2</include>
@@@ -457,6 -520,9 +458,7 @@@
          <include>org.apache.camel:camel-nats-starter</include>
          <include>org.apache.camel:camel-netty4-http-starter</include>
          <include>org.apache.camel:camel-netty4-starter</include>
 -        <include>org.apache.camel:camel-netty-http-starter</include>
 -        <include>org.apache.camel:camel-netty-starter</include>
+         <include>org.apache.camel:camel-nsq-starter</include>
          <include>org.apache.camel:camel-ognl-starter</include>
          <include>org.apache.camel:camel-olingo2-starter</include>
          <include>org.apache.camel:camel-olingo4-starter</include>
diff --cc camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveByTypeOnExceptionTest.java
index 0000000,2fa4b04..b7a6aa4
mode 000000,100644..100644
--- a/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveByTypeOnExceptionTest.java
+++ b/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveByTypeOnExceptionTest.java
@@@ -1,0 -1,62 +1,63 @@@
+ /**
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.camel.processor.interceptor;
+ 
+ import org.apache.camel.ContextTestSupport;
+ import org.apache.camel.builder.AdviceWithRouteBuilder;
+ import org.apache.camel.builder.RouteBuilder;
+ import org.apache.camel.model.OnExceptionDefinition;
++import org.apache.camel.reifier.RouteReifier;
+ import org.junit.Test;
+ 
+ /**
+  * Advice with tests
+  */
+ public class AdviceWithWeaveByTypeOnExceptionTest extends ContextTestSupport {
+ 
+     @Test
+     public void testWeaveOnException() throws Exception {
 -        context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() {
++        RouteReifier.adviceWith(context.getRouteDefinitions().get(0), context, new AdviceWithRouteBuilder() {
+             @Override
+             public void configure() throws Exception {
+                 weaveByType(OnExceptionDefinition.class).after().to("mock:error");
+             }
+         });
+ 
+         getMockEndpoint("mock:error").expectedMessageCount(1);
+         getMockEndpoint("mock:result").expectedMessageCount(0);
+ 
+         template.sendBody("direct:start", "Hello World");
+ 
+         assertMockEndpointsSatisfied();
+     }
+ 
+     @Override
+     protected RouteBuilder createRouteBuilder() throws Exception {
+         return new RouteBuilder() {
+             @Override
+             public void configure() throws Exception {
+                 from("direct:start")
+                     .onException(Exception.class)
+                         .handled(true)
+                         .to("log:error")
+                     .end()
+                     .throwException(new IllegalArgumentException("Forced"))
+                     .to("mock:result");
+             }
+         };
+     }
+ }
diff --cc components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java
index 3dc5789,9841e6c..682cf82
--- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java
+++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java
@@@ -31,7 -32,8 +32,6 @@@ import org.apache.camel.api.management.
  import org.apache.camel.component.ResourceEndpoint;
  import org.apache.camel.spi.UriEndpoint;
  import org.apache.camel.spi.UriParam;
- import org.apache.camel.util.IOHelper;
 -import org.slf4j.Logger;
 -import org.slf4j.LoggerFactory;
  
  /**
   * Validates the payload of a message using NetworkNT JSON Schema library.
diff --cc components/camel-linkedin/camel-linkedin-component/src/main/java/org/apache/camel/component/linkedin/LinkedInComponent.java
index ad11fce,3d8f05d..297164b
--- a/components/camel-linkedin/camel-linkedin-component/src/main/java/org/apache/camel/component/linkedin/LinkedInComponent.java
+++ b/components/camel-linkedin/camel-linkedin-component/src/main/java/org/apache/camel/component/linkedin/LinkedInComponent.java
@@@ -22,9 -22,9 +22,10 @@@ import javax.net.ssl.SSLContext
  
  import org.apache.camel.CamelContext;
  import org.apache.camel.Endpoint;
 +import org.apache.camel.RuntimeCamelException;
  import org.apache.camel.component.linkedin.api.LinkedInOAuthRequestFilter;
  import org.apache.camel.component.linkedin.api.OAuthParams;
+ import org.apache.camel.component.linkedin.api.OAuthSecureStorage;
  import org.apache.camel.component.linkedin.internal.CachingOAuthSecureStorage;
  import org.apache.camel.component.linkedin.internal.LinkedInApiCollection;
  import org.apache.camel.component.linkedin.internal.LinkedInApiName;
diff --cc components/camel-netty4/src/main/docs/netty4-component.adoc
index 1b50653,0d62964..1381961
--- a/components/camel-netty4/src/main/docs/netty4-component.adoc
+++ b/components/camel-netty4/src/main/docs/netty4-component.adoc
@@@ -255,8 -249,14 +249,14 @@@ The component supports 78 options, whic
  | *camel.component.netty4.executor-service* | To use the given EventExecutorGroup. The option is a io.netty.util.concurrent.EventExecutorGroup type. |  | String
  | *camel.component.netty4.maximum-pool-size* | The thread pool size for the EventExecutorGroup if its in use. The default value is 16. | 16 | Integer
  | *camel.component.netty4.resolve-property-placeholders* | Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders. | true | Boolean
 -| *camel.component.netty4.ssl-context-parameters* | To configure security using SSLContextParameters. The option is a org.apache.camel.util.jsse.SSLContextParameters type. |  | String
 +| *camel.component.netty4.ssl-context-parameters* | To configure security using SSLContextParameters. The option is a org.apache.camel.support.jsse.SSLContextParameters type. |  | String
  | *camel.component.netty4.use-global-ssl-context-parameters* | Enable usage of global SSL context parameters. | false | Boolean
+ | *camel.component.netty4.configuration.client-pipeline-factory* | @deprecated use #setClientInitializerFactory |  | ClientInitializer Factory
+ | *camel.component.netty4.configuration.decoder* | A custom ChannelHandler class that can be used to perform special marshalling of inbound payloads. |  | ChannelHandler
+ | *camel.component.netty4.configuration.encoder* | A custom ChannelHandler class that can be used to perform special marshalling of outbound payloads. |  | ChannelHandler
+ | *camel.component.netty4.configuration.key-store-file* | Client side certificate keystore to be used for encryption |  | File
+ | *camel.component.netty4.configuration.server-pipeline-factory* | @deprecated use #setServerInitializerFactory |  | ServerInitializer Factory
+ | *camel.component.netty4.configuration.trust-store-file* | Server side certificate keystore to be used for encryption |  | File
  |===
  // spring-boot-auto-configure options: END
  
diff --cc components/pom.xml
index ed5bc0a,4356c93..a2917dc
--- a/components/pom.xml
+++ b/components/pom.xml
@@@ -200,8 -225,11 +200,9 @@@
      <module>camel-mybatis</module>
      <module>camel-nagios</module>
      <module>camel-nats</module>
 -    <module>camel-netty</module>
      <module>camel-netty4</module>
 -    <module>camel-netty-http</module>
      <module>camel-netty4-http</module>
+     <module>camel-nsq</module>
      <module>camel-ognl</module>
      <module>camel-olingo2</module>
      <module>camel-olingo4</module>
diff --cc docs/user-manual/en/SUMMARY.md
index e527294,9abdaca..462a656
--- a/docs/user-manual/en/SUMMARY.md
+++ b/docs/user-manual/en/SUMMARY.md
@@@ -339,8 -353,11 +338,9 @@@
  	* [MyBatis Bean](mybatis-bean-component.adoc)
  	* [Nagios](nagios-component.adoc)
  	* [Nats](nats-component.adoc)
 -	* [Netty](netty-component.adoc)
 -	* [Netty HTTP](netty-http-component.adoc)
  	* [Netty4](netty4-component.adoc)
  	* [Netty4 HTTP](netty4-http-component.adoc)
+ 	* [nsq](nsq-component.adoc)
  	* [Olingo2](olingo2-component.adoc)
  	* [Olingo4](olingo4-component.adoc)
  	* [OPC UA Client](milo-client-component.adoc)
@@@ -473,10 -508,14 +473,12 @@@
  	* [Bindy Fixed Length](bindy-dataformat.adoc)
  	* [Bindy Key Value Pair](bindy-dataformat.adoc)
  	* [Boon](boon-dataformat.adoc)
 -	* [Castor](castor-dataformat.adoc)
  	* [Crypto (Java Cryptographic Extension)](crypto-dataformat.adoc)
  	* [CSV](csv-dataformat.adoc)
+ 	* [FHIR JSon](fhirJson-dataformat.adoc)
+ 	* [FHIR XML](fhirXml-dataformat.adoc)
  	* [Flatpack](flatpack-dataformat.adoc)
  	* [GZip](gzip-dataformat.adoc)
 -	* [Hessian](hessian-dataformat.adoc)
  	* [HL7](hl7-dataformat.adoc)
  	* [iCal](ical-dataformat.adoc)
  	* [JacksonXML](jacksonxml-dataformat.adoc)
diff --cc platforms/spring-boot/components-starter/pom.xml
index 231b1ba,8208920..4329011
--- a/platforms/spring-boot/components-starter/pom.xml
+++ b/platforms/spring-boot/components-starter/pom.xml
@@@ -245,8 -265,11 +245,9 @@@
      <module>camel-mybatis-starter</module>
      <module>camel-nagios-starter</module>
      <module>camel-nats-starter</module>
 -    <module>camel-netty-http-starter</module>
 -    <module>camel-netty-starter</module>
      <module>camel-netty4-http-starter</module>
      <module>camel-netty4-starter</module>
+     <module>camel-nsq-starter</module>
      <module>camel-ognl-starter</module>
      <module>camel-olingo2-starter</module>
      <module>camel-olingo4-starter</module>


[camel] 04/08: Split internal services creation

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d1099089c4af691f649080693786101d9b4c13dd
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Nov 7 16:43:41 2018 +0100

    Split internal services creation
---
 ...CamelContext.java => AbstractCamelContext.java} |  856 ++--
 .../org/apache/camel/impl/DefaultCamelContext.java | 4587 +-------------------
 .../org/apache/camel/impl/DefaultDebugger.java     |   17 +-
 .../java/org/apache/camel/impl/RouteService.java   |    4 +-
 4 files changed, 521 insertions(+), 4943 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/AbstractCamelContext.java
similarity index 90%
copy from camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
copy to camel-core/src/main/java/org/apache/camel/impl/AbstractCamelContext.java
index 22b1f30..9bd47e2 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/AbstractCamelContext.java
@@ -33,7 +33,6 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
@@ -88,9 +87,6 @@ import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilderSupport;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.health.HealthCheckRegistry;
-import org.apache.camel.impl.converter.BaseTypeConverterRegistry;
-import org.apache.camel.impl.converter.DefaultTypeConverter;
-import org.apache.camel.impl.health.DefaultHealthCheckRegistry;
 import org.apache.camel.impl.transformer.TransformerKey;
 import org.apache.camel.impl.validator.ValidatorKey;
 import org.apache.camel.model.DataFormatDefinition;
@@ -112,7 +108,6 @@ import org.apache.camel.processor.interceptor.Debug;
 import org.apache.camel.processor.interceptor.HandleFault;
 import org.apache.camel.reifier.RouteReifier;
 import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
-import org.apache.camel.runtimecatalog.impl.DefaultRuntimeCamelCatalog;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.CamelContextTracker;
@@ -139,7 +134,6 @@ import org.apache.camel.spi.LogListener;
 import org.apache.camel.spi.ManagementMBeanAssembler;
 import org.apache.camel.spi.ManagementNameStrategy;
 import org.apache.camel.spi.ManagementStrategy;
-import org.apache.camel.spi.ManagementStrategyFactory;
 import org.apache.camel.spi.MessageHistoryFactory;
 import org.apache.camel.spi.ModelJAXBContextFactory;
 import org.apache.camel.spi.NodeIdFactory;
@@ -151,7 +145,6 @@ import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestRegistry;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.RouteController;
-import org.apache.camel.spi.RouteError;
 import org.apache.camel.spi.RouteError.Phase;
 import org.apache.camel.spi.RoutePolicyFactory;
 import org.apache.camel.spi.RouteStartupOrder;
@@ -191,16 +184,16 @@ import static org.apache.camel.impl.MDCUnitOfWork.MDC_CAMEL_CONTEXT_ID;
 /**
  * Represents the context used to configure routes and the policies to use.
  */
-public class DefaultCamelContext extends ServiceSupport implements ModelCamelContext, Suspendable {
+public abstract class AbstractCamelContext extends ServiceSupport implements ModelCamelContext, Suspendable {
+
+    public enum Initialization {
+        Eager, Default, Lazy
+    }
 
     private String version;
     private final AtomicBoolean vetoStated = new AtomicBoolean();
-    private JAXBContext jaxbContext;
-    private CamelContextNameStrategy nameStrategy;
-    private ManagementNameStrategy managementNameStrategy;
     private String managementName;
     private ClassLoader applicationContextClassLoader;
-    private EndpointRegistry<EndpointKey> endpoints;
     private final AtomicInteger endpointKeyCounter = new AtomicInteger();
     private final List<EndpointStrategy> endpointStrategies = new ArrayList<>();
     private final Map<String, Component> components = new ConcurrentHashMap<>();
@@ -208,32 +201,23 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     private final List<Service> servicesToStop = new CopyOnWriteArrayList<>();
     private final List<StartupListener> startupListeners = new CopyOnWriteArrayList<>();
     private final DeferServiceStartupListener deferStartupListener = new DeferServiceStartupListener();
-    private TypeConverter typeConverter;
-    private TypeConverterRegistry typeConverterRegistry;
-    private Injector injector;
-    private ComponentResolver componentResolver;
     private boolean autoCreateComponents = true;
-    private LanguageResolver languageResolver;
-    private final Map<String, Language> languages = new HashMap<>();
-    private Registry registry;
-    private List<LifecycleStrategy> lifecycleStrategies = new CopyOnWriteArrayList<>();
-    private ManagementStrategy managementStrategy;
-    private ManagementMBeanAssembler managementMBeanAssembler;
+    private final Map<String, Language> languages = new ConcurrentHashMap<>();
+    private final List<LifecycleStrategy> lifecycleStrategies = new CopyOnWriteArrayList<>();
     private final List<RouteDefinition> routeDefinitions = new ArrayList<>();
     private final List<RestDefinition> restDefinitions = new ArrayList<>();
     private Map<String, RestConfiguration> restConfigurations = new ConcurrentHashMap<>();
     private Map<String, ServiceCallConfigurationDefinition> serviceCallConfigurations = new ConcurrentHashMap<>();
     private Map<String, HystrixConfigurationDefinition> hystrixConfigurations = new ConcurrentHashMap<>();
-    private RestRegistry restRegistry = new DefaultRestRegistry();
     private List<InterceptStrategy> interceptStrategies = new ArrayList<>();
     private List<RoutePolicyFactory> routePolicyFactories = new ArrayList<>();
     private Set<LogListener> logListeners = new LinkedHashSet<>();
-    private HeadersMapFactory headersMapFactory;
     // special flags to control the first startup which can are special
     private volatile boolean firstStartDone;
     private volatile boolean doNotStartRoutesOnFirstStart;
     private final ThreadLocal<Boolean> isStartingRoutes = new ThreadLocal<>();
     private final ThreadLocal<Boolean> isSetupRoutes = new ThreadLocal<>();
+    private Initialization initialization = Initialization.Default;
     private Boolean autoStartup = Boolean.TRUE;
     private Boolean trace = Boolean.FALSE;
     private Boolean messageHistory = Boolean.TRUE;
@@ -253,45 +237,62 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     private final Object errorHandlerExecutorServiceLock = new Object();
     private ScheduledExecutorService errorHandlerExecutorService;
     private Map<String, DataFormatDefinition> dataFormats = new HashMap<>();
-    private DataFormatResolver dataFormatResolver;
     private Map<String, String> globalOptions = new HashMap<>();
-    private FactoryFinderResolver factoryFinderResolver;
-    private FactoryFinder defaultFactoryFinder;
     private PropertiesComponent propertiesComponent;
-    private StreamCachingStrategy streamCachingStrategy;
-    private final Map<String, FactoryFinder> factories = new HashMap<>();
+    private final Map<String, FactoryFinder> factories = new ConcurrentHashMap<>();
     private final Map<String, RouteService> routeServices = new LinkedHashMap<>();
     private final Map<String, RouteService> suspendedRouteServices = new LinkedHashMap<>();
-    private ClassResolver classResolver = createClassResolver();
-    private PackageScanClassResolver packageScanClassResolver;
-    // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool
-    // so if we have 6 endpoints in the pool, we can have 6 x 100 producers in total
-    private ServicePool<Producer> producerServicePool;
-    private ServicePool<PollingConsumer> pollingConsumerServicePool;
-    private NodeIdFactory nodeIdFactory;
-    private ProcessorFactory processorFactory;
-    private MessageHistoryFactory messageHistoryFactory;
-    private InflightRepository inflightRepository;
-    private AsyncProcessorAwaitManager asyncProcessorAwaitManager;
+
+    private volatile CamelContextNameStrategy nameStrategy;
+    private volatile ManagementNameStrategy managementNameStrategy;
+    private Registry registry;
+
+    private volatile TypeConverter typeConverter;
+    private volatile TypeConverterRegistry typeConverterRegistry;
+    private volatile Injector injector;
+    private volatile ComponentResolver componentResolver;
+    private volatile LanguageResolver languageResolver;
+    private volatile DataFormatResolver dataFormatResolver;
+    private volatile ManagementStrategy managementStrategy;
+    private volatile ManagementMBeanAssembler managementMBeanAssembler;
+    private volatile RestRegistry restRegistry;
+    private volatile HeadersMapFactory headersMapFactory;
+    private volatile ClassResolver classResolver;
+    private volatile PackageScanClassResolver packageScanClassResolver;
+    private volatile ServicePool<Producer> producerServicePool;
+    private volatile ServicePool<PollingConsumer> pollingConsumerServicePool;
+    private volatile NodeIdFactory nodeIdFactory;
+    private volatile ProcessorFactory processorFactory;
+    private volatile MessageHistoryFactory messageHistoryFactory;
+    private volatile FactoryFinderResolver factoryFinderResolver;
+    private volatile FactoryFinder defaultFactoryFinder;
+    private volatile StreamCachingStrategy streamCachingStrategy;
+    private volatile InflightRepository inflightRepository;
+    private volatile AsyncProcessorAwaitManager asyncProcessorAwaitManager;
+    private volatile ShutdownStrategy shutdownStrategy;
+    private volatile ModelJAXBContextFactory modelJAXBContextFactory;
+    private volatile ExecutorServiceManager executorServiceManager;
+    private volatile UuidGenerator uuidGenerator;
+    private volatile UnitOfWorkFactory unitOfWorkFactory;
+    private volatile ReloadStrategy reloadStrategy;
+    private volatile RouteController routeController;
+
+    private TransformerRegistry<TransformerKey> transformerRegistry;
+    private ValidatorRegistry<ValidatorKey> validatorRegistry;
+    private EndpointRegistry<EndpointKey> endpoints;
     private RuntimeEndpointRegistry runtimeEndpointRegistry;
+
     private final List<RouteStartupOrder> routeStartupOrder = new ArrayList<>();
     // start auto assigning route ids using numbering 1000 and upwards
     private int defaultRouteStartupOrder = 1000;
-    private ShutdownStrategy shutdownStrategy;
     private ShutdownRoute shutdownRoute = ShutdownRoute.Default;
     private ShutdownRunningTask shutdownRunningTask = ShutdownRunningTask.CompleteCurrentTaskOnly;
-    private ExecutorServiceManager executorServiceManager;
     private Debugger debugger;
-    private UuidGenerator uuidGenerator;
-    private UnitOfWorkFactory unitOfWorkFactory;
     private final StopWatch stopWatch = new StopWatch(false);
     private Date startDate;
-    private ModelJAXBContextFactory modelJAXBContextFactory;
     private List<TransformerDefinition> transformers = new ArrayList<>();
-    private TransformerRegistry<TransformerKey> transformerRegistry;
     private List<ValidatorDefinition> validators = new ArrayList<>();
-    private ValidatorRegistry<ValidatorKey> validatorRegistry;
-    private ReloadStrategy reloadStrategy;
+
     private SSLContextParameters sslContextParameters;
     private final ThreadLocal<Set<String>> componentsInCreation = new ThreadLocal<Set<String>>() {
         @Override
@@ -299,7 +300,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
             return new HashSet<>();
         }
     };
-    private RouteController routeController = createRouteController();
     private Map<Class<?>, Object> extensions = new ConcurrentHashMap<>();
 
     /**
@@ -308,7 +308,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
      * <p/>
      * Use one of the other constructors to force use an explicit registry / JNDI.
      */
-    public DefaultCamelContext() {
+    public AbstractCamelContext() {
         this(true);
     }
 
@@ -317,7 +317,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
      *
      * @param jndiContext the JNDI context
      */
-    public DefaultCamelContext(Context jndiContext) {
+    public AbstractCamelContext(Context jndiContext) {
         this();
         setJndiContext(jndiContext);
     }
@@ -327,12 +327,12 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
      *
      * @param registry the registry
      */
-    public DefaultCamelContext(Registry registry) {
+    public AbstractCamelContext(Registry registry) {
         this();
         setRegistry(registry);
     }
 
-    public DefaultCamelContext(boolean init) {
+    public AbstractCamelContext(boolean init) {
         // create a provisional (temporary) endpoint registry at first since end users may access endpoints before CamelContext is started
         // we will later transfer the endpoints to the actual DefaultEndpointRegistry later, but we do this to starup Camel faster.
         this.endpoints = new ProvisionalEndpointRegistry();
@@ -349,64 +349,9 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public void doInit() {
-        if (nameStrategy == null) {
-            nameStrategy = createCamelContextNameStrategy();
-        }
-        if (managementNameStrategy == null) {
-            managementNameStrategy = createManagementNameStrategy();
-        }
-        if (headersMapFactory == null) {
-            headersMapFactory = createHeadersMapFactory();
-        }
-        if (classResolver == null) {
-            classResolver = createClassResolver();
-        }
-        if (producerServicePool == null) {
-            producerServicePool = createProducerServicePool();
-        }
-        if (pollingConsumerServicePool == null) {
-            pollingConsumerServicePool = createPollingConsumerServicePool();
-        }
-        if (nodeIdFactory == null){
-            nodeIdFactory = createNodeIdFactory();
-        }
-        if (processorFactory == null) {
-            processorFactory = createProcessorFactory();
-        }
-        if (messageHistoryFactory == null) {
-            messageHistoryFactory = createMessageHistoryFactory();
-        }
-        if (inflightRepository == null) {
-            inflightRepository = createInflightRepository();
-        }
-        if (asyncProcessorAwaitManager == null) {
-            asyncProcessorAwaitManager = createAsyncProcessorAwaitManager();
-        }
-        if (shutdownStrategy == null) {
-            shutdownStrategy = createShutdownStrategy();
-        }
-        if (uuidGenerator == null) {
-            uuidGenerator = createDefaultUuidGenerator();
-        }
-        if (unitOfWorkFactory == null) {
-            unitOfWorkFactory = createUnitOfWorkFactory();
-        }
-        if (executorServiceManager == null) {
-            executorServiceManager = createExecutorServiceManager();
-        }
-        if (packageScanClassResolver == null) {
-            packageScanClassResolver = createPackageScanClassResolver();
-        }
-        if (managementStrategy == null) {
-            // setup management strategy first since end users may use it to add event notifiers
-            // using the management strategy before the CamelContext has been started
-            managementStrategy = createManagementStrategy();
-        }
-
         // Call all registered trackers with this context
         // Note, this may use a partially constructed object
         CamelContextTracker.notifyContextCreated(this);
-
     }
 
     public <T extends CamelContext> T adapt(Class<T> type) {
@@ -417,7 +362,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     public <T> T getExtension(Class<T> type) {
         Object extension = extensions.get(type);
         if (extension instanceof Supplier) {
-            extension = ((Supplier<T>) extension).get();
+            extension = ((Supplier) extension).get();
             setExtension(type, (T) extension);
         }
         return (T) extension;
@@ -426,8 +371,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     @Override
     public <T> void setExtension(Class<T> type, T module) {
         try {
-            addService(module, true, true);
-            extensions.put(type, module);
+            extensions.put(type, doAddService(module));
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
@@ -441,8 +385,16 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return vetoStated.get();
     }
 
+    public Initialization getInitialization() {
+        return initialization;
+    }
+
+    public void setInitialization(Initialization initialization) {
+        this.initialization = initialization;
+    }
+
     public String getName() {
-        return getNameStrategy() != null ? getNameStrategy().getName() : null;
+        return getNameStrategy().getName();
     }
 
     /**
@@ -452,23 +404,37 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
      */
     public void setName(String name) {
         // use an explicit name strategy since an explicit name was provided to be used
-        this.nameStrategy = new ExplicitCamelContextNameStrategy(name);
+        setNameStrategy(new ExplicitCamelContextNameStrategy(name));
     }
 
     public CamelContextNameStrategy getNameStrategy() {
+        if (nameStrategy == null) {
+            synchronized (this) {
+                if (nameStrategy == null) {
+                    setNameStrategy(createCamelContextNameStrategy());
+                }
+            }
+        }
         return nameStrategy;
     }
 
     public void setNameStrategy(CamelContextNameStrategy nameStrategy) {
-        this.nameStrategy = nameStrategy;
+        this.nameStrategy = doAddService(nameStrategy);
     }
 
     public ManagementNameStrategy getManagementNameStrategy() {
+        if (managementNameStrategy == null) {
+            synchronized (this) {
+                if (managementNameStrategy == null) {
+                    setManagementNameStrategy(createManagementNameStrategy());
+                }
+            }
+        }
         return managementNameStrategy;
     }
 
     public void setManagementNameStrategy(ManagementNameStrategy managementNameStrategy) {
-        this.managementNameStrategy = managementNameStrategy;
+        this.managementNameStrategy = doAddService(managementNameStrategy);
     }
 
     public String getManagementName() {
@@ -530,7 +496,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 @Override
                 public Component apply(String comp) {
                     created.set(true);
-                    return DefaultCamelContext.this.initComponent(name, autoCreateComponents);
+                    return AbstractCamelContext.this.initComponent(name, autoCreateComponents);
                 }
             });
 
@@ -936,12 +902,18 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     @Override
     public void setRouteController(RouteController routeController) {
-        this.routeController = routeController;
-        this.routeController.setCamelContext(this);
+        this.routeController = doAddService(routeController);
     }
 
     @Override
     public RouteController getRouteController() {
+        if (routeController == null) {
+            synchronized (this) {
+                if (routeController == null) {
+                    setRouteController(createRouteController());
+                }
+            }
+        }
         return routeController;
     }
 
@@ -1025,7 +997,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     public void addRoutes(final RoutesBuilder builder) throws Exception {
         init();
         log.debug("Adding routes from builder: {}", builder);
-        doWithDefinedClassLoader(() -> builder.addRoutesToCamelContext(DefaultCamelContext.this));
+        doWithDefinedClassLoader(() -> builder.addRoutesToCamelContext(AbstractCamelContext.this));
     }
 
     public synchronized RoutesDefinition loadRoutesDefinition(InputStream is) throws Exception {
@@ -1034,12 +1006,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     public synchronized RestsDefinition loadRestsDefinition(InputStream is) throws Exception {
         // load routes using JAXB
-        if (jaxbContext == null) {
-            // must use classloader from CamelContext to have JAXB working
-            jaxbContext = getModelJAXBContextFactory().newJAXBContext();
-        }
-
-        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+        Unmarshaller unmarshaller = getModelJAXBContextFactory().newJAXBContext().createUnmarshaller();
         Object result = unmarshaller.unmarshal(is);
 
         if (result == null) {
@@ -1088,7 +1055,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         Iterator<RouteDefinition> iter = routeDefinitions.iterator();
         while (iter.hasNext()) {
             RouteDefinition route = iter.next();
-            if (route.idOrCreate(nodeIdFactory).equals(key)) {
+            if (route.idOrCreate(getNodeIdFactory()).equals(key)) {
                 iter.remove();
                 answer = true;
             }
@@ -1169,7 +1136,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
             try {
                 startRouteService(routeService, false);
             } catch (Exception e) {
-                DefaultRouteError.set(this, routeId, RouteError.Phase.START, e);
+                DefaultRouteError.set(this, routeId, Phase.START, e);
                 throw e;
             }
         }
@@ -1193,7 +1160,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 ServiceHelper.resumeService(route);
             }
         } catch (Exception e) {
-            DefaultRouteError.set(this, routeId, RouteError.Phase.RESUME, e);
+            DefaultRouteError.set(this, routeId, Phase.RESUME, e);
             throw e;
         }
     }
@@ -1216,7 +1183,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 }
                 return completed;
             } catch (Exception e) {
-                DefaultRouteError.set(this, routeId, RouteError.Phase.STOP, e);
+                DefaultRouteError.set(this, routeId, Phase.STOP, e);
                 throw e;
             }
         }
@@ -1300,7 +1267,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                         removeEndpoint(endpoint);
                     }
                 } catch  (Exception e) {
-                    DefaultRouteError.set(this, routeId, RouteError.Phase.REMOVE, e);
+                    DefaultRouteError.set(this, routeId, Phase.REMOVE, e);
                     throw e;
                 }
 
@@ -1341,7 +1308,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 }
             }
         } catch (Exception e) {
-            DefaultRouteError.set(this, routeId, RouteError.Phase.SUSPEND, e);
+            DefaultRouteError.set(this, routeId, Phase.SUSPEND, e);
             throw e;
         }
     }
@@ -1351,15 +1318,32 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public void addService(Object object, boolean stopOnShutdown) throws Exception {
-        doAddService(object, stopOnShutdown, false);
+        addService(object, stopOnShutdown, false);
     }
 
     @Override
     public void addService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception {
-        doAddService(object, stopOnShutdown, forceStart);
+        internalAddService(object, stopOnShutdown, forceStart);
+    }
+
+    protected <T> T doAddService(T object) {
+        return doAddService(object, true);
+    }
+
+    protected <T> T doAddService(T object, boolean stopOnShutdown) {
+        return doAddService(object, stopOnShutdown, true);
+    }
+
+    protected <T> T doAddService(T object, boolean stopOnShutdown, boolean forceStart) {
+        try {
+            internalAddService(object, stopOnShutdown, forceStart);
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+        return object;
     }
 
-    private void doAddService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception {
+    private void internalAddService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception {
 
         // inject CamelContext
         if (object instanceof CamelContextAware) {
@@ -2468,14 +2452,8 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     public TypeConverter getTypeConverter() {
         if (typeConverter == null) {
             synchronized (this) {
-                // we can synchronize on this as there is only one instance
-                // of the camel context (its the container)
-                typeConverter = createTypeConverter();
-                try {
-                    // must add service eager and force start it
-                    addService(typeConverter, true, true);
-                } catch (Exception e) {
-                    throw RuntimeCamelException.wrapRuntimeCamelException(e);
+                if (typeConverter == null) {
+                    setTypeConverter(createTypeConverter());
                 }
             }
         }
@@ -2483,41 +2461,37 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public void setTypeConverter(TypeConverter typeConverter) {
-        this.typeConverter = typeConverter;
-        try {
-            // must add service eager and force start it
-            addService(typeConverter, true, true);
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeCamelException(e);
-        }
+        this.typeConverter = doAddService(typeConverter);
     }
 
     public TypeConverterRegistry getTypeConverterRegistry() {
         if (typeConverterRegistry == null) {
-            // init type converter as its lazy
-            if (typeConverter == null) {
-                getTypeConverter();
-            }
-            if (typeConverter instanceof TypeConverterRegistry) {
-                typeConverterRegistry = (TypeConverterRegistry) typeConverter;
+            synchronized (this) {
+                if (typeConverter == null) {
+                    setTypeConverterRegistry(createTypeConverterRegistry());
+                }
             }
         }
         return typeConverterRegistry;
     }
 
     public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) {
-        this.typeConverterRegistry = typeConverterRegistry;
+        this.typeConverterRegistry = doAddService(typeConverterRegistry);
     }
 
     public Injector getInjector() {
         if (injector == null) {
-            injector = createInjector();
+            synchronized (this) {
+                if (injector == null) {
+                    setInjector(createInjector());
+                }
+            }
         }
         return injector;
     }
 
     public void setInjector(Injector injector) {
-        this.injector = injector;
+        this.injector = doAddService(injector);
     }
 
     public ManagementMBeanAssembler getManagementMBeanAssembler() {
@@ -2525,29 +2499,37 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public void setManagementMBeanAssembler(ManagementMBeanAssembler managementMBeanAssembler) {
-        this.managementMBeanAssembler = managementMBeanAssembler;
+        this.managementMBeanAssembler = doAddService(managementMBeanAssembler, false);
     }
 
     public ComponentResolver getComponentResolver() {
         if (componentResolver == null) {
-            componentResolver = createComponentResolver();
+            synchronized (this) {
+                if (componentResolver == null) {
+                    setComponentResolver(createComponentResolver());
+                }
+            }
         }
         return componentResolver;
     }
 
     public void setComponentResolver(ComponentResolver componentResolver) {
-        this.componentResolver = componentResolver;
+        this.componentResolver = doAddService(componentResolver);
     }
 
     public LanguageResolver getLanguageResolver() {
         if (languageResolver == null) {
-            languageResolver = createLanguageResolver();
+            synchronized (this) {
+                if (languageResolver == null) {
+                    setLanguageResolver(createLanguageResolver());
+                }
+            }
         }
         return languageResolver;
     }
 
     public void setLanguageResolver(LanguageResolver languageResolver) {
-        this.languageResolver = languageResolver;
+        this.languageResolver = doAddService(languageResolver);
     }
 
     public boolean isAutoCreateComponents() {
@@ -2560,8 +2542,11 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     public Registry getRegistry() {
         if (registry == null) {
-            registry = createRegistry();
-            setRegistry(registry);
+            synchronized (this) {
+                if (registry == null) {
+                    setRegistry(createRegistry());
+                }
+            }
         }
         return registry;
     }
@@ -2591,7 +2576,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
      * Sets the registry to the given JNDI context
      *
      * @param jndiContext is the JNDI context to use as the registry
-     * @see #setRegistry(org.apache.camel.spi.Registry)
+     * @see #setRegistry(Registry)
      */
     public void setJndiContext(Context jndiContext) {
         setRegistry(new JndiRegistry(jndiContext));
@@ -2609,12 +2594,8 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return lifecycleStrategies;
     }
 
-    public void setLifecycleStrategies(List<LifecycleStrategy> lifecycleStrategies) {
-        this.lifecycleStrategies = lifecycleStrategies;
-    }
-
     public void addLifecycleStrategy(LifecycleStrategy lifecycleStrategy) {
-        this.lifecycleStrategies.add(lifecycleStrategy);
+        getLifecycleStrategies().add(lifecycleStrategy);
     }
 
     public void setupRoutes(boolean done) {
@@ -2631,7 +2612,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     public synchronized RouteDefinition getRouteDefinition(String id) {
         for (RouteDefinition route : routeDefinitions) {
-            if (route.idOrCreate(nodeIdFactory).equals(id)) {
+            if (route.idOrCreate(getNodeIdFactory()).equals(id)) {
                 return route;
             }
         }
@@ -2899,27 +2880,48 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public void setProducerServicePool(ServicePool<Producer> producerServicePool) {
-        this.producerServicePool = producerServicePool;
+        this.producerServicePool = doAddService(producerServicePool);
     }
 
     public ServicePool<Producer> getProducerServicePool() {
+        if (producerServicePool == null) {
+            synchronized (this) {
+                if (producerServicePool == null) {
+                    setProducerServicePool(createProducerServicePool());
+                }
+            }
+        }
         return producerServicePool;
     }
 
     public ServicePool<PollingConsumer> getPollingConsumerServicePool() {
+        if (pollingConsumerServicePool == null) {
+            synchronized (this) {
+                if (pollingConsumerServicePool == null) {
+                    setPollingConsumerServicePool(createPollingConsumerServicePool());
+                }
+            }
+        }
         return pollingConsumerServicePool;
     }
 
     public void setPollingConsumerServicePool(ServicePool<PollingConsumer> pollingConsumerServicePool) {
-        this.pollingConsumerServicePool = pollingConsumerServicePool;
+        this.pollingConsumerServicePool = doAddService(pollingConsumerServicePool);
     }
 
     public UnitOfWorkFactory getUnitOfWorkFactory() {
+        if (unitOfWorkFactory == null) {
+            synchronized (this) {
+                if (unitOfWorkFactory == null) {
+                    setUnitOfWorkFactory(createUnitOfWorkFactory());
+                }
+            }
+        }
         return unitOfWorkFactory;
     }
 
     public void setUnitOfWorkFactory(UnitOfWorkFactory unitOfWorkFactory) {
-        this.unitOfWorkFactory = unitOfWorkFactory;
+        this.unitOfWorkFactory = doAddService(unitOfWorkFactory);
     }
 
     public RuntimeEndpointRegistry getRuntimeEndpointRegistry() {
@@ -2927,7 +2929,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public void setRuntimeEndpointRegistry(RuntimeEndpointRegistry runtimeEndpointRegistry) {
-        this.runtimeEndpointRegistry = runtimeEndpointRegistry;
+        this.runtimeEndpointRegistry = doAddService(runtimeEndpointRegistry);
     }
 
     public String getUptime() {
@@ -3191,7 +3193,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 doStartCamel();
             } catch (Exception e) {
                 // fire event that we failed to start
-                EventHelper.notifyCamelContextStartupFailed(DefaultCamelContext.this, e);
+                EventHelper.notifyCamelContextStartupFailed(AbstractCamelContext.this, e);
                 // rethrow cause
                 throw e;
             }
@@ -3230,10 +3232,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
             }
         }
 
-        if (classResolver instanceof CamelContextAware) {
-            ((CamelContextAware) classResolver).setCamelContext(this);
-        }
-
         if (log.isDebugEnabled()) {
             log.debug("Using ClassResolver={}, PackageScanClassResolver={}, ApplicationContextClassLoader={}, RouteController={}",
                 getClassResolver(), getPackageScanClassResolver(), getApplicationContextClassLoader(), getRouteController());
@@ -3268,9 +3266,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         // register debugger
         if (getDebugger() != null) {
             log.info("Debugger: {} is enabled on CamelContext: {}", getDebugger(), getName());
-            // register this camel context on the debugger
-            getDebugger().setCamelContext(this);
-            startService(getDebugger());
             addInterceptStrategy(new Debug(getDebugger()));
         }
 
@@ -3311,21 +3306,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
         forceLazyInitialization();
 
-        // re-create endpoint registry as the cache size limit may be set after the constructor of this instance was called.
-        // and we needed to create endpoints up-front as it may be accessed before this context is started
-        endpoints = createEndpointRegistry(endpoints);
-        // add this as service and force pre-start them
-        addService(endpoints, true, true);
-        // special for executorServiceManager as want to stop it manually so false in stopOnShutdown
-        addService(executorServiceManager, false, true);
-        addService(producerServicePool, true, true);
-        addService(pollingConsumerServicePool, true, true);
-        addService(inflightRepository, true, true);
-        addService(asyncProcessorAwaitManager, true, true);
-        addService(shutdownStrategy, true, true);
-        addService(packageScanClassResolver, true, true);
-        addService(restRegistry, true, true);
-        addService(messageHistoryFactory, true, true);
         if (reloadStrategy != null) {
             log.info("Using ReloadStrategy: {}", reloadStrategy);
             addService(reloadStrategy, true, true);
@@ -3334,11 +3314,13 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         // Start runtime catalog
         getExtension(RuntimeCamelCatalog.class);
 
-        // Initialize declarative transformer/validator registry
-        transformerRegistry = createTransformerRegistry(transformers);
-        addService(transformerRegistry, true, true);
-        validatorRegistry = createValidatorRegistry(validators);
-        addService(validatorRegistry, true, true);
+        // re-create endpoint registry as the cache size limit may be set after the constructor of this instance was called.
+        // and we needed to create endpoints up-front as it may be accessed before this context is started
+        endpoints = doAddService(createEndpointRegistry(endpoints));
+        // Initialize declarative transformer registry
+        transformerRegistry = doAddService(createTransformerRegistry(transformers));
+        // Initialize declarative validator registry
+        validatorRegistry = doAddService(createValidatorRegistry(validators));
 
         // optimised to not include runtimeEndpointRegistry unlesstartServices its enabled or JMX statistics is in extended mode
         if (runtimeEndpointRegistry == null && getManagementStrategy() != null && getManagementStrategy().getManagementAgent() != null) {
@@ -3376,6 +3358,11 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         // start the route definitions before the routes is started
         startRouteDefinitions(routeDefinitions);
 
+        if (isUseDataType()) {
+            // log if DataType has been enabled
+            log.info("Message DataType is enabled on CamelContext: {}", getName());
+        }
+
         // is there any stream caching enabled then log an info about this and its limit of spooling to disk, so people is aware of this
         boolean streamCachingInUse = isStreamCaching();
         if (!streamCachingInUse) {
@@ -3387,16 +3374,9 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 }
             }
         }
-
-        if (isUseDataType()) {
-            // log if DataType has been enabled
-            log.info("Message DataType is enabled on CamelContext: {}", getName());
-        }
-
         if (streamCachingInUse) {
             // stream caching is in use so enable the strategy
             getStreamCachingStrategy().setEnabled(true);
-            addService(getStreamCachingStrategy(), true, true);
         } else {
             // log if stream caching is not in use as this can help people to enable it if they use streams
             log.info("StreamCaching is not in use. If using streams then its recommended to enable stream caching."
@@ -3407,13 +3387,8 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
             log.debug("AllowUseOriginalMessage enabled because UseOriginalMessage is in use");
         }
 
-        // use resolver to find the headers map factory to be used, if we are using the default
-        if (headersMapFactory instanceof DefaultHeadersMapFactory) {
-            headersMapFactory = new HeadersMapFactoryResolver().resolve(this);
-        }
-
-        log.debug("Using HeadersMapFactory: {}", headersMapFactory);
-        if (!headersMapFactory.isCaseInsensitive()) {
+        log.debug("Using HeadersMapFactory: {}", getHeadersMapFactory());
+        if (!getHeadersMapFactory().isCaseInsensitive()) {
             log.info("HeadersMapFactory: {} is case-sensitive which can cause problems for protocols such as HTTP based, which rely on case-insensitive headers.", getHeadersMapFactory());
         }
 
@@ -3826,7 +3801,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     /**
-     * @see #safelyStartRouteServices(boolean,boolean,boolean,boolean,java.util.Collection)
+     * @see #safelyStartRouteServices(boolean,boolean,boolean,boolean,Collection)
      */
     protected synchronized void safelyStartRouteServices(boolean forceAutoStart, boolean checkClash, boolean startConsumer,
                                                          boolean resumeConsumer, boolean addingRoutes, RouteService... routeServices) throws Exception {
@@ -4018,18 +3993,50 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
      * components and create routes
      */
     protected void forceLazyInitialization() {
-        getRegistry();
-        getInjector();
-        getLanguageResolver();
-        getTypeConverterRegistry();
-        getTypeConverter();
+        if (initialization != Initialization.Lazy) {
+            getTypeConverter();
+            getTypeConverterRegistry();
+            getInjector();
+            getRegistry();
+            getLanguageResolver();
+            getExecutorServiceManager();
+            getInflightRepository();
+            getAsyncProcessorAwaitManager();
+            getShutdownStrategy();
+            getPackageScanClassResolver();
+            getProducerServicePool();
+            getPollingConsumerServicePool();
+
+            if (isTypeConverterStatisticsEnabled() != null) {
+                getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled());
+            }
 
-        if (isTypeConverterStatisticsEnabled() != null) {
-            getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled());
+            // resolve simple language to initialize it
+            resolveLanguage("simple");
+
+            // Start runtime catalog
+            getExtension(RuntimeCamelCatalog.class);
+
+            if (initialization == Initialization.Eager) {
+                getExtension(HealthCheckRegistry.class);
+                getComponentResolver();
+                getDataFormatResolver();
+                getManagementStrategy();
+                getRestRegistry();
+                getHeadersMapFactory();
+                getClassResolver();
+                getNodeIdFactory();
+                getProcessorFactory();
+                getMessageHistoryFactory();
+                getFactoryFinderResolver();
+                getDefaultFactoryFinder();
+                getStreamCachingStrategy();
+                getModelJAXBContextFactory();
+                getUuidGenerator();
+                getUnitOfWorkFactory();
+                getRouteController();
+            }
         }
-
-        // resolve simple language to initialize it
-        resolveLanguage("simple");
     }
 
     /**
@@ -4043,52 +4050,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     /**
-     * Lazily create a default implementation
-     */
-    protected TypeConverter createTypeConverter() {
-        BaseTypeConverterRegistry answer;
-        answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder(), isLoadTypeConverters());
-        answer.setCamelContext(this);
-        setTypeConverterRegistry(answer);
-        return answer;
-    }
-
-    /**
-     * Lazily create a default implementation
-     */
-    protected Injector createInjector() {
-        FactoryFinder finder = getDefaultFactoryFinder();
-        try {
-            return (Injector) finder.newInstance("Injector");
-        } catch (NoFactoryAvailableException e) {
-            // lets use the default injector
-            return new DefaultInjector(this);
-        }
-    }
-
-    /**
-     * Lazily create a default implementation
-     */
-    protected ComponentResolver createComponentResolver() {
-        return new DefaultComponentResolver();
-    }
-
-    /**
-     * Lazily create a default implementation
-     */
-    protected Registry createRegistry() {
-        JndiRegistry jndi = new JndiRegistry();
-        try {
-            // getContext() will force setting up JNDI
-            jndi.getContext();
-            return jndi;
-        } catch (Throwable e) {
-            log.debug("Cannot create javax.naming.InitialContext due " + e.getMessage() + ". Will fallback and use SimpleRegistry instead. This exception is ignored.", e);
-            return new SimpleRegistry();
-        }
-    }
-
-    /**
      * A pluggable strategy to allow an endpoint to be created without requiring
      * a component to be its factory, such as for looking up the URI inside some
      * {@link Registry}
@@ -4155,87 +4116,114 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     public FactoryFinder getDefaultFactoryFinder() {
         if (defaultFactoryFinder == null) {
-            defaultFactoryFinder = getFactoryFinderResolver().resolveDefaultFactoryFinder(getClassResolver());
+            synchronized (this) {
+                if (defaultFactoryFinder == null) {
+                    defaultFactoryFinder = getFactoryFinderResolver().resolveDefaultFactoryFinder(getClassResolver());
+                }
+            }
         }
         return defaultFactoryFinder;
     }
 
     public FactoryFinderResolver getFactoryFinderResolver() {
         if (factoryFinderResolver == null) {
-            factoryFinderResolver = createFactoryFinderResolver();
+            synchronized (this) {
+                if (factoryFinderResolver == null) {
+                    factoryFinderResolver = createFactoryFinderResolver();
+                }
+            }
         }
         return factoryFinderResolver;
     }
 
-    public void setFactoryFinderResolver(FactoryFinderResolver resolver) {
-        this.factoryFinderResolver = resolver;
+    public void setFactoryFinderResolver(FactoryFinderResolver factoryFinderResolver) {
+        this.factoryFinderResolver = doAddService(factoryFinderResolver);
     }
 
     public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException {
-        synchronized (factories) {
-            FactoryFinder answer = factories.get(path);
-            if (answer == null) {
-                answer = getFactoryFinderResolver().resolveFactoryFinder(getClassResolver(), path);
-                factories.put(path, answer);
-            }
-            return answer;
-        }
+        return factories.computeIfAbsent(path, this::createFactoryFinder);
+    }
+
+    protected FactoryFinder createFactoryFinder(String path) {
+        return getFactoryFinderResolver().resolveFactoryFinder(getClassResolver(), path);
     }
 
     public ClassResolver getClassResolver() {
+        if (classResolver == null) {
+            synchronized (this) {
+                if (classResolver == null) {
+                    setClassResolver(createClassResolver());
+                }
+            }
+        }
         return classResolver;
     }
 
     public void setClassResolver(ClassResolver classResolver) {
-        this.classResolver = classResolver;
+        this.classResolver = doAddService(classResolver);
     }
 
     public PackageScanClassResolver getPackageScanClassResolver() {
+        if (packageScanClassResolver == null) {
+            synchronized (this) {
+                if (packageScanClassResolver == null) {
+                    setPackageScanClassResolver(createPackageScanClassResolver());
+                }
+            }
+        }
         return packageScanClassResolver;
     }
 
     public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) {
-        this.packageScanClassResolver = packageScanClassResolver;
+        this.packageScanClassResolver = doAddService(packageScanClassResolver);
     }
 
     public List<String> getComponentNames() {
-        List<String> answer = new ArrayList<>();
-        for (String name : components.keySet()) {
-            answer.add(name);
-        }
-        return answer;
+        return new ArrayList<>(components.keySet());
     }
 
     public List<String> getLanguageNames() {
-        synchronized (languages) {
-            List<String> answer = new ArrayList<>();
-            for (String name : languages.keySet()) {
-                answer.add(name);
-            }
-            return answer;
-        }
+        return new ArrayList<>(languages.keySet());
     }
 
     public ModelJAXBContextFactory getModelJAXBContextFactory() {
         if (modelJAXBContextFactory == null) {
-            modelJAXBContextFactory = createModelJAXBContextFactory();
+            synchronized (this) {
+                if (modelJAXBContextFactory == null) {
+                    setModelJAXBContextFactory(createModelJAXBContextFactory());
+                }
+            }
         }
         return modelJAXBContextFactory;
     }
 
     public void setModelJAXBContextFactory(final ModelJAXBContextFactory modelJAXBContextFactory) {
-        this.modelJAXBContextFactory = modelJAXBContextFactory;
+        this.modelJAXBContextFactory = doAddService(modelJAXBContextFactory);
     }
 
     public NodeIdFactory getNodeIdFactory() {
+        if (nodeIdFactory == null) {
+            synchronized (this) {
+                if (nodeIdFactory == null) {
+                    setNodeIdFactory(createNodeIdFactory());
+                }
+            }
+        }
         return nodeIdFactory;
     }
 
     public void setNodeIdFactory(NodeIdFactory idFactory) {
-        this.nodeIdFactory = idFactory;
+        this.nodeIdFactory = doAddService(idFactory);
     }
 
     public ManagementStrategy getManagementStrategy() {
+        if (managementStrategy == null) {
+            synchronized (this) {
+                if (managementStrategy == null) {
+                    setManagementStrategy(createManagementStrategy());
+                }
+            }
+        }
         return managementStrategy;
     }
 
@@ -4255,20 +4243,38 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         }
     }
 
+    public boolean isJMXDisabled() {
+        return disableJMX;
+    }
+
     public InflightRepository getInflightRepository() {
+        if (inflightRepository == null) {
+            synchronized (this) {
+                if (inflightRepository == null) {
+                    setInflightRepository(createInflightRepository());
+                }
+            }
+        }
         return inflightRepository;
     }
 
     public void setInflightRepository(InflightRepository repository) {
-        this.inflightRepository = repository;
+        this.inflightRepository = doAddService(repository);
     }
 
     public AsyncProcessorAwaitManager getAsyncProcessorAwaitManager() {
+        if (asyncProcessorAwaitManager == null) {
+            synchronized (this) {
+                if (asyncProcessorAwaitManager == null) {
+                    setAsyncProcessorAwaitManager(createAsyncProcessorAwaitManager());
+                }
+            }
+        }
         return asyncProcessorAwaitManager;
     }
 
     public void setAsyncProcessorAwaitManager(AsyncProcessorAwaitManager asyncProcessorAwaitManager) {
-        this.asyncProcessorAwaitManager = asyncProcessorAwaitManager;
+        this.asyncProcessorAwaitManager = doAddService(asyncProcessorAwaitManager);
     }
 
     public void setAutoStartup(Boolean autoStartup) {
@@ -4330,13 +4336,17 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     public DataFormatResolver getDataFormatResolver() {
         if (dataFormatResolver == null) {
-            dataFormatResolver = createDataFormatResolver();
+            synchronized (this) {
+                if (dataFormatResolver == null) {
+                    setDataFormatResolver(createDataFormatResolver());
+                }
+            }
         }
         return dataFormatResolver;
     }
 
     public void setDataFormatResolver(DataFormatResolver dataFormatResolver) {
-        this.dataFormatResolver = dataFormatResolver;
+        this.dataFormatResolver = doAddService(dataFormatResolver);
     }
 
     public DataFormat resolveDataFormat(String name) {
@@ -4380,11 +4390,18 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public ShutdownStrategy getShutdownStrategy() {
+        if (shutdownStrategy == null) {
+            synchronized (this) {
+                if (shutdownStrategy == null) {
+                    shutdownStrategy = createShutdownStrategy();
+                }
+            }
+        }
         return shutdownStrategy;
     }
 
     public void setShutdownStrategy(ShutdownStrategy shutdownStrategy) {
-        this.shutdownStrategy = shutdownStrategy;
+        this.shutdownStrategy = doAddService(shutdownStrategy);
     }
 
     public ShutdownRoute getShutdownRoute() {
@@ -4412,27 +4429,49 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public ExecutorServiceManager getExecutorServiceManager() {
+        if (executorServiceManager == null) {
+            synchronized (this) {
+                if (executorServiceManager == null) {
+                    setExecutorServiceManager(createExecutorServiceManager());
+                }
+            }
+        }
         return this.executorServiceManager;
     }
 
     public void setExecutorServiceManager(ExecutorServiceManager executorServiceManager) {
-        this.executorServiceManager = executorServiceManager;
+        // special for executorServiceManager as want to stop it manually so false in stopOnShutdown
+        this.executorServiceManager = doAddService(executorServiceManager, false);
     }
 
     public ProcessorFactory getProcessorFactory() {
+        if (processorFactory == null) {
+            synchronized (this) {
+                if (processorFactory == null) {
+                    setProcessorFactory(createProcessorFactory());
+                }
+            }
+        }
         return processorFactory;
     }
 
     public void setProcessorFactory(ProcessorFactory processorFactory) {
-        this.processorFactory = processorFactory;
+        this.processorFactory = doAddService(processorFactory);
     }
 
     public MessageHistoryFactory getMessageHistoryFactory() {
+        if (messageHistoryFactory == null) {
+            synchronized (this) {
+                if (messageHistoryFactory == null) {
+                    setMessageHistoryFactory(createMessageHistoryFactory());
+                }
+            }
+        }
         return messageHistoryFactory;
     }
 
     public void setMessageHistoryFactory(MessageHistoryFactory messageHistoryFactory) {
-        this.messageHistoryFactory = messageHistoryFactory;
+        this.messageHistoryFactory = doAddService(messageHistoryFactory);
     }
 
     public Debugger getDebugger() {
@@ -4440,34 +4479,55 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     public void setDebugger(Debugger debugger) {
-        this.debugger = debugger;
+        if (isStartingOrStarted()) {
+            throw new IllegalStateException("Can not set debugger on a started CamelContext");
+        }
+        this.debugger = doAddService(debugger);
     }
 
     public UuidGenerator getUuidGenerator() {
+        if (uuidGenerator == null) {
+            synchronized (this) {
+                if (uuidGenerator == null) {
+                    setUuidGenerator(createUuidGenerator());
+                }
+            }
+        }
         return uuidGenerator;
     }
 
     public void setUuidGenerator(UuidGenerator uuidGenerator) {
-        this.uuidGenerator = uuidGenerator;
+        this.uuidGenerator = doAddService(uuidGenerator);
     }
 
     public StreamCachingStrategy getStreamCachingStrategy() {
         if (streamCachingStrategy == null) {
-            streamCachingStrategy = new DefaultStreamCachingStrategy();
+            synchronized (this) {
+                if (streamCachingStrategy == null) {
+                    setStreamCachingStrategy(createStreamCachingStrategy());
+                }
+            }
         }
         return streamCachingStrategy;
     }
 
     public void setStreamCachingStrategy(StreamCachingStrategy streamCachingStrategy) {
-        this.streamCachingStrategy = streamCachingStrategy;
+        this.streamCachingStrategy = doAddService(streamCachingStrategy, true, false);
     }
 
     public RestRegistry getRestRegistry() {
+        if (restRegistry ==  null) {
+            synchronized (this) {
+                if (restRegistry == null) {
+                    setRestRegistry(createRestRegistry());
+                }
+            }
+        }
         return restRegistry;
     }
 
     public void setRestRegistry(RestRegistry restRegistry) {
-        this.restRegistry = restRegistry;
+        this.restRegistry = doAddService(restRegistry);
     }
 
     @Override
@@ -4490,7 +4550,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     @Override
     public void setReloadStrategy(ReloadStrategy reloadStrategy) {
-        this.reloadStrategy = reloadStrategy;
+        this.reloadStrategy = doAddService(reloadStrategy);
     }
 
     @Override
@@ -4550,33 +4610,25 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
 
     @Override
     public HeadersMapFactory getHeadersMapFactory() {
+        if (headersMapFactory == null) {
+            synchronized (this) {
+                if (headersMapFactory == null) {
+                    setHeadersMapFactory(createHeadersMapFactory());
+                }
+            }
+        }
         return headersMapFactory;
     }
 
     @Override
     public void setHeadersMapFactory(HeadersMapFactory headersMapFactory) {
-        this.headersMapFactory = headersMapFactory;
+        this.headersMapFactory = doAddService(headersMapFactory);
     }
 
     protected Map<String, RouteService> getRouteServices() {
         return routeServices;
     }
 
-    protected ManagementStrategy createManagementStrategy() {
-        if (!disableJMX) {
-            try {
-                ServiceLoader<ManagementStrategyFactory> loader = ServiceLoader.load(ManagementStrategyFactory.class);
-                Iterator<ManagementStrategyFactory> iterator = loader.iterator();
-                if (iterator.hasNext()) {
-                    return iterator.next().create(this);
-                }
-            } catch (Exception e) {
-                log.warn("Cannot create JMX lifecycle strategy. Will fallback and disable JMX.", e);
-            }
-        }
-        return new DefaultManagementStrategy(this);
-    }
-
     /**
      * Reset context counter to a preset value. Mostly used for tests to ensure a predictable getName()
      *
@@ -4587,19 +4639,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         DefaultManagementNameStrategy.setCounter(value);
     }
 
-    protected UuidGenerator createDefaultUuidGenerator() {
-        if (System.getProperty("com.google.appengine.runtime.environment") != null) {
-            // either "Production" or "Development"
-            return new JavaUuidGenerator();
-        } else {
-            return new DefaultUuidGenerator();
-        }
-    }
-
-    protected ModelJAXBContextFactory createModelJAXBContextFactory() {
-        return new DefaultModelJAXBContextFactory();
-    }
-
     @Override
     public String toString() {
         return "CamelContext(" + getName() + ")";
@@ -4629,109 +4668,72 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         }
     }
 
-    protected NodeIdFactory createNodeIdFactory() {
-        return new DefaultNodeIdFactory();
-    }
+    protected abstract StreamCachingStrategy createStreamCachingStrategy();
 
-    protected FactoryFinderResolver createFactoryFinderResolver() {
-        return new DefaultFactoryFinderResolver();
-    }
+    protected abstract TypeConverter createTypeConverter();
 
-    protected ClassResolver createClassResolver() {
-        return new DefaultClassResolver(this);
-    }
+    protected abstract TypeConverterRegistry createTypeConverterRegistry();
 
-    protected ProcessorFactory createProcessorFactory() {
-        return new DefaultProcessorFactory();
-    }
+    protected abstract Injector createInjector();
 
-    protected DataFormatResolver createDataFormatResolver() {
-        return new DefaultDataFormatResolver();
-    }
+    protected abstract ComponentResolver createComponentResolver();
 
-    protected MessageHistoryFactory createMessageHistoryFactory() {
-        return new DefaultMessageHistoryFactory();
-    }
+    protected abstract Registry createRegistry();
 
-    protected InflightRepository createInflightRepository() {
-        return new DefaultInflightRepository();
-    }
+    protected abstract UuidGenerator createUuidGenerator();
 
-    protected AsyncProcessorAwaitManager createAsyncProcessorAwaitManager() {
-        return new DefaultAsyncProcessorAwaitManager();
-    }
+    protected abstract ModelJAXBContextFactory createModelJAXBContextFactory();
 
-    protected RouteController createRouteController() {
-        return new DefaultRouteController(this);
-    }
+    protected abstract NodeIdFactory createNodeIdFactory();
 
-    protected HealthCheckRegistry createHealthCheckRegistry() {
-        return new DefaultHealthCheckRegistry(this);
-    }
+    protected abstract FactoryFinderResolver createFactoryFinderResolver();
 
+    protected abstract ClassResolver createClassResolver();
 
-    protected ShutdownStrategy createShutdownStrategy() {
-        return new DefaultShutdownStrategy(this);
-    }
+    protected abstract ManagementStrategy createManagementStrategy();
 
-    protected PackageScanClassResolver createPackageScanClassResolver() {
-        PackageScanClassResolver packageScanClassResolver;
-        // use WebSphere specific resolver if running on WebSphere
-        if (WebSpherePackageScanClassResolver.isWebSphereClassLoader(this.getClass().getClassLoader())) {
-            log.info("Using WebSphere specific PackageScanClassResolver");
-            packageScanClassResolver = new WebSpherePackageScanClassResolver("META-INF/services/org/apache/camel/TypeConverter");
-        } else {
-            packageScanClassResolver = new DefaultPackageScanClassResolver();
-        }
-        return packageScanClassResolver;
-    }
+    protected abstract ProcessorFactory createProcessorFactory();
 
-    protected ExecutorServiceManager createExecutorServiceManager() {
-        return new DefaultExecutorServiceManager(this);
-    }
+    protected abstract DataFormatResolver createDataFormatResolver();
 
-    protected ServicePool<Producer> createProducerServicePool() {
-        return new ServicePool<>(Endpoint::createProducer, Producer::getEndpoint, 100);
-    }
+    protected abstract MessageHistoryFactory createMessageHistoryFactory();
 
-    protected ServicePool<PollingConsumer> createPollingConsumerServicePool() {
-        return new ServicePool<>(Endpoint::createPollingConsumer, PollingConsumer::getEndpoint, 100);
-    }
+    protected abstract InflightRepository createInflightRepository();
 
-    protected UnitOfWorkFactory createUnitOfWorkFactory() {
-        return new DefaultUnitOfWorkFactory();
-    }
+    protected abstract AsyncProcessorAwaitManager createAsyncProcessorAwaitManager();
 
-    protected RuntimeCamelCatalog createRuntimeCamelCatalog() {
-        return new DefaultRuntimeCamelCatalog(this, true);
-    }
+    protected abstract RouteController createRouteController();
 
-    protected CamelContextNameStrategy createCamelContextNameStrategy() {
-        return new DefaultCamelContextNameStrategy();
-    }
+    protected abstract HealthCheckRegistry createHealthCheckRegistry();
 
-    protected ManagementNameStrategy createManagementNameStrategy() {
-        return new DefaultManagementNameStrategy(this);
-    }
+    protected abstract ShutdownStrategy createShutdownStrategy();
 
-    protected HeadersMapFactory createHeadersMapFactory() {
-        return new DefaultHeadersMapFactory();
-    }
+    protected abstract PackageScanClassResolver createPackageScanClassResolver();
 
-    protected LanguageResolver createLanguageResolver() {
-        return new DefaultLanguageResolver();
-    }
+    protected abstract ExecutorServiceManager createExecutorServiceManager();
 
-    protected EndpointRegistry<EndpointKey> createEndpointRegistry(Map<EndpointKey, Endpoint> endpoints) {
-        return new DefaultEndpointRegistry(this, endpoints);
-    }
+    protected abstract ServicePool<Producer> createProducerServicePool();
 
-    protected ValidatorRegistry<ValidatorKey> createValidatorRegistry(List<ValidatorDefinition> validators) throws Exception {
-        return new DefaultValidatorRegistry(this, validators);
-    }
+    protected abstract ServicePool<PollingConsumer> createPollingConsumerServicePool();
 
-    protected TransformerRegistry<TransformerKey> createTransformerRegistry(List<TransformerDefinition> transformers) throws Exception {
-        return new DefaultTransformerRegistry(this, transformers);
-    }
+    protected abstract UnitOfWorkFactory createUnitOfWorkFactory();
+
+    protected abstract RuntimeCamelCatalog createRuntimeCamelCatalog();
+
+    protected abstract CamelContextNameStrategy createCamelContextNameStrategy();
+
+    protected abstract ManagementNameStrategy createManagementNameStrategy();
+
+    protected abstract HeadersMapFactory createHeadersMapFactory();
+
+    protected abstract LanguageResolver createLanguageResolver();
+
+    protected abstract RestRegistry createRestRegistry();
+
+    protected abstract EndpointRegistry<EndpointKey> createEndpointRegistry(Map<EndpointKey, Endpoint> endpoints);
+
+    protected abstract ValidatorRegistry<ValidatorKey> createValidatorRegistry(List<ValidatorDefinition> validators) throws Exception;
+
+    protected abstract TransformerRegistry<TransformerKey> createTransformerRegistry(List<TransformerDefinition> transformers) throws Exception;
 
 }
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 22b1f30..1740a92 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -16,127 +16,42 @@
  */
 package org.apache.camel.impl;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Function;
-import java.util.function.Supplier;
 
 import javax.naming.Context;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.Unmarshaller;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.Component;
-import org.apache.camel.Consumer;
-import org.apache.camel.ConsumerTemplate;
 import org.apache.camel.Endpoint;
-import org.apache.camel.ErrorHandlerFactory;
-import org.apache.camel.ExtendedStartupListener;
-import org.apache.camel.FailedToStartRouteException;
-import org.apache.camel.FluentProducerTemplate;
-import org.apache.camel.IsSingleton;
-import org.apache.camel.LoadPropertiesException;
-import org.apache.camel.MultipleConsumersSupport;
-import org.apache.camel.NamedNode;
 import org.apache.camel.NoFactoryAvailableException;
-import org.apache.camel.NoSuchEndpointException;
 import org.apache.camel.PollingConsumer;
-import org.apache.camel.Processor;
 import org.apache.camel.Producer;
-import org.apache.camel.ProducerTemplate;
-import org.apache.camel.ResolveEndpointFailedException;
-import org.apache.camel.Route;
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.Service;
-import org.apache.camel.ServiceStatus;
-import org.apache.camel.ShutdownRoute;
-import org.apache.camel.ShutdownRunningTask;
-import org.apache.camel.StartupListener;
-import org.apache.camel.StatefulService;
-import org.apache.camel.Suspendable;
-import org.apache.camel.SuspendableService;
 import org.apache.camel.TypeConverter;
-import org.apache.camel.VetoCamelContextStartException;
-import org.apache.camel.builder.DefaultFluentProducerTemplate;
-import org.apache.camel.builder.ErrorHandlerBuilder;
-import org.apache.camel.builder.ErrorHandlerBuilderSupport;
-import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.health.HealthCheckRegistry;
 import org.apache.camel.impl.converter.BaseTypeConverterRegistry;
 import org.apache.camel.impl.converter.DefaultTypeConverter;
 import org.apache.camel.impl.health.DefaultHealthCheckRegistry;
 import org.apache.camel.impl.transformer.TransformerKey;
 import org.apache.camel.impl.validator.ValidatorKey;
-import org.apache.camel.model.DataFormatDefinition;
-import org.apache.camel.model.FromDefinition;
-import org.apache.camel.model.HystrixConfigurationDefinition;
-import org.apache.camel.model.ModelCamelContext;
-import org.apache.camel.model.ModelHelper;
-import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.ProcessorDefinitionHelper;
-import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.RouteDefinitionHelper;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
-import org.apache.camel.model.rest.RestDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.model.transformer.TransformerDefinition;
 import org.apache.camel.model.validator.ValidatorDefinition;
-import org.apache.camel.processor.interceptor.Debug;
-import org.apache.camel.processor.interceptor.HandleFault;
-import org.apache.camel.reifier.RouteReifier;
 import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.runtimecatalog.impl.DefaultRuntimeCamelCatalog;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.CamelContextNameStrategy;
-import org.apache.camel.spi.CamelContextTracker;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.ComponentResolver;
-import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.DataFormatResolver;
-import org.apache.camel.spi.DataType;
-import org.apache.camel.spi.Debugger;
 import org.apache.camel.spi.EndpointRegistry;
-import org.apache.camel.spi.EndpointStrategy;
-import org.apache.camel.spi.EventNotifier;
 import org.apache.camel.spi.ExecutorServiceManager;
 import org.apache.camel.spi.FactoryFinder;
 import org.apache.camel.spi.FactoryFinderResolver;
 import org.apache.camel.spi.HeadersMapFactory;
 import org.apache.camel.spi.InflightRepository;
 import org.apache.camel.spi.Injector;
-import org.apache.camel.spi.InterceptStrategy;
-import org.apache.camel.spi.Language;
 import org.apache.camel.spi.LanguageResolver;
-import org.apache.camel.spi.LifecycleStrategy;
-import org.apache.camel.spi.LogListener;
-import org.apache.camel.spi.ManagementMBeanAssembler;
 import org.apache.camel.spi.ManagementNameStrategy;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.spi.ManagementStrategyFactory;
@@ -146,4424 +61,110 @@ import org.apache.camel.spi.NodeIdFactory;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.ProcessorFactory;
 import org.apache.camel.spi.Registry;
-import org.apache.camel.spi.ReloadStrategy;
-import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestRegistry;
-import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.RouteController;
-import org.apache.camel.spi.RouteError;
-import org.apache.camel.spi.RouteError.Phase;
-import org.apache.camel.spi.RoutePolicyFactory;
-import org.apache.camel.spi.RouteStartupOrder;
-import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
 import org.apache.camel.spi.StreamCachingStrategy;
-import org.apache.camel.spi.Transformer;
 import org.apache.camel.spi.TransformerRegistry;
 import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.camel.spi.UnitOfWorkFactory;
 import org.apache.camel.spi.UuidGenerator;
-import org.apache.camel.spi.Validator;
 import org.apache.camel.spi.ValidatorRegistry;
-import org.apache.camel.support.CamelContextHelper;
-import org.apache.camel.support.EndpointHelper;
-import org.apache.camel.support.EventHelper;
-import org.apache.camel.support.IntrospectionSupport;
-import org.apache.camel.support.OrderedComparator;
-import org.apache.camel.support.ProcessorEndpoint;
-import org.apache.camel.support.ServiceHelper;
-import org.apache.camel.support.ServiceSupport;
-import org.apache.camel.support.jsse.SSLContextParameters;
-import org.apache.camel.util.CollectionStringBuffer;
-import org.apache.camel.util.IOHelper;
-import org.apache.camel.util.JsonSchemaHelper;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.StopWatch;
-import org.apache.camel.util.StringHelper;
-import org.apache.camel.util.StringQuoteHelper;
-import org.apache.camel.util.TimeUtils;
-import org.apache.camel.util.URISupport;
-import org.apache.camel.util.function.ThrowingRunnable;
-import org.slf4j.MDC;
 
-import static org.apache.camel.impl.MDCUnitOfWork.MDC_CAMEL_CONTEXT_ID;
-
-/**
- * Represents the context used to configure routes and the policies to use.
- */
-public class DefaultCamelContext extends ServiceSupport implements ModelCamelContext, Suspendable {
-
-    private String version;
-    private final AtomicBoolean vetoStated = new AtomicBoolean();
-    private JAXBContext jaxbContext;
-    private CamelContextNameStrategy nameStrategy;
-    private ManagementNameStrategy managementNameStrategy;
-    private String managementName;
-    private ClassLoader applicationContextClassLoader;
-    private EndpointRegistry<EndpointKey> endpoints;
-    private final AtomicInteger endpointKeyCounter = new AtomicInteger();
-    private final List<EndpointStrategy> endpointStrategies = new ArrayList<>();
-    private final Map<String, Component> components = new ConcurrentHashMap<>();
-    private final Set<Route> routes = new LinkedHashSet<>();
-    private final List<Service> servicesToStop = new CopyOnWriteArrayList<>();
-    private final List<StartupListener> startupListeners = new CopyOnWriteArrayList<>();
-    private final DeferServiceStartupListener deferStartupListener = new DeferServiceStartupListener();
-    private TypeConverter typeConverter;
-    private TypeConverterRegistry typeConverterRegistry;
-    private Injector injector;
-    private ComponentResolver componentResolver;
-    private boolean autoCreateComponents = true;
-    private LanguageResolver languageResolver;
-    private final Map<String, Language> languages = new HashMap<>();
-    private Registry registry;
-    private List<LifecycleStrategy> lifecycleStrategies = new CopyOnWriteArrayList<>();
-    private ManagementStrategy managementStrategy;
-    private ManagementMBeanAssembler managementMBeanAssembler;
-    private final List<RouteDefinition> routeDefinitions = new ArrayList<>();
-    private final List<RestDefinition> restDefinitions = new ArrayList<>();
-    private Map<String, RestConfiguration> restConfigurations = new ConcurrentHashMap<>();
-    private Map<String, ServiceCallConfigurationDefinition> serviceCallConfigurations = new ConcurrentHashMap<>();
-    private Map<String, HystrixConfigurationDefinition> hystrixConfigurations = new ConcurrentHashMap<>();
-    private RestRegistry restRegistry = new DefaultRestRegistry();
-    private List<InterceptStrategy> interceptStrategies = new ArrayList<>();
-    private List<RoutePolicyFactory> routePolicyFactories = new ArrayList<>();
-    private Set<LogListener> logListeners = new LinkedHashSet<>();
-    private HeadersMapFactory headersMapFactory;
-    // special flags to control the first startup which can are special
-    private volatile boolean firstStartDone;
-    private volatile boolean doNotStartRoutesOnFirstStart;
-    private final ThreadLocal<Boolean> isStartingRoutes = new ThreadLocal<>();
-    private final ThreadLocal<Boolean> isSetupRoutes = new ThreadLocal<>();
-    private Boolean autoStartup = Boolean.TRUE;
-    private Boolean trace = Boolean.FALSE;
-    private Boolean messageHistory = Boolean.TRUE;
-    private Boolean logMask = Boolean.FALSE;
-    private Boolean logExhaustedMessageBody = Boolean.FALSE;
-    private Boolean streamCache = Boolean.FALSE;
-    private Boolean handleFault = Boolean.FALSE;
-    private Boolean disableJMX = Boolean.FALSE;
-    private Boolean loadTypeConverters = Boolean.TRUE;
-    private Boolean typeConverterStatisticsEnabled = Boolean.FALSE;
-    private Boolean useMDCLogging = Boolean.FALSE;
-    private Boolean useDataType = Boolean.FALSE;
-    private Boolean useBreadcrumb = Boolean.TRUE;
-    private Boolean allowUseOriginalMessage = Boolean.FALSE;
-    private Long delay;
-    private ErrorHandlerFactory errorHandlerBuilder;
-    private final Object errorHandlerExecutorServiceLock = new Object();
-    private ScheduledExecutorService errorHandlerExecutorService;
-    private Map<String, DataFormatDefinition> dataFormats = new HashMap<>();
-    private DataFormatResolver dataFormatResolver;
-    private Map<String, String> globalOptions = new HashMap<>();
-    private FactoryFinderResolver factoryFinderResolver;
-    private FactoryFinder defaultFactoryFinder;
-    private PropertiesComponent propertiesComponent;
-    private StreamCachingStrategy streamCachingStrategy;
-    private final Map<String, FactoryFinder> factories = new HashMap<>();
-    private final Map<String, RouteService> routeServices = new LinkedHashMap<>();
-    private final Map<String, RouteService> suspendedRouteServices = new LinkedHashMap<>();
-    private ClassResolver classResolver = createClassResolver();
-    private PackageScanClassResolver packageScanClassResolver;
-    // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool
-    // so if we have 6 endpoints in the pool, we can have 6 x 100 producers in total
-    private ServicePool<Producer> producerServicePool;
-    private ServicePool<PollingConsumer> pollingConsumerServicePool;
-    private NodeIdFactory nodeIdFactory;
-    private ProcessorFactory processorFactory;
-    private MessageHistoryFactory messageHistoryFactory;
-    private InflightRepository inflightRepository;
-    private AsyncProcessorAwaitManager asyncProcessorAwaitManager;
-    private RuntimeEndpointRegistry runtimeEndpointRegistry;
-    private final List<RouteStartupOrder> routeStartupOrder = new ArrayList<>();
-    // start auto assigning route ids using numbering 1000 and upwards
-    private int defaultRouteStartupOrder = 1000;
-    private ShutdownStrategy shutdownStrategy;
-    private ShutdownRoute shutdownRoute = ShutdownRoute.Default;
-    private ShutdownRunningTask shutdownRunningTask = ShutdownRunningTask.CompleteCurrentTaskOnly;
-    private ExecutorServiceManager executorServiceManager;
-    private Debugger debugger;
-    private UuidGenerator uuidGenerator;
-    private UnitOfWorkFactory unitOfWorkFactory;
-    private final StopWatch stopWatch = new StopWatch(false);
-    private Date startDate;
-    private ModelJAXBContextFactory modelJAXBContextFactory;
-    private List<TransformerDefinition> transformers = new ArrayList<>();
-    private TransformerRegistry<TransformerKey> transformerRegistry;
-    private List<ValidatorDefinition> validators = new ArrayList<>();
-    private ValidatorRegistry<ValidatorKey> validatorRegistry;
-    private ReloadStrategy reloadStrategy;
-    private SSLContextParameters sslContextParameters;
-    private final ThreadLocal<Set<String>> componentsInCreation = new ThreadLocal<Set<String>>() {
-        @Override
-        public Set<String> initialValue() {
-            return new HashSet<>();
-        }
-    };
-    private RouteController routeController = createRouteController();
-    private Map<Class<?>, Object> extensions = new ConcurrentHashMap<>();
-
-    /**
-     * Creates the {@link CamelContext} using {@link JndiRegistry} as registry,
-     * but will silently fallback and use {@link SimpleRegistry} if JNDI cannot be used.
-     * <p/>
-     * Use one of the other constructors to force use an explicit registry / JNDI.
-     */
-    public DefaultCamelContext() {
-        this(true);
-    }
-
-    /**
-     * Creates the {@link CamelContext} using the given JNDI context as the registry
-     *
-     * @param jndiContext the JNDI context
-     */
-    public DefaultCamelContext(Context jndiContext) {
-        this();
-        setJndiContext(jndiContext);
-    }
-
-    /**
-     * Creates the {@link CamelContext} using the given registry
-     *
-     * @param registry the registry
-     */
-    public DefaultCamelContext(Registry registry) {
-        this();
-        setRegistry(registry);
-    }
-
-    public DefaultCamelContext(boolean init) {
-        // create a provisional (temporary) endpoint registry at first since end users may access endpoints before CamelContext is started
-        // we will later transfer the endpoints to the actual DefaultEndpointRegistry later, but we do this to starup Camel faster.
-        this.endpoints = new ProvisionalEndpointRegistry();
-
-        // add the defer service startup listener
-        this.startupListeners.add(deferStartupListener);
-
-        setDefaultExtension(HealthCheckRegistry.class, this::createHealthCheckRegistry);
-        setDefaultExtension(RuntimeCamelCatalog.class, this::createRuntimeCamelCatalog);
-
-        if (init) {
-            init();
-        }
-    }
-
-    public void doInit() {
-        if (nameStrategy == null) {
-            nameStrategy = createCamelContextNameStrategy();
-        }
-        if (managementNameStrategy == null) {
-            managementNameStrategy = createManagementNameStrategy();
-        }
-        if (headersMapFactory == null) {
-            headersMapFactory = createHeadersMapFactory();
-        }
-        if (classResolver == null) {
-            classResolver = createClassResolver();
-        }
-        if (producerServicePool == null) {
-            producerServicePool = createProducerServicePool();
-        }
-        if (pollingConsumerServicePool == null) {
-            pollingConsumerServicePool = createPollingConsumerServicePool();
-        }
-        if (nodeIdFactory == null){
-            nodeIdFactory = createNodeIdFactory();
-        }
-        if (processorFactory == null) {
-            processorFactory = createProcessorFactory();
-        }
-        if (messageHistoryFactory == null) {
-            messageHistoryFactory = createMessageHistoryFactory();
-        }
-        if (inflightRepository == null) {
-            inflightRepository = createInflightRepository();
-        }
-        if (asyncProcessorAwaitManager == null) {
-            asyncProcessorAwaitManager = createAsyncProcessorAwaitManager();
-        }
-        if (shutdownStrategy == null) {
-            shutdownStrategy = createShutdownStrategy();
-        }
-        if (uuidGenerator == null) {
-            uuidGenerator = createDefaultUuidGenerator();
-        }
-        if (unitOfWorkFactory == null) {
-            unitOfWorkFactory = createUnitOfWorkFactory();
-        }
-        if (executorServiceManager == null) {
-            executorServiceManager = createExecutorServiceManager();
-        }
-        if (packageScanClassResolver == null) {
-            packageScanClassResolver = createPackageScanClassResolver();
-        }
-        if (managementStrategy == null) {
-            // setup management strategy first since end users may use it to add event notifiers
-            // using the management strategy before the CamelContext has been started
-            managementStrategy = createManagementStrategy();
-        }
-
-        // Call all registered trackers with this context
-        // Note, this may use a partially constructed object
-        CamelContextTracker.notifyContextCreated(this);
-
-    }
-
-    public <T extends CamelContext> T adapt(Class<T> type) {
-        return type.cast(this);
-    }
-
-    @Override
-    public <T> T getExtension(Class<T> type) {
-        Object extension = extensions.get(type);
-        if (extension instanceof Supplier) {
-            extension = ((Supplier<T>) extension).get();
-            setExtension(type, (T) extension);
-        }
-        return (T) extension;
-    }
-
-    @Override
-    public <T> void setExtension(Class<T> type, T module) {
-        try {
-            addService(module, true, true);
-            extensions.put(type, module);
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeCamelException(e);
-        }
-    }
-
-    public <T> void setDefaultExtension(Class<T> type, Supplier<T> module) {
-        extensions.putIfAbsent(type, module);
-    }
-
-    public boolean isVetoStarted() {
-        return vetoStated.get();
-    }
-
-    public String getName() {
-        return getNameStrategy() != null ? getNameStrategy().getName() : null;
-    }
-
-    /**
-     * Sets the name of the this context.
-     *
-     * @param name the name
-     */
-    public void setName(String name) {
-        // use an explicit name strategy since an explicit name was provided to be used
-        this.nameStrategy = new ExplicitCamelContextNameStrategy(name);
-    }
-
-    public CamelContextNameStrategy getNameStrategy() {
-        return nameStrategy;
-    }
-
-    public void setNameStrategy(CamelContextNameStrategy nameStrategy) {
-        this.nameStrategy = nameStrategy;
-    }
-
-    public ManagementNameStrategy getManagementNameStrategy() {
-        return managementNameStrategy;
-    }
-
-    public void setManagementNameStrategy(ManagementNameStrategy managementNameStrategy) {
-        this.managementNameStrategy = managementNameStrategy;
-    }
-
-    public String getManagementName() {
-        return managementName;
-    }
-
-    public void setManagementName(String managementName) {
-        this.managementName = managementName;
-    }
-
-    public Component hasComponent(String componentName) {
-        return components.get(componentName);
-    }
-
-    public void addComponent(String componentName, final Component component) {
-        ObjectHelper.notNull(component, "component");
-        component.setCamelContext(this);
-        Component oldValue = components.putIfAbsent(componentName, component);
-        if (oldValue != null) {
-            throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName);
-        }
-        postInitComponent(componentName, component);
-    }
-
-    private void postInitComponent(String componentName, final Component component) {
-        for (LifecycleStrategy strategy : lifecycleStrategies) {
-            strategy.onComponentAdd(componentName, component);
-        }
-
-        // keep reference to properties component up to date
-        if (component instanceof PropertiesComponent && "properties".equals(componentName)) {
-            propertiesComponent = (PropertiesComponent) component;
-        }
-    }
-
-    public Component getComponent(String name) {
-        return getComponent(name, autoCreateComponents, true);
-    }
-
-    public Component getComponent(String name, boolean autoCreateComponents) {
-        return getComponent(name, autoCreateComponents, true);
-    }
-
-    public Component getComponent(String name, boolean autoCreateComponents, boolean autoStart) {
-        init();
-
-        // Check if the named component is already being created, that would mean
-        // that the initComponent has triggered a new getComponent
-        if (componentsInCreation.get().contains(name)) {
-            throw new IllegalStateException("Circular dependency detected, the component " + name + " is already being created");
-        }
-
-        try {
-            // Flag used to mark a component of being created.
-            final AtomicBoolean created = new AtomicBoolean(false);
-
-            // atomic operation to get/create a component. Avoid global locks.
-            final Component component = components.computeIfAbsent(name, new Function<String, Component>() {
-                @Override
-                public Component apply(String comp) {
-                    created.set(true);
-                    return DefaultCamelContext.this.initComponent(name, autoCreateComponents);
-                }
-            });
-
-            // Start the component after its creation as if it is a component proxy
-            // that creates/start a delegated component, we may end up in a deadlock
-            if (component != null && created.get() && autoStart && (isStarted() || isStarting())) {
-                // If the component is looked up after the context is started,
-                // lets start it up.
-                if (component instanceof Service) {
-                    startService((Service)component);
-                }
-            }
-
-            return  component;
-        } catch (Exception e) {
-            throw new RuntimeCamelException("Cannot auto create component: " + name, e);
-        } finally {
-            // remove the reference to the component being created
-            componentsInCreation.get().remove(name);
-        }
-    }
-
-    /**
-     * Function to initialize a component and auto start. Returns null if the autoCreateComponents is disabled
-     */
-    private Component initComponent(String name, boolean autoCreateComponents) {
-        Component component = null;
-        if (autoCreateComponents) {
-            try {
-                if (log.isDebugEnabled()) {
-                    log.debug("Using ComponentResolver: {} to resolve component with name: {}", getComponentResolver(), name);
-                }
-
-                // Mark the component as being created so we can detect circular
-                // requests.
-                //
-                // In spring apps, the component resolver may trigger a new getComponent
-                // because of the underlying bean factory and as the endpoints are
-                // registered as singleton, the spring factory creates the bean
-                // and then check the type so the getComponent is always triggered.
-                //
-                // Simple circular dependency:
-                //
-                //   <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
-                //     <route>
-                //       <from id="twitter" uri="twitter://timeline/home?type=polling"/>
-                //       <log message="Got ${body}"/>
-                //     </route>
-                //   </camelContext>
-                //
-                // Complex circular dependency:
-                //
-                //   <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
-                //     <route>
-                //       <from id="log" uri="seda:test"/>
-                //       <to id="seda" uri="log:test"/>
-                //     </route>
-                //   </camelContext>
-                //
-                // This would freeze the app (lock or infinite loop).
-                //
-                // See https://issues.apache.org/jira/browse/CAMEL-11225
-                componentsInCreation.get().add(name);
-
-                component = getComponentResolver().resolveComponent(name, this);
-                if (component != null) {
-                    component.setCamelContext(this);
-                    postInitComponent(name, component);
-                }
-            } catch (Exception e) {
-                throw new RuntimeCamelException("Cannot auto create component: " + name, e);
-            }
-        }
-        return component;
-    }
-
-    public <T extends Component> T getComponent(String name, Class<T> componentType) {
-        Component component = getComponent(name);
-        if (componentType.isInstance(component)) {
-            return componentType.cast(component);
-        } else {
-            String message;
-            if (component == null) {
-                message = "Did not find component given by the name: " + name;
-            } else {
-                message = "Found component of type: " + component.getClass() + " instead of expected: " + componentType;
-            }
-            throw new IllegalArgumentException(message);
-        }
-    }
-
-    public Component resolveComponent(String name) {
-        Component answer = hasComponent(name);
-        if (answer == null) {
-            try {
-                answer = getComponentResolver().resolveComponent(name, this);
-            } catch (Exception e) {
-                throw new RuntimeCamelException("Cannot resolve component: " + name, e);
-            }
-        }
-        return answer;
-    }
-
-    public Component removeComponent(String componentName) {
-        Component oldComponent = components.remove(componentName);
-        if (oldComponent != null) {
-            try {
-                stopServices(oldComponent);
-            } catch (Exception e) {
-                log.warn("Error stopping component " + oldComponent + ". This exception will be ignored.", e);
-            }
-            for (LifecycleStrategy strategy : lifecycleStrategies) {
-                strategy.onComponentRemove(componentName, oldComponent);
-            }
-        }
-        // keep reference to properties component up to date
-        if (oldComponent != null && "properties".equals(componentName)) {
-            propertiesComponent = null;
-        }
-        return oldComponent;
-    }
-
-    // Endpoint Management Methods
-    // -----------------------------------------------------------------------
-
-    public EndpointRegistry<EndpointKey> getEndpointRegistry() {
-        return endpoints;
-    }
-
-    public Collection<Endpoint> getEndpoints() {
-        return new ArrayList<>(endpoints.values());
-    }
-
-    public Map<String, Endpoint> getEndpointMap() {
-        Map<String, Endpoint> answer = new TreeMap<>();
-        for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) {
-            answer.put(entry.getKey().get(), entry.getValue());
-        }
-        return answer;
-    }
-
-    public Endpoint hasEndpoint(String uri) {
-        return endpoints.get(getEndpointKey(uri));
-    }
-
-    public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception {
-        Endpoint oldEndpoint;
-
-        startService(endpoint);
-        oldEndpoint = endpoints.remove(getEndpointKey(uri));
-        for (LifecycleStrategy strategy : lifecycleStrategies) {
-            strategy.onEndpointAdd(endpoint);
-        }
-        addEndpointToRegistry(uri, endpoint);
-        if (oldEndpoint != null && oldEndpoint != endpoint) {
-            stopServices(oldEndpoint);
-        }
-
-        return oldEndpoint;
-    }
-
-    public void removeEndpoint(Endpoint endpoint) throws Exception {
-        removeEndpoints(endpoint.getEndpointUri());
-    }
-
-    public Collection<Endpoint> removeEndpoints(String uri) throws Exception {
-        Collection<Endpoint> answer = new ArrayList<>();
-        Endpoint oldEndpoint = endpoints.remove(getEndpointKey(uri));
-        if (oldEndpoint != null) {
-            answer.add(oldEndpoint);
-            stopServices(oldEndpoint);
-        } else {
-            for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) {
-                oldEndpoint = entry.getValue();
-                if (EndpointHelper.matchEndpoint(this, oldEndpoint.getEndpointUri(), uri)) {
-                    try {
-                        stopServices(oldEndpoint);
-                    } catch (Exception e) {
-                        log.warn("Error stopping endpoint " + oldEndpoint + ". This exception will be ignored.", e);
-                    }
-                    answer.add(oldEndpoint);
-                    endpoints.remove(entry.getKey());
-                }
-            }
-        }
-
-        // notify lifecycle its being removed
-        for (Endpoint endpoint : answer) {
-            for (LifecycleStrategy strategy : lifecycleStrategies) {
-                strategy.onEndpointRemove(endpoint);
-            }
-        }
-
-        return answer;
-    }
-
-    public Endpoint getEndpoint(String uri) {
-        init();
-
-        StringHelper.notEmpty(uri, "uri");
-
-        log.trace("Getting endpoint with uri: {}", uri);
-
-        // in case path has property placeholders then try to let property component resolve those
-        try {
-            uri = resolvePropertyPlaceholders(uri);
-        } catch (Exception e) {
-            throw new ResolveEndpointFailedException(uri, e);
-        }
-
-        final String rawUri = uri;
-
-        // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order
-        uri = normalizeEndpointUri(uri);
-
-        log.trace("Getting endpoint with raw uri: {}, normalized uri: {}", rawUri, uri);
-
-        Endpoint answer;
-        String scheme = null;
-        // use optimized method to get the endpoint uri
-        EndpointKey key = getEndpointKeyPreNormalized(uri);
-        answer = endpoints.get(key);
-        if (answer == null) {
-            try {
-                // Use the URI prefix to find the component.
-                String splitURI[] = StringHelper.splitOnCharacter(uri, ":", 2);
-                if (splitURI[1] != null) {
-                    scheme = splitURI[0];
-                    log.trace("Endpoint uri: {} is from component with name: {}", uri, scheme);
-                    Component component = getComponent(scheme);
-
-                    // Ask the component to resolve the endpoint.
-                    if (component != null) {
-                        log.trace("Creating endpoint from uri: {} using component: {}", uri, component);
-
-                        // Have the component create the endpoint if it can.
-                        if (component.useRawUri()) {
-                            answer = component.createEndpoint(rawUri);
-                        } else {
-                            answer = component.createEndpoint(uri);
-                        }
-
-                        if (answer != null && log.isDebugEnabled()) {
-                            log.debug("{} converted to endpoint: {} by component: {}", URISupport.sanitizeUri(uri), answer, component);
-                        }
-                    }
-                }
-
-                if (answer == null) {
-                    // no component then try in registry and elsewhere
-                    answer = createEndpoint(uri);
-                    log.trace("No component to create endpoint from uri: {} fallback lookup in registry -> {}", uri, answer);
-                }
-
-                if (answer == null && splitURI[1] == null) {
-                    // the uri has no context-path which is rare and it was not referring to an endpoint in the registry
-                    // so try to see if it can be created by a component
-
-                    int pos = uri.indexOf('?');
-                    String componentName = pos > 0 ? uri.substring(0, pos) : uri;
-
-                    Component component = getComponent(componentName);
-
-                    // Ask the component to resolve the endpoint.
-                    if (component != null) {
-                        log.trace("Creating endpoint from uri: {} using component: {}", uri, component);
-
-                        // Have the component create the endpoint if it can.
-                        if (component.useRawUri()) {
-                            answer = component.createEndpoint(rawUri);
-                        } else {
-                            answer = component.createEndpoint(uri);
-                        }
-
-                        if (answer != null && log.isDebugEnabled()) {
-                            log.debug("{} converted to endpoint: {} by component: {}", URISupport.sanitizeUri(uri), answer, component);
-                        }
-                    }
-
-                }
-
-                if (answer != null) {
-                    addService(answer);
-                    answer = addEndpointToRegistry(uri, answer);
-                }
-            } catch (Exception e) {
-                throw new ResolveEndpointFailedException(uri, e);
-            }
-        }
-
-        // unknown scheme
-        if (answer == null && scheme != null) {
-            throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme);
-        }
-
-        return answer;
-    }
-
-    public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) {
-        Endpoint endpoint = getEndpoint(name);
-        if (endpoint == null) {
-            throw new NoSuchEndpointException(name);
-        }
-        if (endpoint instanceof InterceptSendToEndpoint) {
-            endpoint = ((InterceptSendToEndpoint) endpoint).getDelegate();
-        }
-        if (endpointType.isInstance(endpoint)) {
-            return endpointType.cast(endpoint);
-        } else {
-            throw new IllegalArgumentException("The endpoint is not of type: " + endpointType
-                + " but is: " + endpoint.getClass().getCanonicalName());
-        }
-    }
-
-    public void addRegisterEndpointCallback(EndpointStrategy strategy) {
-        if (!endpointStrategies.contains(strategy)) {
-            // let it be invoked for already registered endpoints so it can catch-up.
-            endpointStrategies.add(strategy);
-            for (Endpoint endpoint : getEndpoints()) {
-                Endpoint newEndpoint = strategy.registerEndpoint(endpoint.getEndpointUri(), endpoint);
-                if (newEndpoint != null) {
-                    // put will replace existing endpoint with the new endpoint
-                    endpoints.put(getEndpointKey(endpoint.getEndpointUri()), newEndpoint);
-                }
-            }
-        }
-    }
-
-    /**
-     * Strategy to add the given endpoint to the internal endpoint registry
-     *
-     * @param uri      uri of the endpoint
-     * @param endpoint the endpoint to add
-     * @return the added endpoint
-     */
-    protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) {
-        StringHelper.notEmpty(uri, "uri");
-        ObjectHelper.notNull(endpoint, "endpoint");
-
-        // if there is endpoint strategies, then use the endpoints they return
-        // as this allows to intercept endpoints etc.
-        for (EndpointStrategy strategy : endpointStrategies) {
-            endpoint = strategy.registerEndpoint(uri, endpoint);
-        }
-        endpoints.put(getEndpointKey(uri, endpoint), endpoint);
-        return endpoint;
-    }
-
-    /**
-     * Normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order.
-     *
-     * @param uri the uri
-     * @return normalized uri
-     * @throws ResolveEndpointFailedException if uri cannot be normalized
-     */
-    protected static String normalizeEndpointUri(String uri) {
-        try {
-            uri = URISupport.normalizeUri(uri);
-        } catch (Exception e) {
-            throw new ResolveEndpointFailedException(uri, e);
-        }
-        return uri;
-    }
-
-    /**
-     * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry}
-     *
-     * @param uri the endpoint uri
-     * @return the key
-     */
-    protected EndpointKey getEndpointKey(String uri) {
-        return new EndpointKey(uri);
-    }
-
-    /**
-     * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry}
-     *
-     * @param uri the endpoint uri which is pre normalized
-     * @return the key
-     */
-    protected EndpointKey getEndpointKeyPreNormalized(String uri) {
-        return new EndpointKey(uri, true);
-    }
-
-    /**
-     * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry}
-     *
-     * @param uri      the endpoint uri
-     * @param endpoint the endpoint
-     * @return the key
-     */
-    protected EndpointKey getEndpointKey(String uri, Endpoint endpoint) {
-        if (endpoint != null && !endpoint.isSingleton()) {
-            int counter = endpointKeyCounter.incrementAndGet();
-            return new EndpointKey(uri + ":" + counter);
-        } else {
-            return new EndpointKey(uri);
-        }
-    }
-
-    // Route Management Methods
-    // -----------------------------------------------------------------------
-
-    @Override
-    public void setRouteController(RouteController routeController) {
-        this.routeController = routeController;
-        this.routeController.setCamelContext(this);
-    }
-
-    @Override
-    public RouteController getRouteController() {
-        return routeController;
-    }
-
-    public List<RouteStartupOrder> getRouteStartupOrder() {
-        return routeStartupOrder;
-    }
-
-    public List<Route> getRoutes() {
-        // lets return a copy of the collection as objects are removed later when services are stopped
-        if (routes.isEmpty()) {
-            return Collections.emptyList();
-        } else {
-            synchronized (routes) {
-                return new ArrayList<>(routes);
-            }
-        }
-    }
-
-    public Route getRoute(String id) {
-        if (id != null) {
-            for (Route route : getRoutes()) {
-                if (route.getId().equals(id)) {
-                    return route;
-                }
-            }
-        }
-        return null;
-    }
-
-    public Processor getProcessor(String id) {
-        for (Route route : getRoutes()) {
-            List<Processor> list = route.filter(id);
-            if (list.size() == 1) {
-                return list.get(0);
-            }
-        }
-        return null;
-    }
-
-    public <T extends Processor> T getProcessor(String id, Class<T> type) {
-        Processor answer = getProcessor(id);
-        if (answer != null) {
-            return type.cast(answer);
-        }
-        return null;
-    }
-
-    public ProcessorDefinition getProcessorDefinition(String id) {
-        for (RouteDefinition route : getRouteDefinitions()) {
-            Iterator<ProcessorDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class);
-            while (it.hasNext()) {
-                ProcessorDefinition proc = it.next();
-                if (id.equals(proc.getId())) {
-                    return proc;
-                }
-            }
-        }
-        return null;
-    }
-
-    public <T extends ProcessorDefinition> T getProcessorDefinition(String id, Class<T> type) {
-        ProcessorDefinition answer = getProcessorDefinition(id);
-        if (answer != null) {
-            return type.cast(answer);
-        }
-        return null;
-    }
-
-    void removeRouteCollection(Collection<Route> routes) {
-        synchronized (this.routes) {
-            this.routes.removeAll(routes);
-        }
-    }
-
-    void addRouteCollection(Collection<Route> routes) throws Exception {
-        synchronized (this.routes) {
-            this.routes.addAll(routes);
-        }
-    }
-
-    public void addRoutes(final RoutesBuilder builder) throws Exception {
-        init();
-        log.debug("Adding routes from builder: {}", builder);
-        doWithDefinedClassLoader(() -> builder.addRoutesToCamelContext(DefaultCamelContext.this));
-    }
-
-    public synchronized RoutesDefinition loadRoutesDefinition(InputStream is) throws Exception {
-        return ModelHelper.loadRoutesDefinition(this, is);
-    }
-
-    public synchronized RestsDefinition loadRestsDefinition(InputStream is) throws Exception {
-        // load routes using JAXB
-        if (jaxbContext == null) {
-            // must use classloader from CamelContext to have JAXB working
-            jaxbContext = getModelJAXBContextFactory().newJAXBContext();
-        }
-
-        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
-        Object result = unmarshaller.unmarshal(is);
-
-        if (result == null) {
-            throw new IOException("Cannot unmarshal to rests using JAXB from input stream: " + is);
-        }
-
-        // can either be routes or a single route
-        RestsDefinition answer;
-        if (result instanceof RestDefinition) {
-            RestDefinition rest = (RestDefinition) result;
-            answer = new RestsDefinition();
-            answer.getRests().add(rest);
-        } else if (result instanceof RestsDefinition) {
-            answer = (RestsDefinition) result;
-        } else {
-            throw new IllegalArgumentException("Unmarshalled object is an unsupported type: " + ObjectHelper.className(result) + " -> " + result);
-        }
-
-        return answer;
-    }
-
-    public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
-        if (routeDefinitions == null || routeDefinitions.isEmpty()) {
-            return;
-        }
-        for (RouteDefinition routeDefinition : routeDefinitions) {
-            removeRouteDefinition(routeDefinition);
-        }
-        this.routeDefinitions.addAll(routeDefinitions);
-        if (shouldStartRoutes()) {
-            startRouteDefinitions(routeDefinitions);
-        }
-    }
-
-    public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception {
-        addRouteDefinitions(Collections.singletonList(routeDefinition));
-    }
-
-    /**
-     * Removes the route definition with the given key.
-     *
-     * @return true if one or more routes was removed
-     */
-    protected boolean removeRouteDefinition(String key) {
-        boolean answer = false;
-        Iterator<RouteDefinition> iter = routeDefinitions.iterator();
-        while (iter.hasNext()) {
-            RouteDefinition route = iter.next();
-            if (route.idOrCreate(nodeIdFactory).equals(key)) {
-                iter.remove();
-                answer = true;
-            }
-        }
-        return answer;
-    }
-
-    public synchronized void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
-        for (RouteDefinition routeDefinition : routeDefinitions) {
-            removeRouteDefinition(routeDefinition);
-        }
-    }
-
-    public synchronized void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception {
-        RouteDefinition toBeRemoved = routeDefinition;
-        String id = routeDefinition.getId();
-        if (id != null) {
-            // remove existing route
-            stopRoute(id);
-            removeRoute(id);
-            toBeRemoved = getRouteDefinition(id);
-        }
-        this.routeDefinitions.remove(toBeRemoved);
-    }
-
-    public ServiceStatus getRouteStatus(String key) {
-        RouteService routeService = routeServices.get(key);
-        if (routeService != null) {
-            return routeService.getStatus();
-        }
-        return null;
-    }
-
-    public void startRoute(RouteDefinition route) throws Exception {
-        // assign ids to the routes and validate that the id's is all unique
-        RouteDefinitionHelper.forceAssignIds(this, routeDefinitions);
-        String duplicate = RouteDefinitionHelper.validateUniqueIds(route, routeDefinitions);
-        if (duplicate != null) {
-            throw new FailedToStartRouteException(route.getId(), "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes.");
-        }
-
-        // indicate we are staring the route using this thread so
-        // we are able to query this if needed
-        isStartingRoutes.set(true);
-        try {
-            // must ensure route is prepared, before we can start it
-            route.prepare(this);
-
-            List<Route> routes = new ArrayList<>();
-            List<RouteContext> routeContexts = new RouteReifier(route).addRoutes(this, routes);
-            RouteService routeService = new RouteService(this, route, routeContexts, routes);
-            startRouteService(routeService, true);
-        } finally {
-            // we are done staring routes
-            isStartingRoutes.remove();
-        }
-    }
-
-    public boolean isStartingRoutes() {
-        Boolean answer = isStartingRoutes.get();
-        return answer != null && answer;
-    }
-
-    public boolean isSetupRoutes() {
-        Boolean answer = isSetupRoutes.get();
-        return answer != null && answer;
-    }
-
-    public void startAllRoutes() throws Exception {
-        doStartOrResumeRoutes(routeServices, true, true, false, false);
-    }
-
-    public synchronized void startRoute(String routeId) throws Exception {
-        DefaultRouteError.reset(this, routeId);
-
-        RouteService routeService = routeServices.get(routeId);
-        if (routeService != null) {
-            try {
-                startRouteService(routeService, false);
-            } catch (Exception e) {
-                DefaultRouteError.set(this, routeId, RouteError.Phase.START, e);
-                throw e;
-            }
-        }
-    }
-
-    public synchronized void resumeRoute(String routeId) throws Exception {
-        DefaultRouteError.reset(this, routeId);
-
-        try {
-            if (!routeSupportsSuspension(routeId)) {
-                // start route if suspension is not supported
-                startRoute(routeId);
-                return;
-            }
-
-            RouteService routeService = routeServices.get(routeId);
-            if (routeService != null) {
-                resumeRouteService(routeService);
-                // must resume the route as well
-                Route route = getRoute(routeId);
-                ServiceHelper.resumeService(route);
-            }
-        } catch (Exception e) {
-            DefaultRouteError.set(this, routeId, RouteError.Phase.RESUME, e);
-            throw e;
-        }
-    }
-
-    public synchronized boolean stopRoute(String routeId, long timeout, TimeUnit timeUnit, boolean abortAfterTimeout) throws Exception {
-        DefaultRouteError.reset(this, routeId);
-
-        RouteService routeService = routeServices.get(routeId);
-        if (routeService != null) {
-            try {
-                RouteStartupOrder route = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
-
-                boolean completed = getShutdownStrategy().shutdown(this, route, timeout, timeUnit, abortAfterTimeout);
-                if (completed) {
-                    // must stop route service as well
-                    stopRouteService(routeService, false);
-                } else {
-                    // shutdown was aborted, make sure route is re-started properly
-                    startRouteService(routeService, false);
-                }
-                return completed;
-            } catch (Exception e) {
-                DefaultRouteError.set(this, routeId, RouteError.Phase.STOP, e);
-                throw e;
-            }
-        }
-
-        return false;
-    }
-
-    public void stopRoute(String routeId) throws Exception {
-        doShutdownRoute(routeId, getShutdownStrategy().getTimeout(), getShutdownStrategy().getTimeUnit(), false);
-    }
-
-    public void stopRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception {
-        doShutdownRoute(routeId, timeout, timeUnit, false);
-    }
-
-    protected synchronized void doShutdownRoute(String routeId, long timeout, TimeUnit timeUnit, boolean removingRoutes) throws Exception {
-        DefaultRouteError.reset(this, routeId);
-
-        RouteService routeService = routeServices.get(routeId);
-        if (routeService != null) {
-            try {
-                List<RouteStartupOrder> routes = new ArrayList<>(1);
-                RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
-                routes.add(order);
-
-                getShutdownStrategy().shutdown(this, routes, timeout, timeUnit);
-                // must stop route service as well (and remove the routes from management)
-                stopRouteService(routeService, removingRoutes);
-            } catch (Exception e) {
-                DefaultRouteError.set(this, routeId, removingRoutes ? Phase.SHUTDOWN : Phase.STOP, e);
-                throw e;
-            }
-        }
-    }
-
-    public synchronized boolean removeRoute(String routeId) throws Exception {
-        DefaultRouteError.reset(this, routeId);
-
-        // remove the route from ErrorHandlerBuilder if possible
-        if (getErrorHandlerFactory() instanceof ErrorHandlerBuilderSupport) {
-            ErrorHandlerBuilderSupport builder = (ErrorHandlerBuilderSupport) getErrorHandlerFactory();
-            builder.removeOnExceptionList(routeId);
-        }
-
-        // gather a map of all the endpoints in use by the routes, so we can known if a given endpoints is in use
-        // by one or more routes, when we remove the route
-        Map<String, Set<Endpoint>> endpointsInUse = new HashMap<>();
-        for (Map.Entry<String, RouteService> entry : routeServices.entrySet()) {
-            endpointsInUse.put(entry.getKey(), entry.getValue().gatherEndpoints());
-        }
-
-        RouteService routeService = routeServices.get(routeId);
-        if (routeService != null) {
-            if (getRouteStatus(routeId).isStopped()) {
-                try {
-                    routeService.setRemovingRoutes(true);
-                    shutdownRouteService(routeService);
-                    removeRouteDefinition(routeId);
-                    routeServices.remove(routeId);
-                    // remove route from startup order as well, as it was removed
-                    routeStartupOrder.removeIf(order -> order.getRoute().getId().equals(routeId));
-
-                    // from the route which we have removed, then remove all its private endpoints
-                    // (eg the endpoints which are not in use by other routes)
-                    Set<Endpoint> toRemove = new LinkedHashSet<>();
-                    for (Endpoint endpoint : endpointsInUse.get(routeId)) {
-                        // how many times is the endpoint in use
-                        int count = 0;
-                        for (Set<Endpoint> endpoints : endpointsInUse.values()) {
-                            if (endpoints.contains(endpoint)) {
-                                count++;
-                            }
-                        }
-                        // notice we will count ourselves so if there is only 1 then its safe to remove
-                        if (count <= 1) {
-                            toRemove.add(endpoint);
-                        }
-                    }
-                    for (Endpoint endpoint : toRemove) {
-                        log.debug("Removing: {} which was only in use by route: {}", endpoint, routeId);
-                        removeEndpoint(endpoint);
-                    }
-                } catch  (Exception e) {
-                    DefaultRouteError.set(this, routeId, RouteError.Phase.REMOVE, e);
-                    throw e;
-                }
-
-                return true;
-            } else {
-                return false;
-            }
-        }
-        return false;
-    }
-
-    public void suspendRoute(String routeId) throws Exception {
-        suspendRoute(routeId, getShutdownStrategy().getTimeout(), getShutdownStrategy().getTimeUnit());
-    }
-
-    public synchronized void suspendRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception {
-        DefaultRouteError.reset(this, routeId);
-
-        try {
-            if (!routeSupportsSuspension(routeId)) {
-                stopRoute(routeId, timeout, timeUnit);
-                return;
-            }
-
-            RouteService routeService = routeServices.get(routeId);
-            if (routeService != null) {
-                List<RouteStartupOrder> routes = new ArrayList<>(1);
-                Route route = routeService.getRoutes().iterator().next();
-                RouteStartupOrder order = new DefaultRouteStartupOrder(1, route, routeService);
-                routes.add(order);
-
-                getShutdownStrategy().suspend(this, routes, timeout, timeUnit);
-                // must suspend route service as well
-                suspendRouteService(routeService);
-                // must suspend the route as well
-                if (route instanceof SuspendableService) {
-                    ((SuspendableService) route).suspend();
-                }
-            }
-        } catch (Exception e) {
-            DefaultRouteError.set(this, routeId, RouteError.Phase.SUSPEND, e);
-            throw e;
-        }
-    }
-
-    public void addService(Object object) throws Exception {
-        addService(object, true);
-    }
-
-    public void addService(Object object, boolean stopOnShutdown) throws Exception {
-        doAddService(object, stopOnShutdown, false);
-    }
-
-    @Override
-    public void addService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception {
-        doAddService(object, stopOnShutdown, forceStart);
-    }
-
-    private void doAddService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception {
-
-        // inject CamelContext
-        if (object instanceof CamelContextAware) {
-            CamelContextAware aware = (CamelContextAware) object;
-            aware.setCamelContext(this);
-        }
-
-        if (object instanceof Service) {
-            Service service = (Service) object;
-
-            for (LifecycleStrategy strategy : lifecycleStrategies) {
-                if (service instanceof Endpoint) {
-                    // use specialized endpoint add
-                    strategy.onEndpointAdd((Endpoint) service);
-                } else {
-                    strategy.onServiceAdd(this, service, null);
-                }
-            }
-
-            if (!forceStart) {
-                // now start the service (and defer starting if CamelContext is starting up itself)
-                deferStartService(object, stopOnShutdown);
-            } else {
-                // only add to services to close if its a singleton
-                // otherwise we could for example end up with a lot of prototype scope endpoints
-                boolean singleton = true; // assume singleton by default
-                if (object instanceof IsSingleton) {
-                    singleton = ((IsSingleton) service).isSingleton();
-                }
-                // do not add endpoints as they have their own list
-                if (singleton && !(service instanceof Endpoint)) {
-                    // only add to list of services to stop if its not already there
-                    if (stopOnShutdown && !hasService(service)) {
-                        servicesToStop.add(service);
-                    }
-                }
-                ServiceHelper.startService(service);
-            }
-        }
-    }
-
-    public boolean removeService(Object object) throws Exception {
-        if (object instanceof Endpoint) {
-            removeEndpoint((Endpoint) object);
-            return true;
-        }
-        if (object instanceof Service) {
-            Service service = (Service) object;
-            for (LifecycleStrategy strategy : lifecycleStrategies) {
-                strategy.onServiceRemove(this, service, null);
-            }
-            return servicesToStop.remove(service);
-        }
-        return false;
-    }
-
-    public boolean hasService(Object object) {
-        if (object instanceof Service) {
-            Service service = (Service) object;
-            return servicesToStop.contains(service);
-        }
-        return false;
-    }
-
-    @Override
-    public <T> T hasService(Class<T> type) {
-        for (Service service : servicesToStop) {
-            if (type.isInstance(service)) {
-                return type.cast(service);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public <T> Set<T> hasServices(Class<T> type) {
-        Set<T> set = new HashSet<>();
-        for (Service service : servicesToStop) {
-            if (type.isInstance(service)) {
-                set.add((T) service);
-            }
-        }
-        return set;
-    }
-
-    public void deferStartService(Object object, boolean stopOnShutdown) throws Exception {
-        if (object instanceof Service) {
-            Service service = (Service) object;
-
-            // only add to services to close if its a singleton
-            // otherwise we could for example end up with a lot of prototype scope endpoints
-            boolean singleton = true; // assume singleton by default
-            if (object instanceof IsSingleton) {
-                singleton = ((IsSingleton) service).isSingleton();
-            }
-            // do not add endpoints as they have their own list
-            if (singleton && !(service instanceof Endpoint)) {
-                // only add to list of services to stop if its not already there
-                if (stopOnShutdown && !hasService(service)) {
-                    servicesToStop.add(service);
-                }
-            }
-            // are we already started?
-            if (isStarted()) {
-                ServiceHelper.startService(service);
-            } else {
-                deferStartupListener.addService(service);
-            }
-        }
-    }
-
-    public void addStartupListener(StartupListener listener) throws Exception {
-        // either add to listener so we can invoke then later when CamelContext has been started
-        // or invoke the callback right now
-        if (isStarted()) {
-            listener.onCamelContextStarted(this, true);
-        } else {
-            startupListeners.add(listener);
-        }
-    }
-
-    public String resolveComponentDefaultName(String javaType) {
-        // special for some components
-        // TODO: ActiveMQ 5.11 will include this out of the box, so not needed when its released
-        if ("org.apache.activemq.camel.component.ActiveMQComponent".equals(javaType)) {
-            return "jms";
-        }
-
-        // try to find the component by its java type from the in-use components
-        if (javaType != null) {
-            // find all the components which will include the default component name
-            try {
-                Map<String, Properties> all = CamelContextHelper.findComponents(this);
-                for (Map.Entry<String, Properties> entry : all.entrySet()) {
-                    String fqn = (String) entry.getValue().get("class");
-                    if (javaType.equals(fqn)) {
-                        // is there component docs for that name?
-                        String name = entry.getKey();
-                        String json = getComponentParameterJsonSchema(name);
-                        if (json != null) {
-                            return name;
-                        }
-                    }
-                }
-            } catch (Exception e) {
-                // ignore
-                return null;
-            }
-        }
-
-        // could not find a component with that name
-        return null;
-    }
-
-    public Map<String, Properties> findComponents() throws LoadPropertiesException, IOException {
-        return CamelContextHelper.findComponents(this);
-    }
-
-    public Map<String, Properties> findEips() throws LoadPropertiesException, IOException {
-        return CamelContextHelper.findEips(this);
-    }
-
-    public String getComponentParameterJsonSchema(String componentName) throws IOException {
-        // use the component factory finder to find the package name of the component class, which is the location
-        // where the documentation exists as well
-        FactoryFinder finder = getFactoryFinder(DefaultComponentResolver.RESOURCE_PATH);
-        try {
-            Class<?> clazz = null;
-            try {
-                clazz = finder.findClass(componentName);
-            } catch (NoFactoryAvailableException e) {
-                // ignore, i.e. if a component is an auto-configured spring-boot
-                // component
-            }
-
-            if (clazz == null) {
-                // fallback and find existing component
-                Component existing = hasComponent(componentName);
-                if (existing != null) {
-                    clazz = existing.getClass();
-                } else {
-                    return null;
-                }
-            }
-
-            String packageName = clazz.getPackage().getName();
-            packageName = packageName.replace('.', '/');
-            String path = packageName + "/" + componentName + ".json";
-
-            ClassResolver resolver = getClassResolver();
-            InputStream inputStream = resolver.loadResourceAsStream(path);
-            log.debug("Loading component JSON Schema for: {} using class resolver: {} -> {}", componentName, resolver, inputStream);
-            if (inputStream != null) {
-                try {
-                    return IOHelper.loadText(inputStream);
-                } finally {
-                    IOHelper.close(inputStream);
-                }
-            }
-            // special for ActiveMQ as it is really just JMS
-            if ("ActiveMQComponent".equals(clazz.getSimpleName())) {
-                return getComponentParameterJsonSchema("jms");
-            } else {
-                return null;
-            }
-        } catch (ClassNotFoundException e) {
-            return null;
-        }
-    }
-
-    public String getDataFormatParameterJsonSchema(String dataFormatName) throws IOException {
-        // use the dataformat factory finder to find the package name of the dataformat class, which is the location
-        // where the documentation exists as well
-        FactoryFinder finder = getFactoryFinder(DefaultDataFormatResolver.DATAFORMAT_RESOURCE_PATH);
-        try {
-            Class<?> clazz = null;
-            try {
-                clazz = finder.findClass(dataFormatName);
-            } catch (NoFactoryAvailableException e) {
-                // ignore, i.e. if a component is an auto-configured spring-boot
-                // data-formats
-            }
-
-            if (clazz == null) {
-                return null;
-            }
-
-            String packageName = clazz.getPackage().getName();
-            packageName = packageName.replace('.', '/');
-            String path = packageName + "/" + dataFormatName + ".json";
-
-            ClassResolver resolver = getClassResolver();
-            InputStream inputStream = resolver.loadResourceAsStream(path);
-            log.debug("Loading dataformat JSON Schema for: {} using class resolver: {} -> {}", dataFormatName, resolver, inputStream);
-            if (inputStream != null) {
-                try {
-                    return IOHelper.loadText(inputStream);
-                } finally {
-                    IOHelper.close(inputStream);
-                }
-            }
-            return null;
-
-        } catch (ClassNotFoundException e) {
-            return null;
-        }
-    }
-
-    public String getLanguageParameterJsonSchema(String languageName) throws IOException {
-        // use the language factory finder to find the package name of the language class, which is the location
-        // where the documentation exists as well
-        FactoryFinder finder = getFactoryFinder(DefaultLanguageResolver.LANGUAGE_RESOURCE_PATH);
-        try {
-            Class<?> clazz = null;
-            try {
-                clazz = finder.findClass(languageName);
-            } catch (NoFactoryAvailableException e) {
-                // ignore, i.e. if a component is an auto-configured spring-boot
-                // languages
-            }
-
-            if (clazz == null) {
-                return null;
-            }
-
-            String packageName = clazz.getPackage().getName();
-            packageName = packageName.replace('.', '/');
-            String path = packageName + "/" + languageName + ".json";
-
-            ClassResolver resolver = getClassResolver();
-            InputStream inputStream = resolver.loadResourceAsStream(path);
-            log.debug("Loading language JSON Schema for: {} using class resolver: {} -> {}", languageName, resolver, inputStream);
-            if (inputStream != null) {
-                try {
-                    return IOHelper.loadText(inputStream);
-                } finally {
-                    IOHelper.close(inputStream);
-                }
-            }
-            return null;
-
-        } catch (ClassNotFoundException e) {
-            return null;
-        }
-    }
-
-    public String getEipParameterJsonSchema(String eipName) throws IOException {
-        // the eip json schema may be in some of the sub-packages so look until we find it
-        String[] subPackages = new String[]{"", "/config", "/dataformat", "/language", "/loadbalancer", "/rest"};
-        for (String sub : subPackages) {
-            String path = CamelContextHelper.MODEL_DOCUMENTATION_PREFIX + sub + "/" + eipName + ".json";
-            ClassResolver resolver = getClassResolver();
-            InputStream inputStream = resolver.loadResourceAsStream(path);
-            if (inputStream != null) {
-                log.debug("Loading eip JSON Schema for: {} using class resolver: {} -> {}", eipName, resolver, inputStream);
-                try {
-                    return IOHelper.loadText(inputStream);
-                } finally {
-                    IOHelper.close(inputStream);
-                }
-            }
-        }
-        return null;
-    }
-
-    public String explainEipJson(String nameOrId, boolean includeAllOptions) {
-        try {
-            // try to find the id within all known routes and their eips
-            String eipName = nameOrId;
-            NamedNode target = null;
-            for (RouteDefinition route : getRouteDefinitions()) {
-                if (route.getId().equals(nameOrId)) {
-                    target = route;
-                    break;
-                }
-                for (FromDefinition from : route.getInputs()) {
-                    if (nameOrId.equals(from.getId())) {
-                        target = route;
-                        break;
-                    }
-                }
-                Iterator<ProcessorDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class);
-                while (it.hasNext()) {
-                    ProcessorDefinition def = it.next();
-                    if (nameOrId.equals(def.getId())) {
-                        target = def;
-                        break;
-                    }
-                }
-                if (target != null) {
-                    break;
-                }
-            }
-
-            if (target != null) {
-                eipName = target.getShortName();
-            }
-
-            String json = getEipParameterJsonSchema(eipName);
-            if (json == null) {
-                return null;
-            }
-
-            // overlay with runtime parameters that id uses at runtime
-            if (target != null) {
-                List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("properties", json, true);
-
-                // selected rows to use for answer
-                Map<String, String[]> selected = new LinkedHashMap<>();
-
-                // extract options from the node
-                Map<String, Object> options = new LinkedHashMap<>();
-                IntrospectionSupport.getProperties(target, options, "", false);
-                // remove outputs which we do not want to include
-                options.remove("outputs");
-
-                // include other rows
-                for (Map<String, String> row : rows) {
-                    String name = row.get("name");
-                    String kind = row.get("kind");
-                    String label = row.get("label");
-                    String required = row.get("required");
-                    String value = row.get("value");
-                    String defaultValue = row.get("defaultValue");
-                    String type = row.get("type");
-                    String javaType = row.get("javaType");
-                    String deprecated = row.get("deprecated");
-                    String description = row.get("description");
-
-                    // find the configured option
-                    Object o = options.get(name);
-                    if (o != null) {
-                        value = o.toString();
-                    }
-
-                    value = URISupport.sanitizePath(value);
-
-                    if (includeAllOptions || o != null) {
-                        // add as selected row
-                        if (!selected.containsKey(name)) {
-                            selected.put(name, new String[]{name, kind, label, required, type, javaType, deprecated, value, defaultValue, description});
-                        }
-                    }
-                }
-
-                json = StringHelper.before(json, "  \"properties\": {");
-
-                StringBuilder buffer = new StringBuilder("  \"properties\": {");
-
-                boolean first = true;
-                for (String[] row : selected.values()) {
-                    if (first) {
-                        first = false;
-                    } else {
-                        buffer.append(",");
-                    }
-                    buffer.append("\n    ");
-
-                    String name = row[0];
-                    String kind = row[1];
-                    String label = row[2];
-                    String required = row[3];
-                    String type = row[4];
-                    String javaType = row[5];
-                    String deprecated = row[6];
-                    String value = row[7];
-                    String defaultValue = row[8];
-                    String description = row[9];
-
-                    // add json of the option
-                    buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { ");
-                    CollectionStringBuffer csb = new CollectionStringBuffer();
-                    if (kind != null) {
-                        csb.append("\"kind\": \"" + kind + "\"");
-                    }
-                    if (label != null) {
-                        csb.append("\"label\": \"" + label + "\"");
-                    }
-                    if (required != null) {
-                        csb.append("\"required\": \"" + required + "\"");
-                    }
-                    if (type != null) {
-                        csb.append("\"type\": \"" + type + "\"");
-                    }
-                    if (javaType != null) {
-                        csb.append("\"javaType\": \"" + javaType + "\"");
-                    }
-                    if (deprecated != null) {
-                        csb.append("\"deprecated\": \"" + deprecated + "\"");
-                    }
-                    if (value != null) {
-                        csb.append("\"value\": \"" + value + "\"");
-                    }
-                    if (defaultValue != null) {
-                        csb.append("\"defaultValue\": \"" + defaultValue + "\"");
-                    }
-                    if (description != null) {
-                        csb.append("\"description\": \"" + description + "\"");
-                    }
-                    if (!csb.isEmpty()) {
-                        buffer.append(csb.toString());
-                    }
-                    buffer.append(" }");
-                }
-
-                buffer.append("\n  }\n}\n");
-
-                // insert the original first part of the json into the start of the buffer
-                buffer.insert(0, json);
-                return buffer.toString();
-            }
-
-            return json;
-        } catch (Exception e) {
-            // ignore and return empty response
-            return null;
-        }
-    }
-
-    public String explainDataFormatJson(String dataFormatName, DataFormat dataFormat, boolean includeAllOptions) {
-        try {
-            String json = getDataFormatParameterJsonSchema(dataFormatName);
-            if (json == null) {
-                // the model may be shared for multiple data formats such as bindy, json (xstream, jackson, gson)
-                if (dataFormatName.contains("-")) {
-                    dataFormatName = StringHelper.before(dataFormatName, "-");
-                    json = getDataFormatParameterJsonSchema(dataFormatName);
-                }
-                if (json == null) {
-                    return null;
-                }
-            }
-
-            List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("properties", json, true);
-
-            // selected rows to use for answer
-            Map<String, String[]> selected = new LinkedHashMap<>();
-            Map<String, String[]> dataFormatOptions = new LinkedHashMap<>();
-
-            // extract options from the data format
-            Map<String, Object> options = new LinkedHashMap<>();
-            IntrospectionSupport.getProperties(dataFormat, options, "", false);
-
-            for (Map.Entry<String, Object> entry : options.entrySet()) {
-                String name = entry.getKey();
-                String value = "";
-                if (entry.getValue() != null) {
-                    value = entry.getValue().toString();
-                }
-                value = URISupport.sanitizePath(value);
-
-                // find type and description from the json schema
-                String type = null;
-                String kind = null;
-                String label = null;
-                String required = null;
-                String javaType = null;
-                String deprecated = null;
-                String secret = null;
-                String defaultValue = null;
-                String description = null;
-                for (Map<String, String> row : rows) {
-                    if (name.equals(row.get("name"))) {
-                        type = row.get("type");
-                        kind = row.get("kind");
-                        label = row.get("label");
-                        required = row.get("required");
-                        javaType = row.get("javaType");
-                        deprecated = row.get("deprecated");
-                        secret = row.get("secret");
-                        defaultValue = row.get("defaultValue");
-                        description = row.get("description");
-                        break;
-                    }
-                }
-
-                // remember this option from the uri
-                dataFormatOptions.put(name, new String[]{name, kind, label, required, type, javaType, deprecated, secret, value, defaultValue, description});
-            }
-
-            // include other rows
-            for (Map<String, String> row : rows) {
-                String name = row.get("name");
-                String kind = row.get("kind");
-                String label = row.get("label");
-                String required = row.get("required");
-                String value = row.get("value");
-                String defaultValue = row.get("defaultValue");
-                String type = row.get("type");
-                String javaType = row.get("javaType");
-                String deprecated = row.get("deprecated");
-                String secret = row.get("secret");
-                value = URISupport.sanitizePath(value);
-                String description = row.get("description");
-
-                boolean isDataFormatOption = dataFormatOptions.containsKey(name);
-
-                // always include from uri or path options
-                if (includeAllOptions || isDataFormatOption) {
-                    if (!selected.containsKey(name)) {
-                        // add as selected row, but take the value from uri options if it was from there
-                        if (isDataFormatOption) {
-                            selected.put(name, dataFormatOptions.get(name));
-                        } else {
-                            selected.put(name, new String[]{name, kind, label, required, type, javaType, deprecated, secret, value, defaultValue, description});
-                        }
-                    }
-                }
-            }
-
-            json = StringHelper.before(json, "  \"properties\": {");
-
-            StringBuilder buffer = new StringBuilder("  \"properties\": {");
-
-            boolean first = true;
-            for (String[] row : selected.values()) {
-                if (first) {
-                    first = false;
-                } else {
-                    buffer.append(",");
-                }
-                buffer.append("\n    ");
-
-                String name = row[0];
-                String kind = row[1];
-                String label = row[2];
-                String required = row[3];
-                String type = row[4];
-                String javaType = row[5];
-                String deprecated = row[6];
-                String secret = row[7];
-                String value = row[8];
-                String defaultValue = row[9];
-                String description = row[10];
-
-                // add json of the option
-                buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { ");
-                CollectionStringBuffer csb = new CollectionStringBuffer();
-                if (kind != null) {
-                    csb.append("\"kind\": \"" + kind + "\"");
-                }
-                if (label != null) {
-                    csb.append("\"label\": \"" + label + "\"");
-                }
-                if (required != null) {
-                    csb.append("\"required\": \"" + required + "\"");
-                }
-                if (type != null) {
-                    csb.append("\"type\": \"" + type + "\"");
-                }
-                if (javaType != null) {
-                    csb.append("\"javaType\": \"" + javaType + "\"");
-                }
-                if (deprecated != null) {
-                    csb.append("\"deprecated\": \"" + deprecated + "\"");
-                }
-                if (secret != null) {
-                    csb.append("\"secret\": \"" + secret + "\"");
-                }
-                if (value != null) {
-                    csb.append("\"value\": \"" + value + "\"");
-                }
-                if (defaultValue != null) {
-                    csb.append("\"defaultValue\": \"" + defaultValue + "\"");
-                }
-                if (description != null) {
-                    csb.append("\"description\": \"" + description + "\"");
-                }
-                if (!csb.isEmpty()) {
-                    buffer.append(csb.toString());
-                }
-                buffer.append(" }");
-            }
-
-            buffer.append("\n  }\n}\n");
-
-            // insert the original first part of the json into the start of the buffer
-            buffer.insert(0, json);
-            return buffer.toString();
-
-        } catch (Exception e) {
-            // ignore and return empty response
-            return null;
-        }
-    }
-
-    public String explainComponentJson(String componentName, boolean includeAllOptions) {
-        try {
-            String json = getComponentParameterJsonSchema(componentName);
-            if (json == null) {
-                return null;
-            }
-            List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("componentProperties", json, true);
-
-            // selected rows to use for answer
-            Map<String, String[]> selected = new LinkedHashMap<>();
-
-            // insert values from component
-            Component component = getComponent(componentName);
-            Map<String, Object> options = new HashMap<>();
-            IntrospectionSupport.getProperties(component, options, null);
-
-            for (Map.Entry<String, Object> entry : options.entrySet()) {
-                String name = entry.getKey();
-                // skip unwanted options which is default inherited from DefaultComponent
-                if ("camelContext".equals(name) || "endpointClass".equals(name)) {
-                    continue;
-                }
-                String value = "";
-                if (entry.getValue() != null) {
-                    value = entry.getValue().toString();
-                }
-                value = URISupport.sanitizePath(value);
-
-                // find type and description from the json schema
-                String type = null;
-                String kind = null;
-                String group = null;
-                String label = null;
-                String required = null;
-                String javaType = null;
-                String deprecated = null;
-                String secret = null;
-                String defaultValue = null;
-                String description = null;
-                for (Map<String, String> row : rows) {
-                    if (name.equals(row.get("name"))) {
-                        type = row.get("type");
-                        kind = row.get("kind");
-                        group = row.get("group");
-                        label = row.get("label");
-                        required = row.get("required");
-                        javaType = row.get("javaType");
-                        deprecated = row.get("deprecated");
-                        secret = row.get("secret");
-                        defaultValue = row.get("defaultValue");
-                        description = row.get("description");
-                        break;
-                    }
-                }
-                // add as selected row
-                selected.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description});
-            }
-
-            // include other rows
-            for (Map<String, String> row : rows) {
-                String name = row.get("name");
-                String kind = row.get("kind");
-                String group = row.get("group");
-                String label = row.get("label");
-                String required = row.get("required");
-                String value = row.get("value");
-                String defaultValue = row.get("defaultValue");
-                String type = row.get("type");
-                String javaType = row.get("javaType");
-                String deprecated = row.get("deprecated");
-                String secret = row.get("secret");
-                value = URISupport.sanitizePath(value);
-                String description = row.get("description");
-                // always include path options
-                if (includeAllOptions) {
-                    // add as selected row
-                    if (!selected.containsKey(name)) {
-                        selected.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description});
-                    }
-                }
-            }
-
-            json = StringHelper.before(json, "  \"componentProperties\": {");
-            StringBuilder buffer = new StringBuilder("  \"componentProperties\": {");
-
-            boolean first = true;
-            for (String[] row : selected.values()) {
-                if (first) {
-                    first = false;
-                } else {
-                    buffer.append(",");
-                }
-                buffer.append("\n    ");
-
-                String name = row[0];
-                String kind = row[1];
-                String group = row[2];
-                String label = row[3];
-                String required = row[4];
-                String type = row[5];
-                String javaType = row[6];
-                String deprecated = row[7];
-                String secret = row[8];
-                String value = row[9];
-                String defaultValue = row[10];
-                String description = row[11];
-
-                // add json of the option
-                buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { ");
-                CollectionStringBuffer csb = new CollectionStringBuffer();
-                if (kind != null) {
-                    csb.append("\"kind\": \"" + kind + "\"");
-                }
-                if (group != null) {
-                    csb.append("\"group\": \"" + group + "\"");
-                }
-                if (label != null) {
-                    csb.append("\"label\": \"" + label + "\"");
-                }
-                if (required != null) {
-                    csb.append("\"required\": \"" + required + "\"");
-                }
-                if (type != null) {
-                    csb.append("\"type\": \"" + type + "\"");
-                }
-                if (javaType != null) {
-                    csb.append("\"javaType\": \"" + javaType + "\"");
-                }
-                if (deprecated != null) {
-                    csb.append("\"deprecated\": \"" + deprecated + "\"");
-                }
-                if (secret != null) {
-                    csb.append("\"secret\": \"" + secret + "\"");
-                }
-                if (value != null) {
-                    csb.append("\"value\": \"" + value + "\"");
-                }
-                if (defaultValue != null) {
-                    csb.append("\"defaultValue\": \"" + defaultValue + "\"");
-                }
-                if (description != null) {
-                    csb.append("\"description\": \"" + description + "\"");
-                }
-                if (!csb.isEmpty()) {
-                    buffer.append(csb.toString());
-                }
-                buffer.append(" }");
-            }
-            buffer.append("\n  }\n}\n");
-            // insert the original first part of the json into the start of the buffer
-            buffer.insert(0, json);
-            return buffer.toString();
-        } catch (Exception e) {
-            // ignore and return empty response
-            return null;
-        }
-    }
-
-    // CHECKSTYLE:OFF
-    public String explainEndpointJson(String uri, boolean includeAllOptions) {
-        try {
-            URI u = new URI(uri);
-            String json = getComponentParameterJsonSchema(u.getScheme());
-            if (json == null) {
-                return null;
-            }
-            List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("properties", json, true);
-
-            // selected rows to use for answer
-            Map<String, String[]> selected = new LinkedHashMap<>();
-            Map<String, String[]> uriOptions = new LinkedHashMap<>();
-
-            // insert values from uri
-            Map<String, Object> options = new HashMap<>(getExtension(RuntimeCamelCatalog.class).endpointProperties(uri));
-
-            // extract consumer. prefix options
-            Map<String, Object> consumerOptions = IntrospectionSupport.extractProperties(options, "consumer.");
-            // and add back again without the consumer. prefix as that json schema omits that
-            options.putAll(consumerOptions);
-
-            for (Map.Entry<String, Object> entry : options.entrySet()) {
-                String name = entry.getKey();
-                String value = "";
-                if (entry.getValue() != null) {
-                    value = entry.getValue().toString();
-                }
-                value = URISupport.sanitizePath(value);
-                // find type and description from the json schema
-                String type = null;
-                String kind = null;
-                String group = null;
-                String label = null;
-                String required = null;
-                String javaType = null;
-                String deprecated = null;
-                String secret = null;
-                String defaultValue = null;
-                String description = null;
-                for (Map<String, String> row : rows) {
-                    if (name.equals(row.get("name"))) {
-                        type = row.get("type");
-                        kind = row.get("kind");
-                        group = row.get("group");
-                        label = row.get("label");
-                        required = row.get("required");
-                        javaType = row.get("javaType");
-                        deprecated = row.get("deprecated");
-                        secret = row.get("secret");
-                        defaultValue = row.get("defaultValue");
-                        description = row.get("description");
-                        break;
-                    }
-                }
-                // remember this option from the uri
-                uriOptions.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description});
-            }
-
-            // include other rows
-            for (Map<String, String> row : rows) {
-                String name = row.get("name");
-                String kind = row.get("kind");
-                String group = row.get("group");
-                String label = row.get("label");
-                String required = row.get("required");
-                String value = row.get("value");
-                String defaultValue = row.get("defaultValue");
-                String type = row.get("type");
-                String javaType = row.get("javaType");
-                String deprecated = row.get("deprecated");
-                String secret = row.get("secret");
-                value = URISupport.sanitizePath(value);
-                String description = row.get("description");
-                boolean isUriOption = uriOptions.containsKey(name);
-                // always include from uri or path options
-                if (includeAllOptions || isUriOption || "path".equals(kind)) {
-                    if (!selected.containsKey(name)) {
-                        // add as selected row, but take the value from uri options if it was from there
-                        if (isUriOption) {
-                            selected.put(name, uriOptions.get(name));
-                        } else {
-                            selected.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description});
-                        }
-                    }
-                }
-            }
-
-            // skip component properties
-            json = StringHelper.before(json, "  \"componentProperties\": {");
-            // and rewrite properties
-            StringBuilder buffer = new StringBuilder("  \"properties\": {");
-
-            boolean first = true;
-            for (String[] row : selected.values()) {
-                if (first) {
-                    first = false;
-                } else {
-                    buffer.append(",");
-                }
-                buffer.append("\n    ");
-
-                String name = row[0];
-                String kind = row[1];
-                String group = row[2];
-                String label = row[3];
-                String required = row[4];
-                String type = row[5];
-                String javaType = row[6];
-                String deprecated = row[7];
-                String secret = row[8];
-                String value = row[9];
-                String defaultValue = row[10];
-                String description = row[11];
-
-                // add json of the option
-                buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { ");
-                CollectionStringBuffer csb = new CollectionStringBuffer();
-                if (kind != null) {
-                    csb.append("\"kind\": \"" + kind + "\"");
-                }
-                if (group != null) {
-                    csb.append("\"group\": \"" + group + "\"");
-                }
-                if (label != null) {
-                    csb.append("\"label\": \"" + label + "\"");
-                }
-                if (required != null) {
-                    csb.append("\"required\": \"" + required + "\"");
-                }
-                if (type != null) {
-                    csb.append("\"type\": \"" + type + "\"");
-                }
-                if (javaType != null) {
-                    csb.append("\"javaType\": \"" + javaType + "\"");
-                }
-                if (deprecated != null) {
-                    csb.append("\"deprecated\": \"" + deprecated + "\"");
-                }
-                if (secret != null) {
-                    csb.append("\"secret\": \"" + secret + "\"");
-                }
-                if (value != null) {
-                    csb.append("\"value\": \"" + value + "\"");
-                }
-                if (defaultValue != null) {
-                    csb.append("\"defaultValue\": \"" + defaultValue + "\"");
-                }
-                if (description != null) {
-                    csb.append("\"description\": \"" + description + "\"");
-                }
-                if (!csb.isEmpty()) {
-                    buffer.append(csb.toString());
-                }
-                buffer.append(" }");
-            }
-            buffer.append("\n  }\n}\n");
-            // insert the original first part of the json into the start of the buffer
-            buffer.insert(0, json);
-            return buffer.toString();
-        } catch (Exception e) {
-            // ignore and return empty response
-            return null;
-        }
-    }
-    // CHECKSTYLE:ON
-
-    public String createRouteStaticEndpointJson(String routeId) {
-        // lets include dynamic as well as we want as much data as possible
-        return createRouteStaticEndpointJson(routeId, true);
-    }
-
-    public String createRouteStaticEndpointJson(String routeId, boolean includeDynamic) {
-        List<RouteDefinition> routes = new ArrayList<>();
-        if (routeId != null) {
-            RouteDefinition route = getRouteDefinition(routeId);
-            if (route == null) {
-                throw new IllegalArgumentException("Route with id " + routeId + " does not exist");
-            }
-            routes.add(route);
-        } else {
-            routes.addAll(getRouteDefinitions());
-        }
-
-        StringBuilder buffer = new StringBuilder("{\n  \"routes\": {");
-        boolean firstRoute = true;
-        for (RouteDefinition route : routes) {
-            if (!firstRoute) {
-                buffer.append("\n    },");
-            } else {
-                firstRoute = false;
-            }
-
-            String id = route.getId();
-            buffer.append("\n    \"").append(id).append("\": {");
-            buffer.append("\n      \"inputs\": [");
-            // for inputs we do not need to check dynamic as we have the data from the route definition
-            Set<String> inputs = RouteDefinitionHelper.gatherAllStaticEndpointUris(this, route, true, false);
-            boolean first = true;
-            for (String input : inputs) {
-                if (!first) {
-                    buffer.append(",");
-                } else {
-                    first = false;
-                }
-                buffer.append("\n        ");
-                buffer.append(StringHelper.toJson("uri", input, true));
-            }
-            buffer.append("\n      ]");
-
-            buffer.append(",");
-            buffer.append("\n      \"outputs\": [");
-            Set<String> outputs = RouteDefinitionHelper.gatherAllEndpointUris(this, route, false, true, includeDynamic);
-            first = true;
-            for (String output : outputs) {
-                if (!first) {
-                    buffer.append(",");
-                } else {
-                    first = false;
-                }
-                buffer.append("\n        ");
-                buffer.append(StringHelper.toJson("uri", output, true));
-            }
-            buffer.append("\n      ]");
-        }
-        if (!firstRoute) {
-            buffer.append("\n    }");
-        }
-        buffer.append("\n  }\n}\n");
-
-        return buffer.toString();
-    }
-
-    // Helper methods
-    // -----------------------------------------------------------------------
-
-    public Language resolveLanguage(String language) {
-        Language answer;
-        synchronized (languages) {
-            answer = languages.get(language);
-
-            // check if the language is singleton, if so return the shared instance
-            if (answer instanceof IsSingleton) {
-                boolean singleton = ((IsSingleton) answer).isSingleton();
-                if (singleton) {
-                    return answer;
-                }
-            }
-
-            // language not known or not singleton, then use resolver
-            answer = getLanguageResolver().resolveLanguage(language, this);
-
-            // inject CamelContext if aware
-            if (answer != null) {
-                if (answer instanceof CamelContextAware) {
-                    ((CamelContextAware) answer).setCamelContext(this);
-                }
-                if (answer instanceof Service) {
-                    try {
-                        startService((Service) answer);
-                    } catch (Exception e) {
-                        throw RuntimeCamelException.wrapRuntimeCamelException(e);
-                    }
-                }
-
-                languages.put(language, answer);
-            }
-        }
-
-        return answer;
-    }
-
-    public String getPropertyPrefixToken() {
-        PropertiesComponent pc = getPropertiesComponent();
-
-        if (pc != null) {
-            return pc.getPrefixToken();
-        } else {
-            return null;
-        }
-    }
-
-    public String getPropertySuffixToken() {
-        PropertiesComponent pc = getPropertiesComponent();
-
-        if (pc != null) {
-            return pc.getSuffixToken();
-        } else {
-            return null;
-        }
-    }
-
-    public String resolvePropertyPlaceholders(String text) throws Exception {
-        // While it is more efficient to only do the lookup if we are sure we need the component,
-        // with custom tokens, we cannot know if the URI contains a property or not without having
-        // the component.  We also lose fail-fast behavior for the missing component with this change.
-        PropertiesComponent pc = getPropertiesComponent();
-
-        // Do not parse uris that are designated for the properties component as it will handle that itself
-        if (text != null && !text.startsWith("properties:")) {
-            // No component, assume default tokens.
-            if (pc == null && text.contains(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) {
-                // lookup existing properties component, or force create a new default component
-                pc = (PropertiesComponent) CamelContextHelper.lookupPropertiesComponent(this, true);
-            }
-
-            if (pc != null && text.contains(pc.getPrefixToken())) {
-                // the parser will throw exception if property key was not found
-                String answer = pc.parseUri(text);
-                log.debug("Resolved text: {} -> {}", text, answer);
-                return answer;
-            }
-        }
-
-        // return original text as is
-        return text;
-    }
-
-    // Properties
-    // -----------------------------------------------------------------------
-
-    public TypeConverter getTypeConverter() {
-        if (typeConverter == null) {
-            synchronized (this) {
-                // we can synchronize on this as there is only one instance
-                // of the camel context (its the container)
-                typeConverter = createTypeConverter();
-                try {
-                    // must add service eager and force start it
-                    addService(typeConverter, true, true);
-                } catch (Exception e) {
-                    throw RuntimeCamelException.wrapRuntimeCamelException(e);
-                }
-            }
-        }
-        return typeConverter;
-    }
-
-    public void setTypeConverter(TypeConverter typeConverter) {
-        this.typeConverter = typeConverter;
-        try {
-            // must add service eager and force start it
-            addService(typeConverter, true, true);
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeCamelException(e);
-        }
-    }
-
-    public TypeConverterRegistry getTypeConverterRegistry() {
-        if (typeConverterRegistry == null) {
-            // init type converter as its lazy
-            if (typeConverter == null) {
-                getTypeConverter();
-            }
-            if (typeConverter instanceof TypeConverterRegistry) {
-                typeConverterRegistry = (TypeConverterRegistry) typeConverter;
-            }
-        }
-        return typeConverterRegistry;
-    }
-
-    public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) {
-        this.typeConverterRegistry = typeConverterRegistry;
-    }
-
-    public Injector getInjector() {
-        if (injector == null) {
-            injector = createInjector();
-        }
-        return injector;
-    }
-
-    public void setInjector(Injector injector) {
-        this.injector = injector;
-    }
-
-    public ManagementMBeanAssembler getManagementMBeanAssembler() {
-        return managementMBeanAssembler;
-    }
-
-    public void setManagementMBeanAssembler(ManagementMBeanAssembler managementMBeanAssembler) {
-        this.managementMBeanAssembler = managementMBeanAssembler;
-    }
-
-    public ComponentResolver getComponentResolver() {
-        if (componentResolver == null) {
-            componentResolver = createComponentResolver();
-        }
-        return componentResolver;
-    }
-
-    public void setComponentResolver(ComponentResolver componentResolver) {
-        this.componentResolver = componentResolver;
-    }
-
-    public LanguageResolver getLanguageResolver() {
-        if (languageResolver == null) {
-            languageResolver = createLanguageResolver();
-        }
-        return languageResolver;
-    }
-
-    public void setLanguageResolver(LanguageResolver languageResolver) {
-        this.languageResolver = languageResolver;
-    }
-
-    public boolean isAutoCreateComponents() {
-        return autoCreateComponents;
-    }
-
-    public void setAutoCreateComponents(boolean autoCreateComponents) {
-        this.autoCreateComponents = autoCreateComponents;
-    }
-
-    public Registry getRegistry() {
-        if (registry == null) {
-            registry = createRegistry();
-            setRegistry(registry);
-        }
-        return registry;
-    }
-
-    public <T> T getRegistry(Class<T> type) {
-        Registry reg = getRegistry();
-
-        // unwrap the property placeholder delegate
-        if (reg instanceof PropertyPlaceholderDelegateRegistry) {
-            reg = ((PropertyPlaceholderDelegateRegistry) reg).getRegistry();
-        }
-
-        if (type.isAssignableFrom(reg.getClass())) {
-            return type.cast(reg);
-        } else if (reg instanceof CompositeRegistry) {
-            List<Registry> list = ((CompositeRegistry) reg).getRegistryList();
-            for (Registry r : list) {
-                if (type.isAssignableFrom(r.getClass())) {
-                    return type.cast(r);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Sets the registry to the given JNDI context
-     *
-     * @param jndiContext is the JNDI context to use as the registry
-     * @see #setRegistry(org.apache.camel.spi.Registry)
-     */
-    public void setJndiContext(Context jndiContext) {
-        setRegistry(new JndiRegistry(jndiContext));
-    }
-
-    public void setRegistry(Registry registry) {
-        // wrap the registry so we always do property placeholder lookups
-        if (!(registry instanceof PropertyPlaceholderDelegateRegistry)) {
-            registry = new PropertyPlaceholderDelegateRegistry(this, registry);
-        }
-        this.registry = registry;
-    }
-
-    public List<LifecycleStrategy> getLifecycleStrategies() {
-        return lifecycleStrategies;
-    }
-
-    public void setLifecycleStrategies(List<LifecycleStrategy> lifecycleStrategies) {
-        this.lifecycleStrategies = lifecycleStrategies;
-    }
-
-    public void addLifecycleStrategy(LifecycleStrategy lifecycleStrategy) {
-        this.lifecycleStrategies.add(lifecycleStrategy);
-    }
-
-    public void setupRoutes(boolean done) {
-        if (done) {
-            isSetupRoutes.remove();
-        } else {
-            isSetupRoutes.set(true);
-        }
-    }
-
-    public synchronized List<RouteDefinition> getRouteDefinitions() {
-        return routeDefinitions;
-    }
-
-    public synchronized RouteDefinition getRouteDefinition(String id) {
-        for (RouteDefinition route : routeDefinitions) {
-            if (route.idOrCreate(nodeIdFactory).equals(id)) {
-                return route;
-            }
-        }
-        return null;
-    }
-
-    public synchronized List<RestDefinition> getRestDefinitions() {
-        return restDefinitions;
-    }
-
-    public void addRestDefinitions(Collection<RestDefinition> restDefinitions) throws Exception {
-        if (restDefinitions == null || restDefinitions.isEmpty()) {
-            return;
-        }
-
-        this.restDefinitions.addAll(restDefinitions);
-    }
-
-    public RestConfiguration getRestConfiguration() {
-        return restConfigurations.get("");
-    }
-
-    public void setRestConfiguration(RestConfiguration restConfiguration) {
-        restConfigurations.put("", restConfiguration);
-    }
-
-    public Collection<RestConfiguration> getRestConfigurations() {
-        return restConfigurations.values();
-    }
-
-    public void addRestConfiguration(RestConfiguration restConfiguration) {
-        restConfigurations.put(restConfiguration.getComponent(), restConfiguration);
-    }
-
-    public RestConfiguration getRestConfiguration(String component, boolean defaultIfNotExist) {
-        if (component == null) {
-            component = "";
-        }
-        RestConfiguration config = restConfigurations.get(component);
-        if (config == null && defaultIfNotExist) {
-            // grab the default configuration
-            config = getRestConfiguration();
-            if (config == null || (config.getComponent() != null && !config.getComponent().equals(component))) {
-                config = new RestConfiguration();
-                restConfigurations.put(component, config);
-            }
-        }
-        return config;
-    }
-
-    @Override
-    public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) {
-        if (serviceName == null) {
-            serviceName = "";
-        }
-
-        return serviceCallConfigurations.get(serviceName);
-    }
-
-    @Override
-    public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
-        serviceCallConfigurations.put("", configuration);
-    }
-
-    @Override
-    public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) {
-        if (configurations != null) {
-            for (ServiceCallConfigurationDefinition configuration : configurations) {
-                serviceCallConfigurations.put(configuration.getId(), configuration);
-            }
-        }
-    }
-
-    @Override
-    public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) {
-        serviceCallConfigurations.put(serviceName, configuration);
-    }
-
-    @Override
-    public HystrixConfigurationDefinition getHystrixConfiguration(String id) {
-        if (id == null) {
-            id = "";
-        }
-
-        return hystrixConfigurations.get(id);
-    }
-
-    @Override
-    public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) {
-        hystrixConfigurations.put("", configuration);
-    }
-
-    @Override
-    public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) {
-        if (configurations != null) {
-            for (HystrixConfigurationDefinition configuration : configurations) {
-                hystrixConfigurations.put(configuration.getId(), configuration);
-            }
-        }
-    }
-
-    @Override
-    public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) {
-        hystrixConfigurations.put(id, configuration);
-    }
-
-    public List<InterceptStrategy> getInterceptStrategies() {
-        return interceptStrategies;
-    }
-
-    public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) {
-        this.interceptStrategies = interceptStrategies;
-    }
-
-    public void addInterceptStrategy(InterceptStrategy interceptStrategy) {
-        getInterceptStrategies().add(interceptStrategy);
-
-        // for backwards compatible or if user add them here instead of the setXXX methods
-
-        if (interceptStrategy instanceof HandleFault) {
-            setHandleFault(true);
-        }
-    }
-
-    public List<RoutePolicyFactory> getRoutePolicyFactories() {
-        return routePolicyFactories;
-    }
-
-    public void setRoutePolicyFactories(List<RoutePolicyFactory> routePolicyFactories) {
-        this.routePolicyFactories = routePolicyFactories;
-    }
-
-    public void addRoutePolicyFactory(RoutePolicyFactory routePolicyFactory) {
-        getRoutePolicyFactories().add(routePolicyFactory);
-    }
-
-    public Set<LogListener> getLogListeners() {
-        return logListeners;
-    }
-
-    public void addLogListener(LogListener listener) {
-        logListeners.add(listener);
-    }
-
-    public void setStreamCaching(Boolean cache) {
-        this.streamCache = cache;
-    }
-
-    public Boolean isStreamCaching() {
-        return streamCache;
-    }
-
-    public void setTracing(Boolean tracing) {
-        this.trace = tracing;
-    }
-
-    public Boolean isTracing() {
-        return trace;
-    }
-
-    public Boolean isMessageHistory() {
-        return messageHistory;
-    }
-
-    public void setMessageHistory(Boolean messageHistory) {
-        this.messageHistory = messageHistory;
-    }
-
-    public void setLogMask(Boolean logMask) {
-        this.logMask = logMask;
-    }
-
-    public Boolean isLogMask() {
-        return logMask != null && logMask;
-    }
-
-    public Boolean isLogExhaustedMessageBody() {
-        return logExhaustedMessageBody;
-    }
-
-    public void setLogExhaustedMessageBody(Boolean logExhaustedMessageBody) {
-        this.logExhaustedMessageBody = logExhaustedMessageBody;
-    }
-
-    public Boolean isHandleFault() {
-        return handleFault;
-    }
-
-    public void setHandleFault(Boolean handleFault) {
-        this.handleFault = handleFault;
-    }
-
-    public Long getDelayer() {
-        return delay;
-    }
-
-    public void setDelayer(Long delay) {
-        this.delay = delay;
-    }
-
-    public ProducerTemplate createProducerTemplate() {
-        return createProducerTemplate(0);
-    }
-
-    public ProducerTemplate createProducerTemplate(int maximumCacheSize) {
-        DefaultProducerTemplate answer = new DefaultProducerTemplate(this);
-        answer.setMaximumCacheSize(maximumCacheSize);
-        // start it so its ready to use
-        try {
-            startService(answer);
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeCamelException(e);
-        }
-        return answer;
-    }
-
-    public FluentProducerTemplate createFluentProducerTemplate() {
-        return createFluentProducerTemplate(0);
-    }
-
-    public FluentProducerTemplate createFluentProducerTemplate(int maximumCacheSize) {
-        DefaultFluentProducerTemplate answer = new DefaultFluentProducerTemplate(this);
-        answer.setMaximumCacheSize(maximumCacheSize);
-        // start it so its ready to use
-        try {
-            startService(answer);
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeCamelException(e);
-        }
-        return answer;
-    }
-
-    public ConsumerTemplate createConsumerTemplate() {
-        return createConsumerTemplate(0);
-    }
-
-    public ConsumerTemplate createConsumerTemplate(int maximumCacheSize) {
-        DefaultConsumerTemplate answer = new DefaultConsumerTemplate(this);
-        answer.setMaximumCacheSize(maximumCacheSize);
-        // start it so its ready to use
-        try {
-            startService(answer);
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeCamelException(e);
-        }
-        return answer;
-    }
-
-    public ErrorHandlerBuilder getErrorHandlerFactory() {
-        return (ErrorHandlerBuilder)errorHandlerBuilder;
-    }
-
-    public void setErrorHandlerFactory(ErrorHandlerFactory errorHandlerFactory) {
-        this.errorHandlerBuilder = errorHandlerFactory;
-    }
-
-    public ScheduledExecutorService getErrorHandlerExecutorService() {
-        synchronized (errorHandlerExecutorServiceLock) {
-            if (errorHandlerExecutorService == null) {
-                // setup default thread pool for error handler
-                errorHandlerExecutorService = getExecutorServiceManager().newDefaultScheduledThreadPool("ErrorHandlerRedeliveryThreadPool", "ErrorHandlerRedeliveryTask");
-            }
-        }
-        return errorHandlerExecutorService;
-    }
-
-    public void setProducerServicePool(ServicePool<Producer> producerServicePool) {
-        this.producerServicePool = producerServicePool;
-    }
-
-    public ServicePool<Producer> getProducerServicePool() {
-        return producerServicePool;
-    }
-
-    public ServicePool<PollingConsumer> getPollingConsumerServicePool() {
-        return pollingConsumerServicePool;
-    }
-
-    public void setPollingConsumerServicePool(ServicePool<PollingConsumer> pollingConsumerServicePool) {
-        this.pollingConsumerServicePool = pollingConsumerServicePool;
-    }
-
-    public UnitOfWorkFactory getUnitOfWorkFactory() {
-        return unitOfWorkFactory;
-    }
-
-    public void setUnitOfWorkFactory(UnitOfWorkFactory unitOfWorkFactory) {
-        this.unitOfWorkFactory = unitOfWorkFactory;
-    }
-
-    public RuntimeEndpointRegistry getRuntimeEndpointRegistry() {
-        return runtimeEndpointRegistry;
-    }
-
-    public void setRuntimeEndpointRegistry(RuntimeEndpointRegistry runtimeEndpointRegistry) {
-        this.runtimeEndpointRegistry = runtimeEndpointRegistry;
-    }
-
-    public String getUptime() {
-        long delta = getUptimeMillis();
-        if (delta == 0) {
-            return "";
-        }
-        return TimeUtils.printDuration(delta);
-    }
-
-    public long getUptimeMillis() {
-        if (startDate == null) {
-            return 0;
-        }
-        return new Date().getTime() - startDate.getTime();
-    }
-
-    public String getVersion() {
-        if (version == null) {
-            synchronized (this) {
-                if (version == null) {
-                    version = doGetVersion();
-                }
-            }
-        }
-        return version;
-    }
-
-    private String doGetVersion() {
-        String version = null;
-
-        InputStream is = null;
-        // try to load from maven properties first
-        try {
-            Properties p = new Properties();
-            is = getClass().getResourceAsStream("/META-INF/maven/org.apache.camel/camel-core/pom.properties");
-            if (is != null) {
-                p.load(is);
-                version = p.getProperty("version", "");
-            }
-        } catch (Exception e) {
-            // ignore
-        } finally {
-            if (is != null) {
-                IOHelper.close(is);
-            }
-        }
-
-        // fallback to using Java API
-        if (version == null) {
-            Package aPackage = getClass().getPackage();
-            if (aPackage != null) {
-                version = aPackage.getImplementationVersion();
-                if (version == null) {
-                    version = aPackage.getSpecificationVersion();
-                }
-            }
-        }
-
-        if (version == null) {
-            // we could not compute the version so use a blank
-            version = "";
-        }
-
-        return version;
-    }
-
-    @Override
-    protected void doSuspend() throws Exception {
-        EventHelper.notifyCamelContextSuspending(this);
-
-        log.info("Apache Camel {} (CamelContext: {}) is suspending", getVersion(), getName());
-        StopWatch watch = new StopWatch();
-
-        // update list of started routes to be suspended
-        // because we only want to suspend started routes
-        // (so when we resume we only resume the routes which actually was suspended)
-        for (Map.Entry<String, RouteService> entry : getRouteServices().entrySet()) {
-            if (entry.getValue().getStatus().isStarted()) {
-                suspendedRouteServices.put(entry.getKey(), entry.getValue());
-            }
-        }
-
-        // assemble list of startup ordering so routes can be shutdown accordingly
-        List<RouteStartupOrder> orders = new ArrayList<>();
-        for (Map.Entry<String, RouteService> entry : suspendedRouteServices.entrySet()) {
-            Route route = entry.getValue().getRoutes().iterator().next();
-            Integer order = entry.getValue().getRouteDefinition().getStartupOrder();
-            if (order == null) {
-                order = defaultRouteStartupOrder++;
-            }
-            orders.add(new DefaultRouteStartupOrder(order, route, entry.getValue()));
-        }
-
-        // suspend routes using the shutdown strategy so it can shutdown in correct order
-        // routes which doesn't support suspension will be stopped instead
-        getShutdownStrategy().suspend(this, orders);
-
-        // mark the route services as suspended or stopped
-        for (RouteService service : suspendedRouteServices.values()) {
-            if (routeSupportsSuspension(service.getId())) {
-                service.suspend();
-            } else {
-                service.stop();
-            }
-        }
-
-        watch.taken();
-        if (log.isInfoEnabled()) {
-            log.info("Apache Camel {} (CamelContext: {}) is suspended in {}", getVersion(), getName(), TimeUtils.printDuration(watch.taken()));
-        }
-
-        EventHelper.notifyCamelContextSuspended(this);
-    }
-
-    @Override
-    protected void doResume() throws Exception {
-        try {
-            EventHelper.notifyCamelContextResuming(this);
-
-            log.info("Apache Camel {} (CamelContext: {}) is resuming", getVersion(), getName());
-            StopWatch watch = new StopWatch();
-
-            // start the suspended routes (do not check for route clashes, and indicate)
-            doStartOrResumeRoutes(suspendedRouteServices, false, true, true, false);
-
-            // mark the route services as resumed (will be marked as started) as well
-            for (RouteService service : suspendedRouteServices.values()) {
-                if (routeSupportsSuspension(service.getId())) {
-                    service.resume();
-                } else {
-                    service.start();
-                }
-            }
-
-            if (log.isInfoEnabled()) {
-                log.info("Resumed {} routes", suspendedRouteServices.size());
-                log.info("Apache Camel {} (CamelContext: {}) resumed in {}", getVersion(), getName(), TimeUtils.printDuration(watch.taken()));
-            }
-
-            // and clear the list as they have been resumed
-            suspendedRouteServices.clear();
-
-            EventHelper.notifyCamelContextResumed(this);
-        } catch (Exception e) {
-            EventHelper.notifyCamelContextResumeFailed(this, e);
-            throw e;
-        }
-    }
-
-    @Override
-    public void start() throws Exception {
-        try (MDCHelper mdcHelper = new MDCHelper()) {
-            init();
-            vetoStated.set(false);
-            startDate = new Date();
-            stopWatch.restart();
-            log.info("Apache Camel {} (CamelContext: {}) is starting", getVersion(), getName());
-
-            // Start the route controller
-            ServiceHelper.startService(this.routeController);
-
-            doNotStartRoutesOnFirstStart = !firstStartDone && !isAutoStartup();
-
-            // if the context was configured with auto startup = false, and we are already started,
-            // then we may need to start the routes on the 2nd start call
-            if (firstStartDone && !isAutoStartup() && isStarted()) {
-                // invoke this logic to warm up the routes and if possible also start the routes
-                doStartOrResumeRoutes(routeServices, true, true, false, true);
-            }
-
-            // super will invoke doStart which will prepare internal services and start routes etc.
-            try {
-                firstStartDone = true;
-                super.start();
-            } catch (VetoCamelContextStartException e) {
-                // mark we veto against starting Camel
-                vetoStated.set(true);
-                if (e.isRethrowException()) {
-                    throw e;
-                } else {
-                    log.info("CamelContext ({}) vetoed to not start due {}", getName(), e.getMessage());
-                    // swallow exception and change state of this camel context to stopped
-                    stop();
-                    return;
-                }
-            }
-
-            if (log.isInfoEnabled()) {
-                // count how many routes are actually started
-                int started = 0;
-                for (Route route : getRoutes()) {
-                    ServiceStatus status = getRouteStatus(route.getId());
-                    if (status != null && status.isStarted()) {
-                        started++;
-                    }
-                }
-
-                final Collection<Route> controlledRoutes = getRouteController().getControlledRoutes();
-                if (controlledRoutes.isEmpty()) {
-                    log.info("Total {} routes, of which {} are started",
-                        getRoutes().size(),
-                        started);
-                } else {
-                    log.info("Total {} routes, of which {} are started, and {} are managed by RouteController: {}",
-                        getRoutes().size(),
-                        started,
-                        controlledRoutes.size(),
-                        getRouteController().getClass().getName()
-                    );
-                }
-                log.info("Apache Camel {} (CamelContext: {}) started in {}", getVersion(), getName(), TimeUtils.printDuration(stopWatch.taken()));
-            }
-
-            // okay the routes has been started so emit event that CamelContext has started (here at the end)
-            EventHelper.notifyCamelContextStarted(this);
-
-            // now call the startup listeners where the routes has been started
-            for (StartupListener startup : startupListeners) {
-                if (startup instanceof ExtendedStartupListener) {
-                    ((ExtendedStartupListener) startup).onCamelContextFullyStarted(this, isStarted());
-                }
-            }
-        }
-    }
-
-    @Override
-    public void stop() throws Exception {
-        try (MDCHelper mdcHelper = new MDCHelper()) {
-            super.stop();
-        }
-    }
-
-    @Override
-    public void suspend() throws Exception {
-        try (MDCHelper mdcHelper = new MDCHelper()) {
-            super.suspend();
-        }
-    }
-
-    @Override
-    public void resume() throws Exception {
-        try (MDCHelper mdcHelper = new MDCHelper()) {
-            super.resume();
-        }
-    }
-
-    @Override
-    public void shutdown() throws Exception {
-        try (MDCHelper mdcHelper = new MDCHelper()) {
-            super.shutdown();
-        }
-    }
-
-    // Implementation methods
-    // -----------------------------------------------------------------------
-
-    protected synchronized void doStart() throws Exception {
-        doWithDefinedClassLoader(() -> {
-            try {
-                doStartCamel();
-            } catch (Exception e) {
-                // fire event that we failed to start
-                EventHelper.notifyCamelContextStartupFailed(DefaultCamelContext.this, e);
-                // rethrow cause
-                throw e;
-            }
-        });
-    }
-
-    private <T extends Throwable> void doWithDefinedClassLoader(ThrowingRunnable<T> callable) throws T {
-        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
-        try {
-            // Using the ApplicationClassLoader as the default for TCCL
-            if (applicationContextClassLoader != null) {
-                Thread.currentThread().setContextClassLoader(applicationContextClassLoader);
-            }
-            callable.run();
-        } finally {
-            Thread.currentThread().setContextClassLoader(tccl);
-        }
-    }
-
-    protected void doStartCamel() throws Exception {
-
-        // custom properties may use property placeholders so resolve those early on
-        if (globalOptions != null && !globalOptions.isEmpty()) {
-            for (Map.Entry<String, String> entry : globalOptions.entrySet()) {
-                String key = entry.getKey();
-                String value = entry.getValue();
-                if (value != null) {
-                    String replaced = resolvePropertyPlaceholders(value);
-                    if (!value.equals(replaced)) {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Camel property with key {} replaced value from {} -> {}", key, value, replaced);
-                        }
-                        entry.setValue(replaced);
-                    }
-                }
-            }
-        }
-
-        if (classResolver instanceof CamelContextAware) {
-            ((CamelContextAware) classResolver).setCamelContext(this);
-        }
-
-        if (log.isDebugEnabled()) {
-            log.debug("Using ClassResolver={}, PackageScanClassResolver={}, ApplicationContextClassLoader={}, RouteController={}",
-                getClassResolver(), getPackageScanClassResolver(), getApplicationContextClassLoader(), getRouteController());
-        }
-
-        if (isStreamCaching()) {
-            log.info("StreamCaching is enabled on CamelContext: {}", getName());
-        }
-
-        if (isTracing()) {
-            // tracing is added in the DefaultChannel so we can enable it on the fly
-            log.info("Tracing is enabled on CamelContext: {}", getName());
-        }
-
-        if (isUseMDCLogging()) {
-            // log if MDC has been enabled
-            log.info("MDC logging is enabled on CamelContext: {}", getName());
-        }
-
-        if (isHandleFault()) {
-            // only add a new handle fault if not already configured
-            if (HandleFault.getHandleFault(this) == null) {
-                log.info("HandleFault is enabled on CamelContext: {}", getName());
-                addInterceptStrategy(new HandleFault());
-            }
-        }
-
-        if (getDelayer() != null && getDelayer() > 0) {
-            log.info("Delayer is enabled with: {} ms. on CamelContext: {}", getDelayer(), getName());
-        }
-
-        // register debugger
-        if (getDebugger() != null) {
-            log.info("Debugger: {} is enabled on CamelContext: {}", getDebugger(), getName());
-            // register this camel context on the debugger
-            getDebugger().setCamelContext(this);
-            startService(getDebugger());
-            addInterceptStrategy(new Debug(getDebugger()));
-        }
-
-        // start management strategy before lifecycles are started
-        ManagementStrategy managementStrategy = getManagementStrategy();
-        startService(managementStrategy);
-
-        // start lifecycle strategies
-        ServiceHelper.startService(lifecycleStrategies);
-        Iterator<LifecycleStrategy> it = lifecycleStrategies.iterator();
-        while (it.hasNext()) {
-            LifecycleStrategy strategy = it.next();
-            try {
-                strategy.onContextStart(this);
-            } catch (VetoCamelContextStartException e) {
-                // okay we should not start Camel since it was vetoed
-                log.warn("Lifecycle strategy vetoed starting CamelContext ({}) due: {}", getName(), e.getMessage());
-                throw e;
-            } catch (Exception e) {
-                log.warn("Lifecycle strategy " + strategy + " failed starting CamelContext ({}) due: {}", getName(), e.getMessage());
-                throw e;
-            }
-        }
-
-        // start notifiers as services
-        for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
-            if (notifier instanceof Service) {
-                Service service = (Service) notifier;
-                for (LifecycleStrategy strategy : lifecycleStrategies) {
-                    strategy.onServiceAdd(this, service, null);
-                }
-                startService((Service) notifier);
-            }
-        }
-
-        // must let some bootstrap service be started before we can notify the starting event
-        EventHelper.notifyCamelContextStarting(this);
-
-        forceLazyInitialization();
-
-        // re-create endpoint registry as the cache size limit may be set after the constructor of this instance was called.
-        // and we needed to create endpoints up-front as it may be accessed before this context is started
-        endpoints = createEndpointRegistry(endpoints);
-        // add this as service and force pre-start them
-        addService(endpoints, true, true);
-        // special for executorServiceManager as want to stop it manually so false in stopOnShutdown
-        addService(executorServiceManager, false, true);
-        addService(producerServicePool, true, true);
-        addService(pollingConsumerServicePool, true, true);
-        addService(inflightRepository, true, true);
-        addService(asyncProcessorAwaitManager, true, true);
-        addService(shutdownStrategy, true, true);
-        addService(packageScanClassResolver, true, true);
-        addService(restRegistry, true, true);
-        addService(messageHistoryFactory, true, true);
-        if (reloadStrategy != null) {
-            log.info("Using ReloadStrategy: {}", reloadStrategy);
-            addService(reloadStrategy, true, true);
-        }
-
-        // Start runtime catalog
-        getExtension(RuntimeCamelCatalog.class);
-
-        // Initialize declarative transformer/validator registry
-        transformerRegistry = createTransformerRegistry(transformers);
-        addService(transformerRegistry, true, true);
-        validatorRegistry = createValidatorRegistry(validators);
-        addService(validatorRegistry, true, true);
-
-        // optimised to not include runtimeEndpointRegistry unlesstartServices its enabled or JMX statistics is in extended mode
-        if (runtimeEndpointRegistry == null && getManagementStrategy() != null && getManagementStrategy().getManagementAgent() != null) {
-            Boolean isEnabled = getManagementStrategy().getManagementAgent().getEndpointRuntimeStatisticsEnabled();
-            boolean isExtended = getManagementStrategy().getManagementAgent().getStatisticsLevel().isExtended();
-            // extended mode is either if we use Extended statistics level or the option is explicit enabled
-            boolean extended = isExtended || isEnabled != null && isEnabled;
-            if (extended) {
-                runtimeEndpointRegistry = new DefaultRuntimeEndpointRegistry();
-            }
-        }
-        if (runtimeEndpointRegistry != null) {
-            if (runtimeEndpointRegistry instanceof EventNotifier) {
-                getManagementStrategy().addEventNotifier((EventNotifier) runtimeEndpointRegistry);
-            }
-            addService(runtimeEndpointRegistry, true, true);
-        }
-
-        // eager lookup any configured properties component to avoid subsequent lookup attempts which may impact performance
-        // due we use properties component for property placeholder resolution at runtime
-        Component existing = CamelContextHelper.lookupPropertiesComponent(this, false);
-        if (existing != null) {
-            // store reference to the existing properties component
-            if (existing instanceof PropertiesComponent) {
-                propertiesComponent = (PropertiesComponent) existing;
-            } else {
-                // properties component must be expected type
-                throw new IllegalArgumentException("Found properties component of type: " + existing.getClass() + " instead of expected: " + PropertiesComponent.class);
-            }
-        }
-
-        // start components
-        startServices(components.values());
-
-        // start the route definitions before the routes is started
-        startRouteDefinitions(routeDefinitions);
-
-        // is there any stream caching enabled then log an info about this and its limit of spooling to disk, so people is aware of this
-        boolean streamCachingInUse = isStreamCaching();
-        if (!streamCachingInUse) {
-            for (RouteDefinition route : routeDefinitions) {
-                Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache());
-                if (routeCache != null && routeCache) {
-                    streamCachingInUse = true;
-                    break;
-                }
-            }
-        }
-
-        if (isUseDataType()) {
-            // log if DataType has been enabled
-            log.info("Message DataType is enabled on CamelContext: {}", getName());
-        }
-
-        if (streamCachingInUse) {
-            // stream caching is in use so enable the strategy
-            getStreamCachingStrategy().setEnabled(true);
-            addService(getStreamCachingStrategy(), true, true);
-        } else {
-            // log if stream caching is not in use as this can help people to enable it if they use streams
-            log.info("StreamCaching is not in use. If using streams then its recommended to enable stream caching."
-                    + " See more details at http://camel.apache.org/stream-caching.html");
-        }
-
-        if (isAllowUseOriginalMessage()) {
-            log.debug("AllowUseOriginalMessage enabled because UseOriginalMessage is in use");
-        }
-
-        // use resolver to find the headers map factory to be used, if we are using the default
-        if (headersMapFactory instanceof DefaultHeadersMapFactory) {
-            headersMapFactory = new HeadersMapFactoryResolver().resolve(this);
-        }
-
-        log.debug("Using HeadersMapFactory: {}", headersMapFactory);
-        if (!headersMapFactory.isCaseInsensitive()) {
-            log.info("HeadersMapFactory: {} is case-sensitive which can cause problems for protocols such as HTTP based, which rely on case-insensitive headers.", getHeadersMapFactory());
-        }
-
-        // start routes
-        if (doNotStartRoutesOnFirstStart) {
-            log.debug("Skip starting routes as CamelContext has been configured with autoStartup=false");
-        }
-
-        // invoke this logic to warmup the routes and if possible also start the routes
-        doStartOrResumeRoutes(routeServices, true, !doNotStartRoutesOnFirstStart, false, true);
-
-        // starting will continue in the start method
-    }
-
-    protected synchronized void doStop() throws Exception {
-        stopWatch.restart();
-        log.info("Apache Camel {} (CamelContext: {}) is shutting down", getVersion(), getName());
-        EventHelper.notifyCamelContextStopping(this);
-
-        // Stop the route controller
-        ServiceHelper.stopAndShutdownService(this.routeController);
-
-        // stop route inputs in the same order as they was started so we stop the very first inputs first
-        try {
-            // force shutting down routes as they may otherwise cause shutdown to hang
-            shutdownStrategy.shutdownForced(this, getRouteStartupOrder());
-        } catch (Throwable e) {
-            log.warn("Error occurred while shutting down routes. This exception will be ignored.", e);
-        }
-
-        // shutdown await manager to trigger interrupt of blocked threads to attempt to free these threads graceful
-        shutdownServices(asyncProcessorAwaitManager);
-
-        routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder).reversed());
-        List<RouteService> list = new ArrayList<>();
-        for (RouteStartupOrder startupOrder : routeStartupOrder) {
-            DefaultRouteStartupOrder order = (DefaultRouteStartupOrder) startupOrder;
-            RouteService routeService = order.getRouteService();
-            list.add(routeService);
-        }
-        shutdownServices(list, false);
-        // do not clear route services or startup listeners as we can start Camel again and get the route back as before
-        routeStartupOrder.clear();
-
-        // but clear any suspend routes
-        suspendedRouteServices.clear();
-
-        // stop consumers from the services to close first, such as POJO consumer (eg @Consumer)
-        // which we need to stop after the routes, as a POJO consumer is essentially a route also
-        for (Service service : servicesToStop) {
-            if (service instanceof Consumer) {
-                shutdownServices(service);
-            }
-        }
-
-        // the stop order is important
-
-        // shutdown default error handler thread pool
-        if (errorHandlerExecutorService != null) {
-            // force shutting down the thread pool
-            getExecutorServiceManager().shutdownNow(errorHandlerExecutorService);
-            errorHandlerExecutorService = null;
-        }
-
-        // shutdown debugger
-        ServiceHelper.stopAndShutdownService(getDebugger());
-
-        shutdownServices(endpoints.values());
-        endpoints.clear();
-
-        shutdownServices(components.values());
-        components.clear();
-
-        shutdownServices(languages.values());
-        languages.clear();
-
-        try {
-            for (LifecycleStrategy strategy : lifecycleStrategies) {
-                strategy.onContextStop(this);
-            }
-        } catch (Throwable e) {
-            log.warn("Error occurred while stopping lifecycle strategies. This exception will be ignored.", e);
-        }
-
-        // shutdown services as late as possible
-        shutdownServices(servicesToStop);
-        servicesToStop.clear();
-
-        // must notify that we are stopped before stopping the management strategy
-        EventHelper.notifyCamelContextStopped(this);
-
-        // stop the notifier service
-        for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
-            shutdownServices(notifier);
-        }
-
-        // shutdown executor service and management as the last one
-        shutdownServices(executorServiceManager);
-        shutdownServices(managementStrategy);
-        shutdownServices(managementMBeanAssembler);
-        shutdownServices(lifecycleStrategies);
-        // do not clear lifecycleStrategies as we can start Camel again and get the route back as before
-
-        // stop the lazy created so they can be re-created on restart
-        forceStopLazyInitialization();
-
-        // stop to clear introspection cache
-        IntrospectionSupport.stop();
-
-        if (log.isInfoEnabled()) {
-            log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") uptime {}", getUptime());
-            log.info("Apache Camel {} (CamelContext: {}) is shutdown in {}", getVersion(), getName(), TimeUtils.printDuration(stopWatch.taken()));
-        }
-
-        // and clear start date
-        startDate = null;
-    }
-
-    /**
-     * Starts or resumes the routes
-     *
-     * @param routeServices  the routes to start (will only start a route if its not already started)
-     * @param checkClash     whether to check for startup ordering clash
-     * @param startConsumer  whether the route consumer should be started. Can be used to warmup the route without starting the consumer.
-     * @param resumeConsumer whether the route consumer should be resumed.
-     * @param addingRoutes   whether we are adding new routes
-     * @throws Exception is thrown if error starting routes
-     */
-    protected void doStartOrResumeRoutes(Map<String, RouteService> routeServices, boolean checkClash,
-                                         boolean startConsumer, boolean resumeConsumer, boolean addingRoutes) throws Exception {
-        isStartingRoutes.set(true);
-        try {
-            // filter out already started routes
-            Map<String, RouteService> filtered = new LinkedHashMap<>();
-            for (Map.Entry<String, RouteService> entry : routeServices.entrySet()) {
-                boolean startable = false;
-
-                Consumer consumer = entry.getValue().getRoutes().iterator().next().getConsumer();
-                if (consumer instanceof SuspendableService) {
-                    // consumer could be suspended, which is not reflected in the RouteService status
-                    startable = ((SuspendableService) consumer).isSuspended();
-                }
-
-                if (!startable && consumer instanceof StatefulService) {
-                    // consumer could be stopped, which is not reflected in the RouteService status
-                    startable = ((StatefulService) consumer).getStatus().isStartable();
-                } else if (!startable) {
-                    // no consumer so use state from route service
-                    startable = entry.getValue().getStatus().isStartable();
-                }
-
-                if (startable) {
-                    filtered.put(entry.getKey(), entry.getValue());
-                }
-            }
-
-            // the context is in last phase of staring, so lets start the routes
-            safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, filtered.values());
-
-        } finally {
-            isStartingRoutes.remove();
-        }
-    }
-
-    protected boolean routeSupportsSuspension(String routeId) {
-        RouteService routeService = routeServices.get(routeId);
-        if (routeService != null) {
-            return routeService.getRoutes().iterator().next().supportsSuspension();
-        }
-        return false;
-    }
-
-    private void shutdownServices(Object service) {
-        // do not rethrow exception as we want to keep shutting down in case of problems
-
-        // allow us to do custom work before delegating to service helper
-        try {
-            if (service instanceof Service) {
-                ServiceHelper.stopAndShutdownService(service);
-            } else if (service instanceof Collection) {
-                ServiceHelper.stopAndShutdownServices((Collection<?>)service);
-            }
-        } catch (Throwable e) {
-            log.warn("Error occurred while shutting down service: " + service + ". This exception will be ignored.", e);
-            // fire event
-            EventHelper.notifyServiceStopFailure(this, service, e);
-        }
-    }
-
-    private void shutdownServices(Collection<?> services) {
-        // reverse stopping by default
-        shutdownServices(services, true);
-    }
-
-    private void shutdownServices(Collection<?> services, boolean reverse) {
-        Collection<?> list = services;
-        if (reverse) {
-            List<Object> reverseList = new ArrayList<>(services);
-            Collections.reverse(reverseList);
-            list = reverseList;
-        }
-
-        for (Object service : list) {
-            shutdownServices(service);
-        }
-    }
-
-    private void startService(Service service) throws Exception {
-        // and register startup aware so they can be notified when
-        // camel context has been started
-        if (service instanceof StartupListener) {
-            StartupListener listener = (StartupListener) service;
-            addStartupListener(listener);
-        }
-
-        if (service instanceof CamelContextAware) {
-            CamelContextAware aware = (CamelContextAware) service;
-            aware.setCamelContext(this);
-        }
-
-        service.start();
-    }
-
-    private void startServices(Collection<?> services) throws Exception {
-        for (Object element : services) {
-            if (element instanceof Service) {
-                startService((Service)element);
-            }
-        }
-    }
-
-    private void stopServices(Object service) throws Exception {
-        // allow us to do custom work before delegating to service helper
-        try {
-            ServiceHelper.stopService(service);
-        } catch (Exception e) {
-            // fire event
-            EventHelper.notifyServiceStopFailure(this, service, e);
-            // rethrow to signal error with stopping
-            throw e;
-        }
-    }
-
-    protected void startRouteDefinitions(Collection<RouteDefinition> list) throws Exception {
-        if (list != null) {
-            for (RouteDefinition route : list) {
-                startRoute(route);
-            }
-        }
-    }
-
-    /**
-     * Starts the given route service
-     */
-    protected synchronized void startRouteService(RouteService routeService, boolean addingRoutes) throws Exception {
-        // we may already be starting routes so remember this, so we can unset accordingly in finally block
-        boolean alreadyStartingRoutes = isStartingRoutes();
-        if (!alreadyStartingRoutes) {
-            isStartingRoutes.set(true);
-        }
-
-        try {
-            // the route service could have been suspended, and if so then resume it instead
-            if (routeService.getStatus().isSuspended()) {
-                resumeRouteService(routeService);
-            } else {
-                // start the route service
-                routeServices.put(routeService.getId(), routeService);
-                if (shouldStartRoutes()) {
-                    // this method will log the routes being started
-                    safelyStartRouteServices(true, true, true, false, addingRoutes, routeService);
-                    // start route services if it was configured to auto startup and we are not adding routes
-                    boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this) && this.isAutoStartup();
-                    if (!addingRoutes || autoStartup) {
-                        // start the route since auto start is enabled or we are starting a route (not adding new routes)
-                        routeService.start();
-                    }
-                }
-            }
-        } finally {
-            if (!alreadyStartingRoutes) {
-                isStartingRoutes.remove();
-            }
-        }
-    }
-
-    /**
-     * Resumes the given route service
-     */
-    protected synchronized void resumeRouteService(RouteService routeService) throws Exception {
-        // the route service could have been stopped, and if so then start it instead
-        if (!routeService.getStatus().isSuspended()) {
-            startRouteService(routeService, false);
-        } else {
-            // resume the route service
-            if (shouldStartRoutes()) {
-                // this method will log the routes being started
-                safelyStartRouteServices(true, false, true, true, false, routeService);
-                // must resume route service as well
-                routeService.resume();
-            }
-        }
-    }
-
-    protected synchronized void stopRouteService(RouteService routeService, boolean removingRoutes) throws Exception {
-        routeService.setRemovingRoutes(removingRoutes);
-        stopRouteService(routeService);
-    }
-
-    protected void logRouteState(Route route, String state) {
-        if (log.isInfoEnabled()) {
-            if (route.getConsumer() != null) {
-                log.info("Route: {} is {}, was consuming from: {}", route.getId(), state, route.getConsumer().getEndpoint());
-            } else {
-                log.info("Route: {} is {}.", route.getId(), state);
-            }
-        }
-    }
-
-    protected synchronized void stopRouteService(RouteService routeService) throws Exception {
-        routeService.stop();
-        for (Route route : routeService.getRoutes()) {
-            logRouteState(route, "stopped");
-        }
-    }
-
-    protected synchronized void shutdownRouteService(RouteService routeService) throws Exception {
-        routeService.shutdown();
-        for (Route route : routeService.getRoutes()) {
-            logRouteState(route, "shutdown and removed");
-        }
-    }
-
-    protected synchronized void suspendRouteService(RouteService routeService) throws Exception {
-        routeService.setRemovingRoutes(false);
-        routeService.suspend();
-        for (Route route : routeService.getRoutes()) {
-            logRouteState(route, "suspended");
-        }
-    }
-
-    /**
-     * Starts the routes services in a proper manner which ensures the routes will be started in correct order,
-     * check for clash and that the routes will also be shutdown in correct order as well.
-     * <p/>
-     * This method <b>must</b> be used to start routes in a safe manner.
-     *
-     * @param checkClash     whether to check for startup order clash
-     * @param startConsumer  whether the route consumer should be started. Can be used to warmup the route without starting the consumer.
-     * @param resumeConsumer whether the route consumer should be resumed.
-     * @param addingRoutes   whether we are adding new routes
-     * @param routeServices  the routes
-     * @throws Exception is thrown if error starting the routes
-     */
-    protected synchronized void safelyStartRouteServices(boolean checkClash, boolean startConsumer, boolean resumeConsumer,
-                                                         boolean addingRoutes, Collection<RouteService> routeServices) throws Exception {
-        // list of inputs to start when all the routes have been prepared for starting
-        // we use a tree map so the routes will be ordered according to startup order defined on the route
-        Map<Integer, DefaultRouteStartupOrder> inputs = new TreeMap<>();
-
-        // figure out the order in which the routes should be started
-        for (RouteService routeService : routeServices) {
-            DefaultRouteStartupOrder order = doPrepareRouteToBeStarted(routeService);
-            // check for clash before we add it as input
-            if (checkClash) {
-                doCheckStartupOrderClash(order, inputs);
-            }
-            inputs.put(order.getStartupOrder(), order);
-        }
-
-        // warm up routes before we start them
-        doWarmUpRoutes(inputs, startConsumer);
-
-        // sort the startup listeners so they are started in the right order
-        startupListeners.sort(OrderedComparator.get());
-        // now call the startup listeners where the routes has been warmed up
-        // (only the actual route consumer has not yet been started)
-        for (StartupListener startup : startupListeners) {
-            startup.onCamelContextStarted(this, isStarted());
-        }
-        // because the consumers may also register startup listeners we need to reset
-        // the already started listeners
-        List<StartupListener> backup = new ArrayList<>(startupListeners);
-        startupListeners.clear();
-
-        // now start the consumers
-        if (startConsumer) {
-            if (resumeConsumer) {
-                // and now resume the routes
-                doResumeRouteConsumers(inputs, addingRoutes);
-            } else {
-                // and now start the routes
-                // and check for clash with multiple consumers of the same endpoints which is not allowed
-                doStartRouteConsumers(inputs, addingRoutes);
-            }
-        }
-
-        // sort the startup listeners so they are started in the right order
-        startupListeners.sort(OrderedComparator.get());
-        // now the consumers that was just started may also add new StartupListeners (such as timer)
-        // so we need to ensure they get started as well
-        for (StartupListener startup : startupListeners) {
-            startup.onCamelContextStarted(this, isStarted());
-        }
-        // and add the previous started startup listeners to the list so we have them all
-        startupListeners.addAll(0, backup);
-
-        // inputs no longer needed
-        inputs.clear();
-    }
-
-    /**
-     * @see #safelyStartRouteServices(boolean,boolean,boolean,boolean,java.util.Collection)
-     */
-    protected synchronized void safelyStartRouteServices(boolean forceAutoStart, boolean checkClash, boolean startConsumer,
-                                                         boolean resumeConsumer, boolean addingRoutes, RouteService... routeServices) throws Exception {
-        safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, Arrays.asList(routeServices));
-    }
-
-    private DefaultRouteStartupOrder doPrepareRouteToBeStarted(RouteService routeService) {
-        // add the inputs from this route service to the list to start afterwards
-        // should be ordered according to the startup number
-        Integer startupOrder = routeService.getRouteDefinition().getStartupOrder();
-        if (startupOrder == null) {
-            // auto assign a default startup order
-            startupOrder = defaultRouteStartupOrder++;
-        }
-
-        // create holder object that contains information about this route to be started
-        Route route = routeService.getRoutes().iterator().next();
-        return new DefaultRouteStartupOrder(startupOrder, route, routeService);
-    }
-
-    private boolean doCheckStartupOrderClash(DefaultRouteStartupOrder answer, Map<Integer, DefaultRouteStartupOrder> inputs) throws FailedToStartRouteException {
-        // check for clash by startupOrder id
-        DefaultRouteStartupOrder other = inputs.get(answer.getStartupOrder());
-        if (other != null && answer != other) {
-            String otherId = other.getRoute().getId();
-            throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder "
-                + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes.");
-        }
-        // check in existing already started as well
-        for (RouteStartupOrder order : routeStartupOrder) {
-            String otherId = order.getRoute().getId();
-            if (answer.getRoute().getId().equals(otherId)) {
-                // its the same route id so skip clash check as its the same route (can happen when using suspend/resume)
-            } else if (answer.getStartupOrder() == order.getStartupOrder()) {
-                throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder "
-                    + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes.");
-            }
-        }
-        return true;
-    }
-
-    private void doWarmUpRoutes(Map<Integer, DefaultRouteStartupOrder> inputs, boolean autoStartup) throws Exception {
-        // now prepare the routes by starting its services before we start the input
-        for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) {
-            // defer starting inputs till later as we want to prepare the routes by starting
-            // all their processors and child services etc.
-            // then later we open the floods to Camel by starting the inputs
-            // what this does is to ensure Camel is more robust on starting routes as all routes
-            // will then be prepared in time before we start inputs which will consume messages to be routed
-            RouteService routeService = entry.getValue().getRouteService();
-            log.debug("Warming up route id: {} having autoStartup={}", routeService.getId(), autoStartup);
-            routeService.warmUp();
-        }
-    }
-
-    private void doResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception {
-        doStartOrResumeRouteConsumers(inputs, true, addingRoutes);
-    }
-
-    private void doStartRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception {
-        doStartOrResumeRouteConsumers(inputs, false, addingRoutes);
-    }
-
-    private void doStartOrResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean resumeOnly, boolean addingRoute) throws Exception {
-        List<Endpoint> routeInputs = new ArrayList<>();
-
-        for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) {
-            Integer order = entry.getKey();
-            Route route = entry.getValue().getRoute();
-            RouteService routeService = entry.getValue().getRouteService();
-
-            // if we are starting camel, then skip routes which are configured to not be auto started
-            boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this) && this.isAutoStartup();
-            if (addingRoute && !autoStartup) {
-                log.info("Skipping starting of route {} as its configured with autoStartup=false", routeService.getId());
-                continue;
-            }
-
-            // start the service
-            for (Consumer consumer : routeService.getInputs().values()) {
-                Endpoint endpoint = consumer.getEndpoint();
-
-                // check multiple consumer violation, with the other routes to be started
-                if (!doCheckMultipleConsumerSupportClash(endpoint, routeInputs)) {
-                    throw new FailedToStartRouteException(routeService.getId(),
-                        "Multiple consumers for the same endpoint is not allowed: " + endpoint);
-                }
-
-                // check for multiple consumer violations with existing routes which
-                // have already been started, or is currently starting
-                List<Endpoint> existingEndpoints = new ArrayList<>();
-                for (Route existingRoute : getRoutes()) {
-                    if (route.getId().equals(existingRoute.getId())) {
-                        // skip ourselves
-                        continue;
-                    }
-                    Endpoint existing = existingRoute.getEndpoint();
-                    ServiceStatus status = getRouteStatus(existingRoute.getId());
-                    if (status != null && (status.isStarted() || status.isStarting())) {
-                        existingEndpoints.add(existing);
-                    }
-                }
-                if (!doCheckMultipleConsumerSupportClash(endpoint, existingEndpoints)) {
-                    throw new FailedToStartRouteException(routeService.getId(),
-                            "Multiple consumers for the same endpoint is not allowed: " + endpoint);
-                }
-
-                // start the consumer on the route
-                log.debug("Route: {} >>> {}", route.getId(), route);
-                if (resumeOnly) {
-                    log.debug("Resuming consumer (order: {}) on route: {}", order, route.getId());
-                } else {
-                    log.debug("Starting consumer (order: {}) on route: {}", order, route.getId());
-                }
-
-                if (resumeOnly && route.supportsSuspension()) {
-                    // if we are resuming and the route can be resumed
-                    ServiceHelper.resumeService(consumer);
-                    log.info("Route: {} resumed and consuming from: {}", route.getId(), endpoint);
-                } else {
-                    // when starting we should invoke the lifecycle strategies
-                    for (LifecycleStrategy strategy : lifecycleStrategies) {
-                        strategy.onServiceAdd(this, consumer, route);
-                    }
-                    try {
-                        startService(consumer);
-                        route.getProperties().remove("route.start.exception");
-                    } catch (Exception e) {
-                        route.getProperties().put("route.start.exception", e);
-                        throw e;
-                    }
-
-                    log.info("Route: {} started and consuming from: {}", route.getId(), endpoint);
-                }
-
-                routeInputs.add(endpoint);
-
-                // add to the order which they was started, so we know how to stop them in reverse order
-                // but only add if we haven't already registered it before (we dont want to double add when restarting)
-                boolean found = false;
-                for (RouteStartupOrder other : routeStartupOrder) {
-                    if (other.getRoute().getId().equals(route.getId())) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found) {
-                    routeStartupOrder.add(entry.getValue());
-                }
-            }
-
-            if (resumeOnly) {
-                routeService.resume();
-            } else {
-                // and start the route service (no need to start children as they are already warmed up)
-                try {
-                    routeService.start();
-                    route.getProperties().remove("route.start.exception");
-                } catch (Exception e) {
-                    route.getProperties().put("route.start.exception", e);
-                    throw e;
-                }
-            }
-        }
-    }
-
-    private boolean doCheckMultipleConsumerSupportClash(Endpoint endpoint, List<Endpoint> routeInputs) {
-        // is multiple consumers supported
-        boolean multipleConsumersSupported = false;
-        if (endpoint instanceof MultipleConsumersSupport) {
-            multipleConsumersSupported = ((MultipleConsumersSupport) endpoint).isMultipleConsumersSupported();
-        }
-
-        if (multipleConsumersSupported) {
-            // multiple consumer allowed, so return true
-            return true;
-        }
-
-        // check in progress list
-        if (routeInputs.contains(endpoint)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Force some lazy initialization to occur upfront before we start any
-     * components and create routes
-     */
-    protected void forceLazyInitialization() {
-        getRegistry();
-        getInjector();
-        getLanguageResolver();
-        getTypeConverterRegistry();
-        getTypeConverter();
-
-        if (isTypeConverterStatisticsEnabled() != null) {
-            getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled());
-        }
-
-        // resolve simple language to initialize it
-        resolveLanguage("simple");
-    }
-
-    /**
-     * Force clear lazy initialization so they can be re-created on restart
-     */
-    protected void forceStopLazyInitialization() {
-        injector = null;
-        languageResolver = null;
-        typeConverterRegistry = null;
-        typeConverter = null;
-    }
-
-    /**
-     * Lazily create a default implementation
-     */
-    protected TypeConverter createTypeConverter() {
-        BaseTypeConverterRegistry answer;
-        answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder(), isLoadTypeConverters());
-        answer.setCamelContext(this);
-        setTypeConverterRegistry(answer);
-        return answer;
-    }
-
-    /**
-     * Lazily create a default implementation
-     */
-    protected Injector createInjector() {
-        FactoryFinder finder = getDefaultFactoryFinder();
-        try {
-            return (Injector) finder.newInstance("Injector");
-        } catch (NoFactoryAvailableException e) {
-            // lets use the default injector
-            return new DefaultInjector(this);
-        }
-    }
-
-    /**
-     * Lazily create a default implementation
-     */
-    protected ComponentResolver createComponentResolver() {
-        return new DefaultComponentResolver();
-    }
-
-    /**
-     * Lazily create a default implementation
-     */
-    protected Registry createRegistry() {
-        JndiRegistry jndi = new JndiRegistry();
-        try {
-            // getContext() will force setting up JNDI
-            jndi.getContext();
-            return jndi;
-        } catch (Throwable e) {
-            log.debug("Cannot create javax.naming.InitialContext due " + e.getMessage() + ". Will fallback and use SimpleRegistry instead. This exception is ignored.", e);
-            return new SimpleRegistry();
-        }
-    }
-
-    /**
-     * A pluggable strategy to allow an endpoint to be created without requiring
-     * a component to be its factory, such as for looking up the URI inside some
-     * {@link Registry}
-     *
-     * @param uri the uri for the endpoint to be created
-     * @return the newly created endpoint or null if it could not be resolved
-     */
-    protected Endpoint createEndpoint(String uri) {
-        Object value = getRegistry().lookupByName(uri);
-        if (value instanceof Endpoint) {
-            return (Endpoint) value;
-        } else if (value instanceof Processor) {
-            return new ProcessorEndpoint(uri, this, (Processor) value);
-        } else if (value != null) {
-            return convertBeanToEndpoint(uri, value);
-        }
-        return null;
-    }
-
-    /**
-     * Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using
-     * some kind of transformation or wrapper
-     *
-     * @param uri  the uri for the endpoint (and name in the registry)
-     * @param bean the bean to be converted to an endpoint, which will be not null
-     * @return a new endpoint
-     */
-    protected Endpoint convertBeanToEndpoint(String uri, Object bean) {
-        throw new IllegalArgumentException("uri: " + uri + " bean: " + bean
-                + " could not be converted to an Endpoint");
-    }
-
-    /**
-     * Should we start newly added routes?
-     */
-    protected boolean shouldStartRoutes() {
-        return isStarted() && !isStarting();
-    }
-
-    /**
-     * Gets the properties component in use.
-     * Returns {@code null} if no properties component is in use.
-     */
-    protected PropertiesComponent getPropertiesComponent() {
-        return propertiesComponent;
-    }
-
-    public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
-        this.dataFormats = dataFormats;
-    }
-
-    public Map<String, DataFormatDefinition> getDataFormats() {
-        return dataFormats;
-    }
-
-    @Override
-    public Map<String, String> getGlobalOptions() {
-        return globalOptions;
-    }
-
-    public void setGlobalOptions(Map<String, String> globalOptions) {
-        this.globalOptions = globalOptions;
-    }
-
-    public FactoryFinder getDefaultFactoryFinder() {
-        if (defaultFactoryFinder == null) {
-            defaultFactoryFinder = getFactoryFinderResolver().resolveDefaultFactoryFinder(getClassResolver());
-        }
-        return defaultFactoryFinder;
-    }
-
-    public FactoryFinderResolver getFactoryFinderResolver() {
-        if (factoryFinderResolver == null) {
-            factoryFinderResolver = createFactoryFinderResolver();
-        }
-        return factoryFinderResolver;
-    }
-
-    public void setFactoryFinderResolver(FactoryFinderResolver resolver) {
-        this.factoryFinderResolver = resolver;
-    }
-
-    public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException {
-        synchronized (factories) {
-            FactoryFinder answer = factories.get(path);
-            if (answer == null) {
-                answer = getFactoryFinderResolver().resolveFactoryFinder(getClassResolver(), path);
-                factories.put(path, answer);
-            }
-            return answer;
-        }
-    }
+/**
+ * Represents the context used to configure routes and the policies to use.
+ */
+public class DefaultCamelContext extends AbstractCamelContext {
 
-    public ClassResolver getClassResolver() {
-        return classResolver;
+    /**
+     * Creates the {@link CamelContext} using {@link JndiRegistry} as registry,
+     * but will silently fallback and use {@link SimpleRegistry} if JNDI cannot be used.
+     * <p/>
+     * Use one of the other constructors to force use an explicit registry / JNDI.
+     */
+    public DefaultCamelContext() {
+        super();
     }
 
-    public void setClassResolver(ClassResolver classResolver) {
-        this.classResolver = classResolver;
+    /**
+     * Creates the {@link CamelContext} using the given JNDI context as the registry
+     *
+     * @param jndiContext the JNDI context
+     */
+    public DefaultCamelContext(Context jndiContext) {
+        super(jndiContext);
     }
 
-    public PackageScanClassResolver getPackageScanClassResolver() {
-        return packageScanClassResolver;
+    /**
+     * Creates the {@link CamelContext} using the given registry
+     *
+     * @param registry the registry
+     */
+    public DefaultCamelContext(Registry registry) {
+        super(registry);
     }
 
-    public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) {
-        this.packageScanClassResolver = packageScanClassResolver;
+    public DefaultCamelContext(boolean init) {
+        super(init);
     }
 
-    public List<String> getComponentNames() {
-        List<String> answer = new ArrayList<>();
-        for (String name : components.keySet()) {
-            answer.add(name);
-        }
+    /**
+     * Lazily create a default implementation
+     */
+    protected TypeConverter createTypeConverter() {
+        BaseTypeConverterRegistry answer;
+        answer = new DefaultTypeConverter(getPackageScanClassResolver(), getInjector(), getDefaultFactoryFinder(), isLoadTypeConverters());
+        answer.setCamelContext(this);
+        setTypeConverterRegistry(answer);
         return answer;
     }
 
-    public List<String> getLanguageNames() {
-        synchronized (languages) {
-            List<String> answer = new ArrayList<>();
-            for (String name : languages.keySet()) {
-                answer.add(name);
-            }
-            return answer;
-        }
-    }
-
-    public ModelJAXBContextFactory getModelJAXBContextFactory() {
-        if (modelJAXBContextFactory == null) {
-            modelJAXBContextFactory = createModelJAXBContextFactory();
-        }
-        return modelJAXBContextFactory;
-    }
-
-    public void setModelJAXBContextFactory(final ModelJAXBContextFactory modelJAXBContextFactory) {
-        this.modelJAXBContextFactory = modelJAXBContextFactory;
-    }
-
-    public NodeIdFactory getNodeIdFactory() {
-        return nodeIdFactory;
-    }
-
-    public void setNodeIdFactory(NodeIdFactory idFactory) {
-        this.nodeIdFactory = idFactory;
-    }
-
-    public ManagementStrategy getManagementStrategy() {
-        return managementStrategy;
-    }
-
-    public void setManagementStrategy(ManagementStrategy managementStrategy) {
-        this.managementStrategy = managementStrategy;
-    }
-
-    public void disableJMX() {
-        if (isNew()) {
-            disableJMX = true;
-        } else if (isInit()) {
-            disableJMX = true;
-            managementStrategy = createManagementStrategy();
-            lifecycleStrategies.clear();
-        } else {
-            throw new IllegalStateException("Disabling JMX can only be done when CamelContext has not been started");
-        }
-    }
-
-    public InflightRepository getInflightRepository() {
-        return inflightRepository;
-    }
-
-    public void setInflightRepository(InflightRepository repository) {
-        this.inflightRepository = repository;
-    }
-
-    public AsyncProcessorAwaitManager getAsyncProcessorAwaitManager() {
-        return asyncProcessorAwaitManager;
-    }
-
-    public void setAsyncProcessorAwaitManager(AsyncProcessorAwaitManager asyncProcessorAwaitManager) {
-        this.asyncProcessorAwaitManager = asyncProcessorAwaitManager;
-    }
-
-    public void setAutoStartup(Boolean autoStartup) {
-        this.autoStartup = autoStartup;
-    }
-
-    public Boolean isAutoStartup() {
-        return autoStartup != null && autoStartup;
-    }
-
-    public Boolean isLoadTypeConverters() {
-        return loadTypeConverters != null && loadTypeConverters;
-    }
-
-    public void setLoadTypeConverters(Boolean loadTypeConverters) {
-        this.loadTypeConverters = loadTypeConverters;
-    }
-
-    public Boolean isTypeConverterStatisticsEnabled() {
-        return typeConverterStatisticsEnabled != null && typeConverterStatisticsEnabled;
-    }
-
-    public void setTypeConverterStatisticsEnabled(Boolean typeConverterStatisticsEnabled) {
-        this.typeConverterStatisticsEnabled = typeConverterStatisticsEnabled;
-    }
-
-    public Boolean isUseMDCLogging() {
-        return useMDCLogging != null && useMDCLogging;
-    }
-
-    public void setUseMDCLogging(Boolean useMDCLogging) {
-        this.useMDCLogging = useMDCLogging;
-    }
-
-    public Boolean isUseDataType() {
-        return useDataType;
-    }
-
     @Override
-    public void setUseDataType(Boolean useDataType) {
-        this.useDataType = useDataType;
-    }
-
-    public Boolean isUseBreadcrumb() {
-        return useBreadcrumb != null && useBreadcrumb;
-    }
-
-    public void setUseBreadcrumb(Boolean useBreadcrumb) {
-        this.useBreadcrumb = useBreadcrumb;
-    }
-
-    public ClassLoader getApplicationContextClassLoader() {
-        return applicationContextClassLoader;
-    }
-
-    public void setApplicationContextClassLoader(ClassLoader classLoader) {
-        applicationContextClassLoader = classLoader;
-    }
-
-    public DataFormatResolver getDataFormatResolver() {
-        if (dataFormatResolver == null) {
-            dataFormatResolver = createDataFormatResolver();
+    protected TypeConverterRegistry createTypeConverterRegistry() {
+        TypeConverter typeConverter = getTypeConverter();
+        if (typeConverter instanceof TypeConverterRegistry) {
+            return (TypeConverterRegistry) typeConverter;
         }
-        return dataFormatResolver;
-    }
-
-    public void setDataFormatResolver(DataFormatResolver dataFormatResolver) {
-        this.dataFormatResolver = dataFormatResolver;
-    }
-
-    public DataFormat resolveDataFormat(String name) {
-        DataFormat answer = getDataFormatResolver().resolveDataFormat(name, this);
-
-        // inject CamelContext if aware
-        if (answer instanceof CamelContextAware) {
-            ((CamelContextAware) answer).setCamelContext(this);
-        }
-
-        return answer;
-    }
-
-    public DataFormat createDataFormat(String name) {
-        DataFormat answer = getDataFormatResolver().createDataFormat(name, this);
-
-        // inject CamelContext if aware
-        if (answer instanceof CamelContextAware) {
-            ((CamelContextAware) answer).setCamelContext(this);
-        }
-
-        return answer;
-    }
-
-    public DataFormatDefinition resolveDataFormatDefinition(String name) {
-        // lookup type and create the data format from it
-        DataFormatDefinition type = lookup(this, name, DataFormatDefinition.class);
-        if (type == null && getDataFormats() != null) {
-            type = getDataFormats().get(name);
-        }
-        return type;
+        return null;
     }
 
-    private static <T> T lookup(CamelContext context, String ref, Class<T> type) {
+    /**
+     * Lazily create a default implementation
+     */
+    protected Injector createInjector() {
+        FactoryFinder finder = getDefaultFactoryFinder();
         try {
-            return context.getRegistry().lookupByNameAndType(ref, type);
-        } catch (Exception e) {
-            // need to ignore not same type and return it as null
-            return null;
-        }
-    }
-
-    public ShutdownStrategy getShutdownStrategy() {
-        return shutdownStrategy;
-    }
-
-    public void setShutdownStrategy(ShutdownStrategy shutdownStrategy) {
-        this.shutdownStrategy = shutdownStrategy;
-    }
-
-    public ShutdownRoute getShutdownRoute() {
-        return shutdownRoute;
-    }
-
-    public void setShutdownRoute(ShutdownRoute shutdownRoute) {
-        this.shutdownRoute = shutdownRoute;
-    }
-
-    public ShutdownRunningTask getShutdownRunningTask() {
-        return shutdownRunningTask;
-    }
-
-    public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) {
-        this.shutdownRunningTask = shutdownRunningTask;
-    }
-
-    public void setAllowUseOriginalMessage(Boolean allowUseOriginalMessage) {
-        this.allowUseOriginalMessage = allowUseOriginalMessage;
-    }
-
-    public Boolean isAllowUseOriginalMessage() {
-        return allowUseOriginalMessage != null && allowUseOriginalMessage;
-    }
-
-    public ExecutorServiceManager getExecutorServiceManager() {
-        return this.executorServiceManager;
-    }
-
-    public void setExecutorServiceManager(ExecutorServiceManager executorServiceManager) {
-        this.executorServiceManager = executorServiceManager;
-    }
-
-    public ProcessorFactory getProcessorFactory() {
-        return processorFactory;
-    }
-
-    public void setProcessorFactory(ProcessorFactory processorFactory) {
-        this.processorFactory = processorFactory;
-    }
-
-    public MessageHistoryFactory getMessageHistoryFactory() {
-        return messageHistoryFactory;
-    }
-
-    public void setMessageHistoryFactory(MessageHistoryFactory messageHistoryFactory) {
-        this.messageHistoryFactory = messageHistoryFactory;
-    }
-
-    public Debugger getDebugger() {
-        return debugger;
-    }
-
-    public void setDebugger(Debugger debugger) {
-        this.debugger = debugger;
-    }
-
-    public UuidGenerator getUuidGenerator() {
-        return uuidGenerator;
-    }
-
-    public void setUuidGenerator(UuidGenerator uuidGenerator) {
-        this.uuidGenerator = uuidGenerator;
-    }
-
-    public StreamCachingStrategy getStreamCachingStrategy() {
-        if (streamCachingStrategy == null) {
-            streamCachingStrategy = new DefaultStreamCachingStrategy();
+            return (Injector) finder.newInstance("Injector");
+        } catch (NoFactoryAvailableException e) {
+            // lets use the default injector
+            return new DefaultInjector(this);
         }
-        return streamCachingStrategy;
-    }
-
-    public void setStreamCachingStrategy(StreamCachingStrategy streamCachingStrategy) {
-        this.streamCachingStrategy = streamCachingStrategy;
     }
 
-    public RestRegistry getRestRegistry() {
-        return restRegistry;
-    }
-
-    public void setRestRegistry(RestRegistry restRegistry) {
-        this.restRegistry = restRegistry;
+    /**
+     * Lazily create a default implementation
+     */
+    protected ComponentResolver createComponentResolver() {
+        return new DefaultComponentResolver();
     }
 
-    @Override
-    public String getGlobalOption(String key) {
-        String value = getGlobalOptions().get(key);
-        if (ObjectHelper.isNotEmpty(value)) {
-            try {
-                value = resolvePropertyPlaceholders(value);
-            } catch (Exception e) {
-                throw new RuntimeCamelException("Error getting global option: " + key, e);
-            }
+    /**
+     * Lazily create a default implementation
+     */
+    protected Registry createRegistry() {
+        JndiRegistry jndi = new JndiRegistry();
+        try {
+            // getContext() will force setting up JNDI
+            jndi.getContext();
+            return jndi;
+        } catch (Throwable e) {
+            log.debug("Cannot create javax.naming.InitialContext due " + e.getMessage() + ". Will fallback and use SimpleRegistry instead. This exception is ignored.", e);
+            return new SimpleRegistry();
         }
-        return value;
-    }
-
-    @Override
-    public ReloadStrategy getReloadStrategy() {
-        return reloadStrategy;
-    }
-
-    @Override
-    public void setReloadStrategy(ReloadStrategy reloadStrategy) {
-        this.reloadStrategy = reloadStrategy;
-    }
-
-    @Override
-    public void setTransformers(List<TransformerDefinition> transformers) {
-        this.transformers = transformers;
-    }
-
-    @Override
-    public List<TransformerDefinition> getTransformers() {
-        return transformers;
-    }
-
-    @Override
-    public Transformer resolveTransformer(String scheme) {
-        return transformerRegistry.resolveTransformer(new TransformerKey(scheme));
-    }
-
-    @Override
-    public Transformer resolveTransformer(DataType from, DataType to) {
-        return transformerRegistry.resolveTransformer(new TransformerKey(from, to));
-    }
-
-    @Override
-    public TransformerRegistry<TransformerKey> getTransformerRegistry() {
-        return transformerRegistry;
-    }
-
-    @Override
-    public void setValidators(List<ValidatorDefinition> validators) {
-        this.validators = validators;
-    }
-
-    @Override
-    public List<ValidatorDefinition> getValidators() {
-        return validators;
-    }
-
-    @Override
-    public Validator resolveValidator(DataType type) {
-        return validatorRegistry.resolveValidator(new ValidatorKey(type));
-    }
-
-    @Override
-    public ValidatorRegistry<ValidatorKey> getValidatorRegistry() {
-        return validatorRegistry;
-    }
-
-    @Override
-    public void setSSLContextParameters(SSLContextParameters sslContextParameters) {
-        this.sslContextParameters = sslContextParameters;
-    }
-
-    @Override
-    public SSLContextParameters getSSLContextParameters() {
-        return this.sslContextParameters;
-    }
-
-    @Override
-    public HeadersMapFactory getHeadersMapFactory() {
-        return headersMapFactory;
-    }
-
-    @Override
-    public void setHeadersMapFactory(HeadersMapFactory headersMapFactory) {
-        this.headersMapFactory = headersMapFactory;
-    }
-
-    protected Map<String, RouteService> getRouteServices() {
-        return routeServices;
     }
 
     protected ManagementStrategy createManagementStrategy() {
-        if (!disableJMX) {
+        if (!isJMXDisabled()) {
             try {
                 ServiceLoader<ManagementStrategyFactory> loader = ServiceLoader.load(ManagementStrategyFactory.class);
                 Iterator<ManagementStrategyFactory> iterator = loader.iterator();
@@ -4577,17 +178,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return new DefaultManagementStrategy(this);
     }
 
-    /**
-     * Reset context counter to a preset value. Mostly used for tests to ensure a predictable getName()
-     *
-     * @param value new value for the context counter
-     */
-    public static void setContextCounter(int value) {
-        DefaultCamelContextNameStrategy.setCounter(value);
-        DefaultManagementNameStrategy.setCounter(value);
-    }
-
-    protected UuidGenerator createDefaultUuidGenerator() {
+    protected UuidGenerator createUuidGenerator() {
         if (System.getProperty("com.google.appengine.runtime.environment") != null) {
             // either "Production" or "Development"
             return new JavaUuidGenerator();
@@ -4600,35 +191,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return new DefaultModelJAXBContextFactory();
     }
 
-    @Override
-    public String toString() {
-        return "CamelContext(" + getName() + ")";
-    }
-
-    class MDCHelper implements AutoCloseable {
-        final Map<String, String> originalContextMap;
-
-        MDCHelper() {
-            if (isUseMDCLogging()) {
-                originalContextMap = MDC.getCopyOfContextMap();
-                MDC.put(MDC_CAMEL_CONTEXT_ID, getName());
-            } else {
-                originalContextMap = null;
-            }
-        }
-
-        @Override
-        public void close() {
-            if (isUseMDCLogging()) {
-                if (originalContextMap != null) {
-                    MDC.setContextMap(originalContextMap);
-                } else {
-                    MDC.clear();
-                }
-            }
-        }
-    }
-
     protected NodeIdFactory createNodeIdFactory() {
         return new DefaultNodeIdFactory();
     }
@@ -4715,13 +277,18 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     }
 
     protected HeadersMapFactory createHeadersMapFactory() {
-        return new DefaultHeadersMapFactory();
+        return new HeadersMapFactoryResolver().resolve(this);
     }
 
     protected LanguageResolver createLanguageResolver() {
         return new DefaultLanguageResolver();
     }
 
+    @Override
+    protected RestRegistry createRestRegistry() {
+        return new DefaultRestRegistry();
+    }
+
     protected EndpointRegistry<EndpointKey> createEndpointRegistry(Map<EndpointKey, Endpoint> endpoints) {
         return new DefaultEndpointRegistry(this, endpoints);
     }
@@ -4734,4 +301,8 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return new DefaultTransformerRegistry(this, transformers);
     }
 
+    @Override
+    protected StreamCachingStrategy createStreamCachingStrategy() {
+        return new DefaultStreamCachingStrategy();
+    }
 }
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultDebugger.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultDebugger.java
index 567bda0..ccbe487 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultDebugger.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultDebugger.java
@@ -42,6 +42,7 @@ import org.apache.camel.spi.Debugger;
 import org.apache.camel.spi.EventNotifier;
 import org.apache.camel.support.EventNotifierSupport;
 import org.apache.camel.support.ServiceHelper;
+import org.apache.camel.support.ServiceSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,9 +50,8 @@ import org.slf4j.LoggerFactory;
 /**
  * The default implementation of the {@link Debugger}.
  */
-public class DefaultDebugger implements Debugger, CamelContextAware {
+public class DefaultDebugger extends ServiceSupport implements Debugger, CamelContextAware {
 
-    private static final Logger LOG = LoggerFactory.getLogger(DefaultDebugger.class);
     private final EventNotifier debugEventNotifier = new DebugEventNotifier();
     private final List<BreakpointConditions> breakpoints = new CopyOnWriteArrayList<>();
     private final int maxConcurrentSingleSteps = 1;
@@ -286,7 +286,7 @@ public class DefaultDebugger implements Debugger, CamelContextAware {
         try {
             breakpoint.beforeProcess(exchange, processor, definition);
         } catch (Throwable e) {
-            LOG.warn("Exception occurred in breakpoint: " + breakpoint + ". This exception will be ignored.", e);
+            log.warn("Exception occurred in breakpoint: " + breakpoint + ". This exception will be ignored.", e);
         }
     }
 
@@ -294,7 +294,7 @@ public class DefaultDebugger implements Debugger, CamelContextAware {
         try {
             breakpoint.afterProcess(exchange, processor, definition, timeTaken);
         } catch (Throwable e) {
-            LOG.warn("Exception occurred in breakpoint: " + breakpoint + ". This exception will be ignored.", e);
+            log.warn("Exception occurred in breakpoint: " + breakpoint + ". This exception will be ignored.", e);
         }
     }
 
@@ -314,7 +314,7 @@ public class DefaultDebugger implements Debugger, CamelContextAware {
         try {
             breakpoint.onEvent(exchange, event, definition);
         } catch (Throwable e) {
-            LOG.warn("Exception occurred in breakpoint: " + breakpoint + ". This exception will be ignored.", e);
+            log.warn("Exception occurred in breakpoint: " + breakpoint + ". This exception will be ignored.", e);
         }
     }
 
@@ -340,6 +340,11 @@ public class DefaultDebugger implements Debugger, CamelContextAware {
 
     @Override
     public void start() throws Exception {
+        super.start();
+    }
+
+    @Override
+    protected void doStart() throws Exception {
         ObjectHelper.notNull(camelContext, "CamelContext", this);
 
         // register our event notifier
@@ -348,7 +353,7 @@ public class DefaultDebugger implements Debugger, CamelContextAware {
     }
 
     @Override
-    public void stop() throws Exception {
+    protected void doStop() throws Exception {
         breakpoints.clear();
         singleSteps.clear();
         ServiceHelper.stopService(debugEventNotifier);
diff --git a/camel-core/src/main/java/org/apache/camel/impl/RouteService.java b/camel-core/src/main/java/org/apache/camel/impl/RouteService.java
index e88636b..1d9a3a7 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/RouteService.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/RouteService.java
@@ -58,7 +58,7 @@ import static org.apache.camel.impl.MDCUnitOfWork.MDC_ROUTE_ID;
  */
 public class RouteService extends ChildServiceSupport {
 
-    private final DefaultCamelContext camelContext;
+    private final AbstractCamelContext camelContext;
     private final RouteDefinition routeDefinition;
     private final List<RouteContext> routeContexts;
     private final List<Route> routes;
@@ -68,7 +68,7 @@ public class RouteService extends ChildServiceSupport {
     private final AtomicBoolean warmUpDone = new AtomicBoolean(false);
     private final AtomicBoolean endpointDone = new AtomicBoolean(false);
 
-    public RouteService(DefaultCamelContext camelContext, RouteDefinition routeDefinition, List<RouteContext> routeContexts, List<Route> routes) {
+    public RouteService(AbstractCamelContext camelContext, RouteDefinition routeDefinition, List<RouteContext> routeContexts, List<Route> routes) {
         this.camelContext = camelContext;
         this.routeDefinition = routeDefinition;
         this.routeContexts = routeContexts;


[camel] 06/08: Fix failing test caused by using a static list of converters

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 7c54a1bb69270078ce89e2547f30bc7a20da73ec
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Nov 8 10:27:40 2018 +0100

    Fix failing test caused by using a static list of converters
---
 .../apache/camel/builder/xml/XPathFeatureTest.java  | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java b/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
index d78dbef..9ea4f24 100644
--- a/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
+++ b/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
@@ -17,6 +17,9 @@
 package org.apache.camel.builder.xml;
 
 import java.io.FileNotFoundException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 
 import org.xml.sax.SAXParseException;
 
@@ -26,6 +29,7 @@ import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.TypeConversionException;
 import org.apache.camel.converter.jaxp.XmlConverter;
+import org.apache.camel.impl.converter.CoreStaticTypeConverterLoader;
 import org.junit.Test;
 
 import static org.apache.camel.builder.xml.XPathBuilder.xpath;
@@ -39,6 +43,23 @@ public class XPathFeatureTest extends ContextTestSupport {
             + " <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM \"file:///bin/test.sh\" >]> <test> &xxe; </test><notwellformed>";
 
     @Override
+    public void setUp() throws Exception {
+        resetCoreConverters();
+        super.setUp();
+    }
+
+    private void resetCoreConverters() throws Exception {
+        Field field = CoreStaticTypeConverterLoader.class.getDeclaredField("INSTANCE");
+        field.setAccessible(true);
+        Field modifiersField = Field.class.getDeclaredField("modifiers");
+        modifiersField.setAccessible(true);
+        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+        Constructor<?> cns = CoreStaticTypeConverterLoader.class.getDeclaredConstructor();
+        cns.setAccessible(true);
+        field.set(null, cns.newInstance());
+    }
+
+    @Override
     public boolean isUseRouteBuilder() {
         return false;
     }


[camel] 05/08: Improve TypeConversionException message

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 958b12e1a8c45ef63c9ad1cdc270664c45552f81
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Nov 8 10:26:35 2018 +0100

    Improve TypeConversionException message
---
 .../src/main/java/org/apache/camel/TypeConversionException.java     | 2 +-
 .../test/java/org/apache/camel/builder/xml/XPathFeatureTest.java    | 6 +++---
 .../src/test/java/org/apache/camel/impl/DefaultComponentTest.java   | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/camel-api/src/main/java/org/apache/camel/TypeConversionException.java b/camel-api/src/main/java/org/apache/camel/TypeConversionException.java
index 4632318..a6b7e01 100644
--- a/camel-api/src/main/java/org/apache/camel/TypeConversionException.java
+++ b/camel-api/src/main/java/org/apache/camel/TypeConversionException.java
@@ -62,7 +62,7 @@ public class TypeConversionException extends RuntimeCamelException {
      */
     public static String createMessage(Object value, Class<?> type, Throwable cause) {
         return "Error during type conversion from type: " + (value != null ? value.getClass().getCanonicalName() : null)
-                + " to the required type: " + type.getCanonicalName() + " with value " + value + " due " + cause.getMessage();
+                + " to the required type: " + type.getCanonicalName() + " with value " + value + " due to " + cause.getClass().getName() + ": " + cause.getMessage();
     }
 
 }
diff --git a/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java b/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
index 50ff16b..d78dbef 100644
--- a/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
+++ b/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
@@ -58,7 +58,7 @@ public class XPathFeatureTest extends ContextTestSupport {
             xpath("/").stringResult().evaluate(createExchange(XML_DATA));
             fail("Expect an Exception here");
         } catch (TypeConversionException ex) {
-            assertTrue("Get a wrong exception cause.", ex.getCause() instanceof FileNotFoundException);
+            assertTrue("Get a wrong exception cause: " + ex.getCause().getClass() + " instead of " + FileNotFoundException.class, ex.getCause() instanceof FileNotFoundException);
         } finally {
             System.clearProperty(DOM_BUILDER_FACTORY_FEATURE + ":"
                 + "http://xml.org/sax/features/external-general-entities");
@@ -72,7 +72,7 @@ public class XPathFeatureTest extends ContextTestSupport {
             xpath("/").documentType(Exchange.class).stringResult().evaluate(createExchange(XML_DATA));
             fail("Expect an Exception here");
         } catch (RuntimeCamelException ex) {
-            assertTrue("Get a wrong exception cause.", ex.getCause() instanceof NoTypeConversionAvailableException);
+            assertTrue("Get a wrong exception cause: " + ex.getCause().getClass() + " instead of " + NoTypeConversionAvailableException.class, ex.getCause() instanceof NoTypeConversionAvailableException);
         }
     }
 
@@ -82,7 +82,7 @@ public class XPathFeatureTest extends ContextTestSupport {
             xpath("/").stringResult().evaluate(createExchange(XML_DATA_INVALID));
             fail("Expect an Exception here");
         } catch (TypeConversionException ex) {
-            assertTrue("Get a wrong exception cause.", ex.getCause() instanceof SAXParseException);
+            assertTrue("Get a wrong exception cause: " + ex.getCause().getClass() + " instead of " + SAXParseException.class, ex.getCause() instanceof SAXParseException);
         }
     }
 
diff --git a/camel-core/src/test/java/org/apache/camel/impl/DefaultComponentTest.java b/camel-core/src/test/java/org/apache/camel/impl/DefaultComponentTest.java
index 6a9b907..94b11dd 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/DefaultComponentTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/DefaultComponentTest.java
@@ -121,7 +121,7 @@ public class DefaultComponentTest extends ContextTestSupport {
         } catch (TypeConversionException ex) {
             assertEquals("Error during type conversion from type: java.lang.String "
                     + "to the required type: java.lang.Integer "
-                    + "with value abc due For input string: \"abc\"", ex.getMessage());
+                    + "with value abc due to java.lang.NumberFormatException: For input string: \"abc\"", ex.getMessage());
         }
     }
 


[camel] 02/08: Make the code more homogeneous in ErrorHandleReifier

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 11da495528f290fdadb6f95564ea7b77595f772a
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Nov 7 16:11:53 2018 +0100

    Make the code more homogeneous in ErrorHandleReifier
---
 .../src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java   | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java b/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java
index ce471a0..5e82fd1 100644
--- a/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java
+++ b/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java
@@ -28,9 +28,7 @@ public class ErrorHandlerReifier {
                 answer.setRedeliveryDelay(CamelContextHelper.parseLong(context, definition.getRedeliveryDelay()));
             }
             if (definition.getAsyncDelayedRedelivery() != null) {
-                if (CamelContextHelper.parseBoolean(context, definition.getAsyncDelayedRedelivery())) {
-                    answer.asyncDelayedRedelivery();
-                }
+                answer.setAsyncDelayedRedelivery(CamelContextHelper.parseBoolean(context, definition.getAsyncDelayedRedelivery()));
             }
             if (definition.getRetriesExhaustedLogLevel() != null) {
                 answer.setRetriesExhaustedLogLevel(definition.getRetriesExhaustedLogLevel());


[camel] 08/08: Fix unit tests

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 96ecf2d7f586c5e882f4434720dfb7800ef7d417
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Nov 8 15:01:11 2018 +0100

    Fix unit tests
---
 .../java/org/apache/camel/impl/AbstractCamelContext.java    | 13 +++++++++----
 .../apache/camel/impl/MultipleLifecycleStrategyTest.java    |  4 ++--
 .../ManagedProducerRouteAddRemoveRegisterAlwaysTest.java    |  2 +-
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/impl/AbstractCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/AbstractCamelContext.java
index 9bd47e2..00aa494 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/AbstractCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/AbstractCamelContext.java
@@ -349,6 +349,10 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Mod
     }
 
     public void doInit() {
+        // setup management strategy first since end users may use it to add event notifiers
+        // using the management strategy before the CamelContext has been started
+        this.managementStrategy = createManagementStrategy();
+
         // Call all registered trackers with this context
         // Note, this may use a partially constructed object
         CamelContextTracker.notifyContextCreated(this);
@@ -902,7 +906,8 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Mod
 
     @Override
     public void setRouteController(RouteController routeController) {
-        this.routeController = doAddService(routeController);
+        this.routeController = routeController;
+        doAddService(routeController);
     }
 
     @Override
@@ -2467,7 +2472,7 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Mod
     public TypeConverterRegistry getTypeConverterRegistry() {
         if (typeConverterRegistry == null) {
             synchronized (this) {
-                if (typeConverter == null) {
+                if (typeConverterRegistry == null) {
                     setTypeConverterRegistry(createTypeConverterRegistry());
                 }
             }
@@ -4006,6 +4011,7 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Mod
             getPackageScanClassResolver();
             getProducerServicePool();
             getPollingConsumerServicePool();
+            getRestRegistry();
 
             if (isTypeConverterStatisticsEnabled() != null) {
                 getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled());
@@ -4022,7 +4028,6 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Mod
                 getComponentResolver();
                 getDataFormatResolver();
                 getManagementStrategy();
-                getRestRegistry();
                 getHeadersMapFactory();
                 getClassResolver();
                 getNodeIdFactory();
@@ -4393,7 +4398,7 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Mod
         if (shutdownStrategy == null) {
             synchronized (this) {
                 if (shutdownStrategy == null) {
-                    shutdownStrategy = createShutdownStrategy();
+                    setShutdownStrategy(createShutdownStrategy());
                 }
             }
         }
diff --git a/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java b/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java
index 23896b3..983c580 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java
@@ -51,8 +51,8 @@ public class MultipleLifecycleStrategyTest extends TestSupport {
 
         List<String> expectedEvents = Arrays.asList("onContextStart",
             "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd",
-            "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", 
-            "onComponentAdd", "onEndpointAdd", "onComponentRemove", "onContextStop");
+            "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd",
+            "onServiceAdd", "onComponentAdd", "onEndpointAdd", "onComponentRemove", "onContextStop");
         
         assertEquals(expectedEvents, dummy1.getEvents());
         assertEquals(expectedEvents, dummy2.getEvents());
diff --git a/camel-management-impl/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java b/camel-management-impl/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java
index 83350bd..5ba8a51 100644
--- a/camel-management-impl/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java
+++ b/camel-management-impl/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java
@@ -28,7 +28,7 @@ import org.junit.Test;
 
 public class ManagedProducerRouteAddRemoveRegisterAlwaysTest extends ManagementTestSupport {
 
-    private int services = 10;
+    private int services = 11;
 
     @Override
     protected CamelContext createCamelContext() throws Exception {


[camel] 01/08: Improve DefaultNodeIdFactory concurrency

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit e1068829f28e71f29121e194d247515171684bc9
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Nov 7 16:11:15 2018 +0100

    Improve DefaultNodeIdFactory concurrency
---
 .../java/org/apache/camel/impl/DefaultNodeIdFactory.java  | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultNodeIdFactory.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultNodeIdFactory.java
index cfc8d40..19cb6ab 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultNodeIdFactory.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultNodeIdFactory.java
@@ -16,8 +16,8 @@
  */
 package org.apache.camel.impl;
 
-import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.camel.NamedNode;
@@ -28,7 +28,7 @@ import org.apache.camel.spi.NodeIdFactory;
  */
 public class DefaultNodeIdFactory implements NodeIdFactory {
 
-    protected static Map<String, AtomicInteger> nodeCounters = new HashMap<>();
+    protected static Map<String, AtomicInteger> nodeCounters = new ConcurrentHashMap<>();
 
     public String createId(NamedNode definition) {
         String key = definition.getShortName();
@@ -38,13 +38,8 @@ public class DefaultNodeIdFactory implements NodeIdFactory {
     /**
      * Returns the counter for the given node key, lazily creating one if necessary
      */
-    protected static synchronized AtomicInteger getNodeCounter(String key) {
-        AtomicInteger answer = nodeCounters.get(key);
-        if (answer == null) {
-            answer = new AtomicInteger(0);
-            nodeCounters.put(key, answer);
-        }
-        return answer;
+    protected static AtomicInteger getNodeCounter(String key) {
+        return nodeCounters.computeIfAbsent(key, k -> new AtomicInteger(0));
     }
 
 
@@ -52,7 +47,7 @@ public class DefaultNodeIdFactory implements NodeIdFactory {
      * Helper method for test purposes that allows tests to start clean (made protected 
      *  to ensure that it is not called accidentally)
      */
-    protected static synchronized void resetAllCounters() {
+    protected static void resetAllCounters() {
         for (AtomicInteger counter : nodeCounters.values()) {
             counter.set(0);
         }


[camel] 03/08: Cache the JAXBContext in ModelJAXBContextFactory

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 121fe1dfc88f64dde4c5b7ced88f76e8004db169
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Nov 7 16:43:14 2018 +0100

    Cache the JAXBContext in ModelJAXBContextFactory
---
 .../camel/impl/DefaultModelJAXBContextFactory.java | 11 ++++++++++-
 .../java/org/apache/camel/model/ModelHelper.java   | 22 ++++++++++++----------
 .../BlueprintModelJAXBContextFactory.java          | 19 +++++++++----------
 .../spring/SpringModelJAXBContextFactory.java      |  4 ----
 .../commands/AbstractLocalCamelController.java     |  4 ++--
 5 files changed, 33 insertions(+), 27 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultModelJAXBContextFactory.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultModelJAXBContextFactory.java
index c830241..348bda2 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultModelJAXBContextFactory.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultModelJAXBContextFactory.java
@@ -27,8 +27,17 @@ import org.apache.camel.spi.ModelJAXBContextFactory;
  */
 public class DefaultModelJAXBContextFactory implements ModelJAXBContextFactory {
 
+    private volatile JAXBContext context;
+
     public JAXBContext newJAXBContext() throws JAXBException {
-        return JAXBContext.newInstance(getPackages(), getClassLoader());
+        if (context == null) {
+            synchronized (this) {
+                if (context == null) {
+                    context = JAXBContext.newInstance(getPackages(), getClassLoader());
+                }
+            }
+        }
+        return context;
     }
 
     protected String getPackages() {
diff --git a/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java b/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java
index 476f15f..dbc95f6 100644
--- a/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java
@@ -41,7 +41,9 @@ import org.apache.camel.Expression;
 import org.apache.camel.NamedNode;
 import org.apache.camel.TypeConversionException;
 import org.apache.camel.converter.jaxp.XmlConverter;
+import org.apache.camel.impl.DefaultModelJAXBContextFactory;
 import org.apache.camel.model.language.ExpressionDefinition;
+import org.apache.camel.spi.ModelJAXBContextFactory;
 import org.apache.camel.spi.NamespaceAware;
 import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.camel.util.ObjectHelper;
@@ -237,13 +239,10 @@ public final class ModelHelper {
     }
 
     private static JAXBContext getJAXBContext(CamelContext context) throws JAXBException {
-        JAXBContext jaxbContext;
-        if (context == null) {
-            jaxbContext = createJAXBContext();
-        } else {
-            jaxbContext = context.getModelJAXBContextFactory().newJAXBContext();
-        }
-        return jaxbContext;
+        ModelJAXBContextFactory factory = context != null
+                ? context.getModelJAXBContextFactory()
+                : getDefaultModelJAXBContextFactory();
+        return factory.newJAXBContext();
     }
 
     private static void applyNamespaces(RouteDefinition route, Map<String, String> namespaces) {
@@ -270,9 +269,12 @@ public final class ModelHelper {
         return na;
     }
 
-    private static JAXBContext createJAXBContext() throws JAXBException {
-        // must use classloader from CamelContext to have JAXB working
-        return JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader());
+    private static class ModelJAXBContextFactoryHolder {
+        private static ModelJAXBContextFactory INSTANCE = new DefaultModelJAXBContextFactory();
+    }
+
+    private static ModelJAXBContextFactory getDefaultModelJAXBContextFactory() {
+        return ModelJAXBContextFactoryHolder.INSTANCE;
     }
 
     /**
diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java
index 1ea5153f..0fed087 100644
--- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java
+++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java
@@ -18,14 +18,12 @@ package org.apache.camel.blueprint;
 
 import java.util.LinkedHashSet;
 import java.util.Set;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
 
 import org.apache.camel.core.xml.AbstractCamelContextFactoryBean;
-import org.apache.camel.spi.ModelJAXBContextFactory;
+import org.apache.camel.impl.DefaultModelJAXBContextFactory;
 import org.apache.camel.util.blueprint.SSLContextParametersFactoryBean;
 
-public class BlueprintModelJAXBContextFactory implements ModelJAXBContextFactory {
+public class BlueprintModelJAXBContextFactory extends DefaultModelJAXBContextFactory {
 
     private final ClassLoader classLoader;
 
@@ -33,7 +31,12 @@ public class BlueprintModelJAXBContextFactory implements ModelJAXBContextFactory
         this.classLoader = classLoader;
     }
 
-    private String getPackages() {
+    @Override
+    protected ClassLoader getClassLoader() {
+        return classLoader;
+    }
+
+    protected String getPackages() {
         // we nedd to have a class from each different package with jaxb models
         // and we must use the .class for the classloader to work in OSGi
         Set<Class<?>> classes = new LinkedHashSet<>();
@@ -54,13 +57,9 @@ public class BlueprintModelJAXBContextFactory implements ModelJAXBContextFactory
             if (packages.length() > 0) {
                 packages.append(":");
             }
-            packages.append(cl.getName().substring(0, cl.getName().lastIndexOf('.')));
+            packages.append(cl.getName(), 0, cl.getName().lastIndexOf('.'));
         }
         return packages.toString();
     }
 
-    @Override
-    public JAXBContext newJAXBContext() throws JAXBException {
-        return JAXBContext.newInstance(getPackages(), classLoader);
-    }
 }
\ No newline at end of file
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/SpringModelJAXBContextFactory.java b/components/camel-spring/src/main/java/org/apache/camel/spring/SpringModelJAXBContextFactory.java
index 37b04ba..2fc3097 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/SpringModelJAXBContextFactory.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/SpringModelJAXBContextFactory.java
@@ -26,10 +26,6 @@ public class SpringModelJAXBContextFactory extends DefaultModelJAXBContextFactor
             + "org.apache.camel.spring:"
             + "org.apache.camel.util.spring:";
 
-    protected ClassLoader getClassLoader() {
-        return getClass().getClassLoader();
-    }
-
     protected String getPackages() {
         return super.getPackages() + ADDITIONAL_JAXB_CONTEXT_PACKAGES;
     }
diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
index 7144478..a07cf12 100644
--- a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
+++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
@@ -379,7 +379,7 @@ public abstract class AbstractLocalCamelController extends AbstractCamelControll
             return null;
         }
 
-        return ModelHelper.dumpModelAsXml(null, route);
+        return ModelHelper.dumpModelAsXml(context, route);
     }
 
     @Override
@@ -421,7 +421,7 @@ public abstract class AbstractLocalCamelController extends AbstractCamelControll
         // use a rests definition to dump the rests
         RestsDefinition def = new RestsDefinition();
         def.setRests(rests);
-        return ModelHelper.dumpModelAsXml(null, def);
+        return ModelHelper.dumpModelAsXml(context, def);
     }
 
     public String getRestApiDocAsJson(String camelContextName) throws Exception {