You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/01/06 11:44:06 UTC

[camel] 04/07: CAMEL-15995: camel-sjms - Make it more feature compatible with camel-jms (producer)

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

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 53692037a023ce7a15c9641729911e2ae31fbe63
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jan 6 07:45:53 2021 +0100

    CAMEL-15995: camel-sjms - Make it more feature compatible with camel-jms (producer)
---
 .../org/apache/camel/catalog/components/sjms.json  |   34 +-
 .../org/apache/camel/catalog/components/sjms2.json |   34 +-
 .../apache/camel/catalog/docs/sjms-component.adoc  |  262 +----
 .../apache/camel/catalog/docs/sjms2-component.adoc |  480 ++------
 components/camel-sjms/pom.xml                      |   12 +-
 .../component/sjms/SjmsComponentConfigurer.java    |   60 +-
 .../component/sjms/SjmsEndpointConfigurer.java     |   42 +-
 .../component/sjms/SjmsEndpointUriFactory.java     |    9 +-
 .../org/apache/camel/component/sjms/sjms.json      |   18 +-
 .../camel-sjms/src/main/docs/sjms-component.adoc   |  262 +----
 .../component/sjms/MessageConsumerResources.java   |   55 -
 .../component/sjms/MessageListenerContainer.java   |    3 +
 .../camel/component/sjms/OldSjmsConsumer.java      |  420 -------
 ...sactionCommitStrategy.java => ReplyToType.java} |   19 +-
 .../apache/camel/component/sjms/SjmsComponent.java |  165 +--
 .../apache/camel/component/sjms/SjmsEndpoint.java  |  199 ++--
 .../apache/camel/component/sjms/SjmsHelper.java    |   32 +-
 .../apache/camel/component/sjms/SjmsProducer.java  |  541 +++++++--
 .../apache/camel/component/sjms/SjmsTemplate.java  |   51 +-
 .../component/sjms/TransactionOnCompletion.java    |   68 ++
 .../sjms/consumer/AbstractMessageHandler.java      |  176 ---
 .../sjms/consumer/InOnlyMessageHandler.java        |   87 --
 .../sjms/consumer/InOutMessageHandler.java         |  175 ---
 .../consumer/SimpleMessageListenerContainer.java   |   86 +-
 .../sjms/jms/ConnectionFactoryResource.java        |  190 ----
 .../component/sjms/jms/ConnectionResource.java     |   51 -
 .../component/sjms/jms/Jms11ObjectFactory.java     |    5 +
 .../camel/component/sjms/jms/JmsObjectFactory.java |    2 +
 .../MessageCreator.java}                           |   16 +-
 .../component/sjms/producer/InOnlyProducer.java    |  145 ---
 .../component/sjms/producer/InOutProducer.java     |  291 -----
 .../sjms/reply/CorrelationTimeoutMap.java          |   70 ++
 .../ExclusiveQueueMessageListenerContainer.java    |   48 +
 .../sjms/reply/MessageSelectorCreator.java         |   86 ++
 .../QueueReplyHandler.java}                        |   18 +-
 .../component/sjms/reply/QueueReplyManager.java    |  142 +++
 .../ReplyHandler.java}                             |   32 +-
 .../camel/component/sjms/reply/ReplyHolder.java    |  124 ++
 .../camel/component/sjms/reply/ReplyManager.java   |  112 ++
 .../component/sjms/reply/ReplyManagerSupport.java  |  264 +++++
 .../TemporaryQueueMessageListenerContainer.java    |   43 +
 .../sjms/reply/TemporaryQueueReplyHandler.java     |   64 ++
 .../sjms/reply/TemporaryQueueReplyManager.java     |  169 +++
 .../apache/camel/component/sjms/reply/package.html |   27 +
 .../sjms/tx/SessionTransactionSynchronization.java |  118 --
 .../component/sjms/ReconnectInOutProducerTest.java |    8 -
 .../component/sjms/ReconnectProducerTest.java      |    9 +-
 .../sjms/SjmsDestinationCreationStrategyTest.java  |   92 --
 .../sjms/SjmsEndpointConnectionSettingsTest.java   |   13 -
 .../sjms/consumer/InOnlyConsumerAsyncTrueTest.java |   59 -
 .../consumer/InOnlyTopicDurableConsumerTest.java   |    2 +-
 .../sjms/consumer/InOutConcurrentConsumerTest.java |    4 +-
 .../sjms/consumer/InOutConsumerQueueAsyncTest.java |   13 +-
 .../consumer/InOutConsumerTempQueueAsyncTest.java  |   16 +-
 .../consumer/InOutSynchronousConsumerTest.java     |    4 +-
 .../component/sjms/it/ConnectionResourceIT.java    |  137 ---
 .../sjms/jms/ConnectionFactoryResourceTest.java    |  109 --
 .../producer/InOutQueueProducerAsyncLoadTest.java  |    2 +-
 .../producer/InOutQueueProducerSyncLoadTest.java   |    2 +-
 .../component/sjms/producer/QueueProducerTest.java |    6 -
 .../sjms/tx/TransactedConcurrentConsumersTest.java |    4 +-
 .../sjms/tx/TransactedConsumerSupport.java         |   10 +-
 .../tx/TransactedConsumersMultipleRouteTest.java   |    4 +-
 .../sjms/tx/TransactedQueueConsumerTest.java       |    4 +-
 .../sjms/tx/TransactedTopicConsumerTest.java       |    5 +-
 .../sjms/tx/TransactedTopicProducerTest.java       |    2 +-
 .../component/sjms2/Sjms2EndpointUriFactory.java   |   56 +-
 .../org/apache/camel/component/sjms2/sjms2.json    |   34 +-
 .../camel-sjms2/src/main/docs/sjms2-component.adoc |  480 ++------
 .../component/sjms2/jms/Jms2ObjectFactory.java     |   18 +
 .../sjms2/Sjms2EndpointConnectionSettingsTest.java |   76 --
 .../consumer/InOnlyTopicDurableConsumerTest.java   |   23 +-
 .../consumer/InOnlyTopicSharedConsumerTest.java    |    6 -
 .../dsl/Sjms2ComponentBuilderFactory.java          |  209 ++--
 .../component/dsl/SjmsComponentBuilderFactory.java |  159 +--
 .../endpoint/dsl/Sjms2EndpointBuilderFactory.java  | 1187 +++++++++++++++-----
 .../endpoint/dsl/SjmsEndpointBuilderFactory.java   |  358 +++---
 .../modules/ROOT/pages/sjms-component.adoc         |  262 +----
 .../modules/ROOT/pages/sjms2-component.adoc        |  480 ++------
 79 files changed, 3795 insertions(+), 5365 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json
index 47a2980..9e065f0 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json
@@ -25,21 +25,17 @@
     "connectionCount": { "kind": "property", "displayName": "Connection Count", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1", "description": "The maximum number of connections available to endpoints started under this component" },
     "connectionFactory": { "kind": "property", "displayName": "Connection Factory", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "javax.jms.ConnectionFactory", "deprecated": false, "autowired": true, "secret": false, "description": "A ConnectionFactory is required to enable the SjmsComponent. It can be set directly or set set as part of a ConnectionResource." },
     "bridgeErrorHandler": { "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a me [...]
-    "reconnectBackOff": { "kind": "property", "displayName": "Reconnect Back Off", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5000, "description": "Backoff in millis on consumer pool reconnection attempts" },
-    "reconnectOnError": { "kind": "property", "displayName": "Reconnect On Error", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Try to apply reconnection logic on consumer pool" },
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during star [...]
     "autowiredEnabled": { "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which t [...]
-    "connectionClientId": { "kind": "property", "displayName": "Connection Client Id", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionMaxWait": { "kind": "property", "displayName": "Connection Max Wait", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5000, "description": "The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionResource": { "kind": "property", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details." },
-    "connectionTestOnBorrow": { "kind": "property", "displayName": "Connection Test On Borrow", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used." },
     "destinationCreationStrategy": { "kind": "property", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "jmsKeyFormatStrategy": { "kind": "property", "displayName": "Jms Key Format Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The defau [...]
     "messageCreatedStrategy": { "kind": "property", "displayName": "Message Created Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.MessageCreatedStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message." },
+    "recoveryInterval": { "kind": "property", "displayName": "Recovery Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds." },
+    "replyToOnTimeoutMaxConcurrentConsumers": { "kind": "property", "displayName": "Reply To On Timeout Max Concurrent Consumers", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request\/reply over JMS." },
+    "requestTimeoutCheckerInterval": { "kind": "property", "displayName": "Request Timeout Checker Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Configures how often Camel should check for timed out Exchanges when doing request\/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeou [...]
     "headerFilterStrategy": { "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." },
-    "connectionPassword": { "kind": "property", "displayName": "Connection Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionUsername": { "kind": "property", "displayName": "Connection Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "transactionCommitStrategy": { "kind": "property", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch." }
+    "password": { "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." },
+    "username": { "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Username to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." }
   },
   "properties": {
     "destinationType": { "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" },
@@ -47,31 +43,37 @@
     "acknowledgementMode": { "kind": "parameter", "displayName": "Acknowledgement Mode", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.SessionAcknowledgementType", "enum": [ "SESSION_TRANSACTED", "CLIENT_ACKNOWLEDGE", "AUTO_ACKNOWLEDGE", "DUPS_OK_ACKNOWLEDGE" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "AUTO_ACKNOWLEDGE", "description": "The JMS acknowledgement name, which is one of:  [...]
     "disableReplyTo": { "kind": "parameter", "displayName": "Disable Reply To", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether Camel ignores the JMSReplyTo header in messages. If true, Camel does not send a reply back to the destination specified in the JMSReplyTo header. You can use this option if you want Camel to consume from  [...]
     "replyTo": { "kind": "parameter", "displayName": "Reply To", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Provides an explicit ReplyTo destination (overrides any incoming value of Message.getJMSReplyTo() in consumer)." },
+    "testConnectionOnStartup": { "kind": "parameter", "displayName": "Test Connection On Startup", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to test the connection on startup. This ensures that when Camel starts that all the JMS consumers have a valid connection to the JMS broker. If a connection cannot be granted then Camel [...]
+    "asyncConsumer": { "kind": "parameter", "displayName": "Async Consumer", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asy [...]
+    "autoStartup": { "kind": "parameter", "displayName": "Auto Startup", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether the consumer container should auto-startup." },
     "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a m [...]
-    "consumerCount": { "kind": "parameter", "displayName": "Consumer Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the number of consumer listeners used for this endpoint." },
+    "concurrentConsumers": { "kind": "parameter", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when consuming from JMS (not for request\/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads. When doing r [...]
     "durableSubscriptionId": { "kind": "parameter", "displayName": "Durable Subscription Id", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the durable subscription Id required for durable topics." },
-    "reconnectBackOff": { "kind": "parameter", "displayName": "Reconnect Back Off", "group": "consumer", "label": "consumer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Backoff in millis on consumer pool reconnection attempts" },
-    "reconnectOnError": { "kind": "parameter", "displayName": "Reconnect On Error", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Try to apply reconnection logic on consumer pool" },
     "replyToDeliveryPersistent": { "kind": "parameter", "displayName": "Reply To Delivery Persistent", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to use persistent delivery by default for replies." },
-    "synchronous": { "kind": "parameter", "displayName": "Synchronous", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported)." },
+    "eagerLoadingOfProperties": { "kind": "parameter", "displayName": "Eager Loading Of Properties", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes c [...]
+    "eagerPoisonBody": { "kind": "parameter", "displayName": "Eager Poison Body", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Poison JMS message due to ${exception.message}", "description": "If eagerLoadingOfProperties is enabled and the JMS message payload (JMS body or JMS properties) is poison (cannot be read\/mapped), then se [...]
     "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...]
     "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
     "messageSelector": { "kind": "parameter", "displayName": "Message Selector", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the JMS Message selector syntax." },
+    "replyToSameDestinationAllowed": { "kind": "parameter", "displayName": "Reply To Same Destination Allowed", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a JMS consumer is allowed to send a reply message to the same destination that the consumer is using to consume from. This prevents an endless loop by c [...]
     "deliveryMode": { "kind": "parameter", "displayName": "Delivery Mode", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "enum": [ "1", "2" ], "deprecated": false, "autowired": false, "secret": false, "description": "Specifies the delivery mode to be used. Possible values are those defined by javax.jms.DeliveryMode. NON_PERSISTENT = 1 and PERSISTENT = 2." },
     "deliveryPersistent": { "kind": "parameter", "displayName": "Delivery Persistent", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether persistent delivery is used by default." },
     "explicitQosEnabled": { "kind": "parameter", "displayName": "Explicit Qos Enabled", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Set if the deliveryMode, priority or timeToLive qualities of service should be used when sending messages. This option is based on Spring's JmsTemplate. The deliveryMode, priority and timeToLi [...]
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during sta [...]
     "preserveMessageQos": { "kind": "parameter", "displayName": "Preserve Message Qos", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDelive [...]
     "priority": { "kind": "parameter", "displayName": "Priority", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "enum": [ "1", "2", "3", "4", "5", "6", "7", "8", "9" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": 4, "description": "Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in orde [...]
+    "replyToConcurrentConsumers": { "kind": "parameter", "displayName": "Reply To Concurrent Consumers", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when doing request\/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads." },
     "replyToOverride": { "kind": "parameter", "displayName": "Reply To Override", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination." },
+    "replyToType": { "kind": "parameter", "displayName": "Reply To Type", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.ReplyToType", "enum": [ "Temporary", "Exclusive" ], "deprecated": false, "autowired": false, "secret": false, "description": "Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request\/reply over JMS. Possible values are: Temporary, Shared, or Exclusi [...]
     "requestTimeout": { "kind": "parameter", "displayName": "Request Timeout", "group": "producer", "label": "producer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeou [...]
     "timeToLive": { "kind": "parameter", "displayName": "Time To Live", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": -1, "description": "When sending messages, specifies the time-to-live of the message (in milliseconds)." },
     "allowNullBody": { "kind": "parameter", "displayName": "Allow Null Body", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown." },
+    "disableTimeToLive": { "kind": "parameter", "displayName": "Disable Time To Live", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Use this option to force disabling time to live. For example when you do request\/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message  [...]
+    "includeSentJMSMessageID": { "kind": "parameter", "displayName": "Include Sent JMSMessage ID", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was  [...]
     "asyncStartListener": { "kind": "parameter", "displayName": "Async Start Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and\/o [...]
     "asyncStopListener": { "kind": "parameter", "displayName": "Async Stop Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to stop the consumer message listener asynchronously, when stopping a route." },
     "connectionCount": { "kind": "parameter", "displayName": "Connection Count", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": true, "autowired": false, "secret": false, "description": "The maximum number of connections available to this endpoint" },
     "connectionFactory": { "kind": "parameter", "displayName": "Connection Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ConnectionFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any" },
-    "connectionResource": { "kind": "parameter", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any" },
     "destinationCreationStrategy": { "kind": "parameter", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "exceptionListener": { "kind": "parameter", "displayName": "Exception Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ExceptionListener", "deprecated": false, "autowired": false, "secret": false, "description": "Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions." },
     "headerFilterStrategy": { "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter header to and from Camel message." },
@@ -79,10 +81,12 @@
     "jmsKeyFormatStrategy": { "kind": "parameter", "displayName": "Jms Key Format Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides two implementations out of the box: default and pass [...]
     "mapJmsMessage": { "kind": "parameter", "displayName": "Map Jms Message", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether Camel should auto map the received JMS message to a suited payload type, such as javax.jms.TextMessage to a String etc. See section about how mapping works below for more details." },
     "messageCreatedStrategy": { "kind": "parameter", "displayName": "Message Created Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.MessageCreatedStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message." },
+    "recoveryInterval": { "kind": "parameter", "displayName": "Recovery Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds." },
+    "synchronous": { "kind": "parameter", "displayName": "Synchronous", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported)." },
+    "transferException": { "kind": "parameter", "displayName": "Transfer Exception", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If enabled and you are using Request Reply messaging (InOut) and an Exchange failed on the consumer side, then the caused Exception will be send back in response as a javax.jms.ObjectMessage. If the client i [...]
     "errorHandlerLoggingLevel": { "kind": "parameter", "displayName": "Error Handler Logging Level", "group": "logging", "label": "consumer,logging", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "WARN", "description": "Allows to configure the default errorHandler logging level for logging uncaught exceptions." },
     "errorHandlerLogStackTrace": { "kind": "parameter", "displayName": "Error Handler Log Stack Trace", "group": "logging", "label": "consumer,logging", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Allows to control whether stacktraces should be logged or not, by the default errorHandler." },
     "transacted": { "kind": "parameter", "displayName": "Transacted", "group": "transaction", "label": "transaction", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to use transacted mode" },
-    "transactionCommitStrategy": { "kind": "parameter", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the commit strategy." },
     "sharedJMSSession": { "kind": "parameter", "displayName": "Shared JMSSession", "group": "transaction (advanced)", "label": "transaction,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS provi [...]
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json
index 8117c35..4fe444a 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json
@@ -25,21 +25,17 @@
     "connectionCount": { "kind": "property", "displayName": "Connection Count", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1", "description": "The maximum number of connections available to endpoints started under this component" },
     "connectionFactory": { "kind": "property", "displayName": "Connection Factory", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "javax.jms.ConnectionFactory", "deprecated": false, "autowired": true, "secret": false, "description": "A ConnectionFactory is required to enable the SjmsComponent. It can be set directly or set set as part of a ConnectionResource." },
     "bridgeErrorHandler": { "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a me [...]
-    "reconnectBackOff": { "kind": "property", "displayName": "Reconnect Back Off", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5000, "description": "Backoff in millis on consumer pool reconnection attempts" },
-    "reconnectOnError": { "kind": "property", "displayName": "Reconnect On Error", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Try to apply reconnection logic on consumer pool" },
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during star [...]
     "autowiredEnabled": { "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which t [...]
-    "connectionClientId": { "kind": "property", "displayName": "Connection Client Id", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionMaxWait": { "kind": "property", "displayName": "Connection Max Wait", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5000, "description": "The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionResource": { "kind": "property", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details." },
-    "connectionTestOnBorrow": { "kind": "property", "displayName": "Connection Test On Borrow", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used." },
     "destinationCreationStrategy": { "kind": "property", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "jmsKeyFormatStrategy": { "kind": "property", "displayName": "Jms Key Format Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The defau [...]
     "messageCreatedStrategy": { "kind": "property", "displayName": "Message Created Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.MessageCreatedStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message." },
+    "recoveryInterval": { "kind": "property", "displayName": "Recovery Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds." },
+    "replyToOnTimeoutMaxConcurrentConsumers": { "kind": "property", "displayName": "Reply To On Timeout Max Concurrent Consumers", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request\/reply over JMS." },
+    "requestTimeoutCheckerInterval": { "kind": "property", "displayName": "Request Timeout Checker Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Configures how often Camel should check for timed out Exchanges when doing request\/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeou [...]
     "headerFilterStrategy": { "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." },
-    "connectionPassword": { "kind": "property", "displayName": "Connection Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionUsername": { "kind": "property", "displayName": "Connection Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "transactionCommitStrategy": { "kind": "property", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch." }
+    "password": { "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." },
+    "username": { "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Username to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." }
   },
   "properties": {
     "destinationType": { "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" },
@@ -47,34 +43,40 @@
     "acknowledgementMode": { "kind": "parameter", "displayName": "Acknowledgement Mode", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.SessionAcknowledgementType", "enum": [ "SESSION_TRANSACTED", "CLIENT_ACKNOWLEDGE", "AUTO_ACKNOWLEDGE", "DUPS_OK_ACKNOWLEDGE" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "AUTO_ACKNOWLEDGE", "description": "The JMS acknowledgement name, which is one of:  [...]
     "disableReplyTo": { "kind": "parameter", "displayName": "Disable Reply To", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether Camel ignores the JMSReplyTo header in messages. If true, Camel does not send a reply back to the destination specified in the JMSReplyTo header. You can use this option if you want Camel to consume from  [...]
     "replyTo": { "kind": "parameter", "displayName": "Reply To", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Provides an explicit ReplyTo destination (overrides any incoming value of Message.getJMSReplyTo() in consumer)." },
+    "testConnectionOnStartup": { "kind": "parameter", "displayName": "Test Connection On Startup", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to test the connection on startup. This ensures that when Camel starts that all the JMS consumers have a valid connection to the JMS broker. If a connection cannot be granted then Camel [...]
+    "asyncConsumer": { "kind": "parameter", "displayName": "Async Consumer", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asy [...]
+    "autoStartup": { "kind": "parameter", "displayName": "Auto Startup", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether the consumer container should auto-startup." },
     "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a m [...]
-    "consumerCount": { "kind": "parameter", "displayName": "Consumer Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the number of consumer listeners used for this endpoint." },
+    "concurrentConsumers": { "kind": "parameter", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when consuming from JMS (not for request\/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads. When doing r [...]
     "durable": { "kind": "parameter", "displayName": "Durable", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets topic consumer to durable." },
     "durableSubscriptionId": { "kind": "parameter", "displayName": "Durable Subscription Id", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the durable subscription Id required for durable topics." },
-    "reconnectBackOff": { "kind": "parameter", "displayName": "Reconnect Back Off", "group": "consumer", "label": "consumer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Backoff in millis on consumer pool reconnection attempts" },
-    "reconnectOnError": { "kind": "parameter", "displayName": "Reconnect On Error", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Try to apply reconnection logic on consumer pool" },
     "replyToDeliveryPersistent": { "kind": "parameter", "displayName": "Reply To Delivery Persistent", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to use persistent delivery by default for replies." },
     "shared": { "kind": "parameter", "displayName": "Shared", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets the consumer to shared." },
     "subscriptionId": { "kind": "parameter", "displayName": "Subscription Id", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the subscription Id, required for durable or shared topics." },
-    "synchronous": { "kind": "parameter", "displayName": "Synchronous", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported)." },
+    "eagerLoadingOfProperties": { "kind": "parameter", "displayName": "Eager Loading Of Properties", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes c [...]
+    "eagerPoisonBody": { "kind": "parameter", "displayName": "Eager Poison Body", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Poison JMS message due to ${exception.message}", "description": "If eagerLoadingOfProperties is enabled and the JMS message payload (JMS body or JMS properties) is poison (cannot be read\/mapped), then se [...]
     "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...]
     "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
     "messageSelector": { "kind": "parameter", "displayName": "Message Selector", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the JMS Message selector syntax." },
+    "replyToSameDestinationAllowed": { "kind": "parameter", "displayName": "Reply To Same Destination Allowed", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a JMS consumer is allowed to send a reply message to the same destination that the consumer is using to consume from. This prevents an endless loop by c [...]
     "deliveryMode": { "kind": "parameter", "displayName": "Delivery Mode", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "enum": [ "1", "2" ], "deprecated": false, "autowired": false, "secret": false, "description": "Specifies the delivery mode to be used. Possible values are those defined by javax.jms.DeliveryMode. NON_PERSISTENT = 1 and PERSISTENT = 2." },
     "deliveryPersistent": { "kind": "parameter", "displayName": "Delivery Persistent", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether persistent delivery is used by default." },
     "explicitQosEnabled": { "kind": "parameter", "displayName": "Explicit Qos Enabled", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Set if the deliveryMode, priority or timeToLive qualities of service should be used when sending messages. This option is based on Spring's JmsTemplate. The deliveryMode, priority and timeToLi [...]
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during sta [...]
     "preserveMessageQos": { "kind": "parameter", "displayName": "Preserve Message Qos", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDelive [...]
     "priority": { "kind": "parameter", "displayName": "Priority", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "enum": [ "1", "2", "3", "4", "5", "6", "7", "8", "9" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": 4, "description": "Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in orde [...]
+    "replyToConcurrentConsumers": { "kind": "parameter", "displayName": "Reply To Concurrent Consumers", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when doing request\/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads." },
     "replyToOverride": { "kind": "parameter", "displayName": "Reply To Override", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination." },
+    "replyToType": { "kind": "parameter", "displayName": "Reply To Type", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.ReplyToType", "enum": [ "Temporary", "Exclusive" ], "deprecated": false, "autowired": false, "secret": false, "description": "Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request\/reply over JMS. Possible values are: Temporary, Shared, or Exclusi [...]
     "requestTimeout": { "kind": "parameter", "displayName": "Request Timeout", "group": "producer", "label": "producer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeou [...]
     "timeToLive": { "kind": "parameter", "displayName": "Time To Live", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": -1, "description": "When sending messages, specifies the time-to-live of the message (in milliseconds)." },
     "allowNullBody": { "kind": "parameter", "displayName": "Allow Null Body", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown." },
+    "disableTimeToLive": { "kind": "parameter", "displayName": "Disable Time To Live", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Use this option to force disabling time to live. For example when you do request\/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message  [...]
+    "includeSentJMSMessageID": { "kind": "parameter", "displayName": "Include Sent JMSMessage ID", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was  [...]
     "asyncStartListener": { "kind": "parameter", "displayName": "Async Start Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and\/o [...]
     "asyncStopListener": { "kind": "parameter", "displayName": "Async Stop Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to stop the consumer message listener asynchronously, when stopping a route." },
     "connectionCount": { "kind": "parameter", "displayName": "Connection Count", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": true, "autowired": false, "secret": false, "description": "The maximum number of connections available to this endpoint" },
     "connectionFactory": { "kind": "parameter", "displayName": "Connection Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ConnectionFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any" },
-    "connectionResource": { "kind": "parameter", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any" },
     "destinationCreationStrategy": { "kind": "parameter", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "exceptionListener": { "kind": "parameter", "displayName": "Exception Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ExceptionListener", "deprecated": false, "autowired": false, "secret": false, "description": "Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions." },
     "headerFilterStrategy": { "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter header to and from Camel message." },
@@ -82,10 +84,12 @@
     "jmsKeyFormatStrategy": { "kind": "parameter", "displayName": "Jms Key Format Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides two implementations out of the box: default and pass [...]
     "mapJmsMessage": { "kind": "parameter", "displayName": "Map Jms Message", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether Camel should auto map the received JMS message to a suited payload type, such as javax.jms.TextMessage to a String etc. See section about how mapping works below for more details." },
     "messageCreatedStrategy": { "kind": "parameter", "displayName": "Message Created Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.MessageCreatedStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message." },
+    "recoveryInterval": { "kind": "parameter", "displayName": "Recovery Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds." },
+    "synchronous": { "kind": "parameter", "displayName": "Synchronous", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported)." },
+    "transferException": { "kind": "parameter", "displayName": "Transfer Exception", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If enabled and you are using Request Reply messaging (InOut) and an Exchange failed on the consumer side, then the caused Exception will be send back in response as a javax.jms.ObjectMessage. If the client i [...]
     "errorHandlerLoggingLevel": { "kind": "parameter", "displayName": "Error Handler Logging Level", "group": "logging", "label": "consumer,logging", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "WARN", "description": "Allows to configure the default errorHandler logging level for logging uncaught exceptions." },
     "errorHandlerLogStackTrace": { "kind": "parameter", "displayName": "Error Handler Log Stack Trace", "group": "logging", "label": "consumer,logging", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Allows to control whether stacktraces should be logged or not, by the default errorHandler." },
     "transacted": { "kind": "parameter", "displayName": "Transacted", "group": "transaction", "label": "transaction", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to use transacted mode" },
-    "transactionCommitStrategy": { "kind": "parameter", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the commit strategy." },
     "sharedJMSSession": { "kind": "parameter", "displayName": "Shared JMSSession", "group": "transaction (advanced)", "label": "transaction,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS provi [...]
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc
index cdabfaa..eaf6c55 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc
@@ -12,33 +12,22 @@ include::{cq-version}@camel-quarkus:ROOT:partial$reference/components/sjms.adoc[
 
 *{component-header}*
 
-The Simple JMS Component, or SJMS, is a JMS client for use with Camel
-that uses well known best practices when it comes to JMS client creation
-and configuration. SJMS contains a brand new JMS client API written
-explicitly for Camel eliminating third party messaging implementations
-keeping it light and resilient. The following features is included:
+The Simple JMS Component is a JMS component that only uses JMS APIs
+and no 3rd-party framework such as Spring JMS.
 
-// TODO: Update this after refactor
+The component was reworked from Camel 3.8 onwards
+to be similar to the existing Camel JMS component that is based on Spring JMS.
 
-* Standard Queue and Topic Support (Durable & Non-Durable)
-* InOnly & InOut MEP Support
-* Asynchronous Producer and Consumer Processing
-* Internal JMS Transaction Support
+The reason is to offer many of the same features and functionality from the JMS component,
+but for users that requires lightweight without having to include the Spring Framework.
 
-Additional key features include:
+There are some advanced features in the Spring JMS component that has been omitted, such as
+shared queues for request/reply. Spring JMS offers fine grained tunings for concurrency settings,
+which can be tweaked for dynamic scaling up and down depending on load. This is a special feature in Spring JMS
+that would require substantial code to implement in SJMS.
 
-* Plugable Connection Resource Management
-* Session, Consumer, & Producer Pooling & Caching Management
-* Support for Customizable Transaction Commit Strategies (Local JMS
-Transactions only)
-
-[NOTE]
-====
-*Why the S in SJMS*
-
-S stands for Simple and Standard and Springless. Also camel-jms was
-already taken.
-====
+The SJMS component does not support for Spring or JTA Transaction, however support for internal local transactions
+is supported using JMS or Transaction or Client Acknowledge Mode. See more further below.
 
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
@@ -90,7 +79,7 @@ You append query options to the URI using the following format,
 == Component Options and Configurations
 
 // component options: START
-The Simple JMS component supports 17 options, which are listed below.
+The Simple JMS component supports 14 options, which are listed below.
 
 
 
@@ -102,18 +91,15 @@ The Simple JMS component supports 17 options, which are listed below.
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. | true | boolean
-| *connectionClientId* (advanced) | The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionMaxWait* (advanced) | The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. | 5000 | long
-| *connectionResource* (advanced) | A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details. |  | ConnectionResource
-| *connectionTestOnBorrow* (advanced) | When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used. | true | boolean
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *jmsKeyFormatStrategy* (advanced) | Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The default strategy will safely marshal dots and hyphens (. and -). Can be used for JMS brokers which do not care whether JMS header keys contain illegal characters. You can provide your own implementation of the org.apache.camel.component.jms.JmsKeyFormatStrategy and refer to it using  [...]
 | *messageCreatedStrategy* (advanced) | To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message. |  | MessageCreatedStrategy
 | *recoveryInterval* (advanced) | Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds. | 5000 | long
+| *replyToOnTimeoutMaxConcurrent{zwsp}Consumers* (advanced) | Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request/reply over JMS. | 1 | int
+| *requestTimeoutCheckerInterval* (advanced) | Configures how often Camel should check for timed out Exchanges when doing request/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeout occurs, then you can lower this interval, to check more frequently. The timeout is determined by the option requestTimeout. | 1000 | long
 | *headerFilterStrategy* (filter) | To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
-| *connectionPassword* (security) | The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionUsername* (security) | The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *transactionCommitStrategy* (transaction) | To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch. |  | TransactionCommitStrategy
+| *password* (security) | Password to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
+| *username* (security) | Username to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
 |===
 // component options: END
 
@@ -138,7 +124,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (47 parameters):
+=== Query Parameters (48 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -151,7 +137,7 @@ with the following path and query parameters:
 | *asyncConsumer* (consumer) | Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asynchronous Routing Engine). This means that messages may be processed not 100% strictly in order. If disabled (as default) then the Exchange is fully processed before the JmsConsumer will pickup the next message from the JMS queue. Note if transac [...]
 | *autoStartup* (consumer) | Specifies whether the consumer container should auto-startup. | true | boolean
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
-| *consumerCount* (consumer) | Sets the number of consumer listeners used for this endpoint. | 1 | int
+| *concurrentConsumers* (consumer) | Specifies the default number of concurrent consumers when consuming from JMS (not for request/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. When doing request/reply over JMS then the option replyToConcurrentConsumers is used to control number of concurrent consumers on the reply message listener. | 1 | int
 | *durableSubscriptionId* (consumer) | Sets the durable subscription Id required for durable topics. |  | String
 | *replyToDeliveryPersistent* (consumer) | Specifies whether to use persistent delivery by default for replies. | true | boolean
 | *eagerLoadingOfProperties* (consumer) | Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes can catch early any issues with the underlying JMS provider and the use of JMS properties. See also the option eagerPoisonBody. | false | boolean
@@ -166,16 +152,18 @@ with the following path and query parameters:
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *preserveMessageQos* (producer) | Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDeliveryMode, and JMSExpiration. You can provide all or only some of them. If not provided, Camel will fall back to use the values from the endpoint instead. So, when using this option, the headers override the values from the endpoint. The explicitQosEnable [...]
 | *priority* (producer) | Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in order for this option to have any effect. There are 9 enums and the value can be one of: 1, 2, 3, 4, 5, 6, 7, 8, 9 | 4 | int
+| *replyToConcurrentConsumers* (producer) | Specifies the default number of concurrent consumers when doing request/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. | 1 | int
 | *replyToOverride* (producer) | Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination. |  | String
+| *replyToType* (producer) | Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request/reply over JMS. Possible values are: Temporary, Shared, or Exclusive. By default Camel will use temporary queues. However if replyTo has been configured, then Shared is used by default. This option allows you to use exclusive queues instead of shared ones. See Camel JMS documentation for more details, and especially the notes about the implications if running  [...]
 | *requestTimeout* (producer) | The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeout value, and thus have per message individual timeout values. See also the requestTimeoutCheckerInterval option. | 20000 | long
 | *timeToLive* (producer) | When sending messages, specifies the time-to-live of the message (in milliseconds). | -1 | long
 | *allowNullBody* (producer) | Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown. | true | boolean
 | *disableTimeToLive* (producer) | Use this option to force disabling time to live. For example when you do request/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message being sent. The problem is that the sender and receiver systems have to have their clocks synchronized, so they are in sync. This is not always so easy to archive. So you can use disableTimeToLive=true to not set a time to live value on the sent message. Then the message w [...]
+| *includeSentJMSMessageID* (producer) | Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was used by the JMS client when the message was sent to the JMS destination. | false | boolean
 | *asyncStartListener* (advanced) | Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and/or failover. This will cause Camel to block while starting routes. By setting this option to true, you will let routes startup, while the JmsConsumer connects to the JMS broker using a dedicated thread in asynchronous mode. If this option is used, then b [...]
 | *asyncStopListener* (advanced) | Whether to stop the consumer message listener asynchronously, when stopping a route. | false | boolean
 | *connectionCount* (advanced) | *Deprecated* The maximum number of connections available to this endpoint |  | Integer
 | *connectionFactory* (advanced) | Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any |  | ConnectionFactory
-| *connectionResource* (advanced) | Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any |  | ConnectionResource
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *exceptionListener* (advanced) | Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions. |  | ExceptionListener
 | *headerFilterStrategy* (advanced) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
@@ -189,97 +177,13 @@ with the following path and query parameters:
 | *errorHandlerLoggingLevel* (logging) | Allows to configure the default errorHandler logging level for logging uncaught exceptions. There are 6 enums and the value can be one of: TRACE, DEBUG, INFO, WARN, ERROR, OFF | WARN | LoggingLevel
 | *errorHandlerLogStackTrace* (logging) | Allows to control whether stacktraces should be logged or not, by the default errorHandler. | true | boolean
 | *transacted* (transaction) | Specifies whether to use transacted mode | false | boolean
-| *transactionCommitStrategy* (transaction) | Sets the commit strategy. |  | TransactionCommitStrategy
 | *sharedJMSSession* (transaction) | Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS providers, use jms component to leverage XA transaction. | true | boolean
 |===
 // endpoint options: END
 
 
 Below is an example of how to configure the `SjmsComponent` with its
-required `ConnectionFactory` provider. It will create a single connection
-by default and store it using the components internal pooling APIs to
-ensure that it is able to service Session creation requests in a thread
-safe manner.
-
-[source,java]
-----
-SjmsComponent component = new SjmsComponent();
-component.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-getContext().addComponent("sjms", component);
-----
-
-For a SJMS component that is required to support a durable subscription,
-you can override the default `ConnectionFactoryResource` instance and set
-the `clientId` property.
-
-[source,java]
-----
-ConnectionFactoryResource connectionResource = new ConnectionFactoryResource();
-connectionResource.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-connectionResource.setClientId("myclient-id");
-
-SjmsComponent component = new SjmsComponent();
-component.setConnectionResource(connectionResource);
-component.setMaxConnections(1);
-----
-
-== Producer Usage
-
-=== InOnly Producer - (Default)
-
-The _InOnly_ producer is the default behavior of the SJMS Producer
-Endpoint.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms:queue:bar");
-----
-
-=== InOut Producer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI. By default it will use a dedicated TemporaryQueue for each
-consumer.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms:queue:bar?exchangePattern=InOut");
-----
-
-You can specify a `replyTo` though which can provide a better
-monitor point.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms:queue:bar?replyTo=my.reply.to.queue");
-----
-
-== Consumer Usage
-
-=== InOnly Consumer - (Default)
-
-The _InOnly_ consumer is the default Exchange behavior of the SJMS
-Consumer Endpoint.
-
-[source,java]
-----
-from("sjms:queue:bar")
-    .to("mock:result");
-----
-
-=== InOut Consumer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI.
-
-[source,java]
-----
-from("sjms:queue:in.out.test?exchangePattern=InOut")
-    .transform(constant("Bye Camel"));
-----
+required `ConnectionFactory` provider.
 
 
 == Reuse endpoint and send to different destinations computed at runtime
@@ -350,89 +254,29 @@ from("direct:order")
   .toD("sjms:order-${header.orderType}");
 --------------------------------
 
-== Advanced Usage Notes
-
-=== Plugable Connection Resource Management [[SJMS-connectionresource]]
-
-SJMS provides JMS `Connection`
-resource management through built-in connection pooling. This eliminates
-the need to depend on third party API pooling logic. However there may
-be times that you are required to use an external Connection resource
-manager such as those provided by J2EE or OSGi containers. For this SJMS
-provides an interface that can be used to override the internal SJMS
-Connection pooling capabilities. This is accomplished through the `ConnectionResource` interface.
-
-The `ConnectionResource`
-provides methods for borrowing and returning Connections as needed is
-the contract used to provide `Connection`
-pools to the SJMS component. A user should use when it is necessary to
-integrate SJMS with an external connection pooling manager.
+== Additional Notes
 
-It is recommended though that for standard JMS `ConnectionFactory`
-providers you use the `ConnectionFactoryResource`
-implementation that is provided with SJMS as-is or extend as it is
-optimized for this component.
+=== Local transactions
 
-Below is an example of using the plugable ConnectionResource with the
-ActiveMQ `PooledConnectionFactory`:
+When using `transacted=true` then JMS Transacted Acknowledge Mode are in use.
+The SJMS component supports this from both the consumer and producers. If a consumer
+is transacted, then the active JMS Session will commit or rollback at the end of processing the message.
 
-[source,java]
-----
-public class AMQConnectionResource implements ConnectionResource {
-    private PooledConnectionFactory pcf;
-
-    public AMQConnectionResource(String connectString, int maxConnections) {
-        super();
-        pcf = new PooledConnectionFactory(connectString);
-        pcf.setMaxConnections(maxConnections);
-        pcf.start();
-    }
-
-    public void stop() {
-        pcf.stop();
-    }
-
-    @Override
-    public Connection borrowConnection() throws Exception {
-        Connection answer = pcf.createConnection();
-        answer.start();
-        return answer;
-    }
-
-    @Override
-    public Connection borrowConnection(long timeout) throws Exception {
-        // SNIPPED...
-    }
-
-    @Override
-    public void returnConnection(Connection connection) throws Exception {
-        // Do nothing since there isn't a way to return a Connection
-        // to the instance of PooledConnectionFactory
-        log.info("Connection returned");
-    }
-}
-----
+SJMS producers that are `transacted=true` will also defer until the end of processing the message
+before the the active JMS Session will commit or rollback.
 
-Then pass in the `ConnectionResource` to the `SjmsComponent`:
+You can combine consumer and producer, such as:
 
 [source,java]
 ----
-CamelContext camelContext = new DefaultCamelContext();
-AMQConnectionResource pool = new AMQConnectionResource("tcp://localhost:33333", 1);
-SjmsComponent component = new SjmsComponent();
-component.setConnectionResource(pool);
-camelContext.addComponent("sjms", component);
+from("sjms:cheese?transacted=true")
+  .to("bean:foo")
+  .to("sjms:foo?transacted=true")
+  .to("bean:bar");
 ----
 
-=== Customizable Transaction Commit Strategies (Local JMS Transactions only)
-
-SJMS provides a developer the means to create a custom and plugable
-transaction strategy through the use of the `TransactionCommitStrategy`
-interface. This allows a user to define a unique set of circumstances
-that the `SessionTransactionSynchronization`
-will use to determine when to commit the Session.
-
-== Additional Notes
+Here the consumer and producer are both transacted, which means that only at the end of processing the message,
+then both the consumer and the producer will commit (or rollback in case of an exception during routing).
 
 === Message Header Format
 
@@ -468,18 +312,13 @@ dropped.
 === Clustering
 
 When using _InOut_ with SJMS in a clustered environment you must either
-use TemporaryQueue destinations or use a unique named reply to
+use TemporaryQueue destinations or use a unique reply to
 destination per InOut producer endpoint. Message correlation is handled
-by the endpoint, not with message selectors at the broker. The InOut
-Producer Endpoint uses Java Concurrency Exchangers cached by the Message
-`JMSCorrelationID`. This provides a nice performance increase while
-reducing the overhead on the broker since all the messages are consumed
-from the destination in the order they are produced by the interested
-consumer.
+by the producer, not with message selectors at the broker.
 
 [NOTE]
 ====
-You should only use queues as destination types, topics is not recommended or fully supported.
+You should only use queues as reply-to destination types, topics is not recommended or fully supported.
 ====
 
 Currently the only correlation strategy is to use the `JMSCorrelationId`.
@@ -487,26 +326,5 @@ The _InOut_ Consumer uses this strategy as well ensuring that all
 responses messages to the included `JMSReplyTo` destination also have the
 `JMSCorrelationId` copied from the request as well.
 
-== Transaction Support [[SJMS-transactions]]
-
-SJMS currently only supports the use of internal JMS Transactions. There
-is no support for the Camel Transaction Processor or the Java
-Transaction API (JTA).
-
-=== Does Springless Mean I Can't Use Spring?
-
-Not at all. Below is an example of the SJMS component using the Spring XML:
-
-[source,xml]
-----
-<route>
-    <from uri="direct:invoke.named.reply.to.queue" />
-    <to uri="sjms:queue:named.reply.to.queue?namedReplyTo=my.response.queue" />
-</route>
-----
-
-Springless refers to moving away from the dependency on the Spring JMS
-API. A new JMS client API is being developed from the ground up to power
-SJMS.
 
 include::camel-spring-boot::page$sjms-starter.adoc[]
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc
index 133a721..a638296 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc
@@ -12,33 +12,22 @@ include::{cq-version}@camel-quarkus:ROOT:partial$reference/components/sjms2.adoc
 
 *{component-header}*
 
-The Simple JMS 2.0 Component, or SJMS2, is a JMS client for use with Camel
-that uses well known best practices when it comes to JMS client creation
-and configuration. SJMS2 contains a brand new JMS 2.0 client API written
-explicitly for Camel eliminating third party messaging implementations
-keeping it light and resilient. The following features is included:
-
-* Standard Queue and Topic Support (Durable & Non-Durable)
-* InOnly & InOut MEP Support
-* Asynchronous Producer and Consumer Processing
-* Internal JMS Transaction Support
-
-Additional key features include:
-
-* Plugable Connection Resource Management
-* Session, Consumer, & Producer Pooling & Caching Management
-* Batch Consumers and Producers
-* Transacted Batch Consumers & Producers
-* Support for Customizable Transaction Commit Strategies (Local JMS
-Transactions only)
+The Simple JMS Component is a JMS component that only uses JMS APIs
+and no 3rd-party framework such as Spring JMS.
 
-[NOTE]
-====
-*Why the S in SJMS*
+The component was reworked from Camel 3.8 onwards
+to be similar to the existing Camel JMS component that is based on Spring JMS.
 
-S stands for Simple and Standard and Springless. Also camel-jms was
-already taken.
-====
+The reason is to offer many of the same features and functionality from the JMS component,
+but for users that requires lightweight without having to include the Spring Framework.
+
+There are some advanced features in the Spring JMS component that has been omitted, such as
+shared queues for request/reply. Spring JMS offers fine grained tunings for concurrency settings,
+which can be tweaked for dynamic scaling up and down depending on load. This is a special feature in Spring JMS
+that would require substantial code to implement in SJMS2.
+
+The SJMS2 component does not support for Spring or JTA Transaction, however support for internal local transactions
+is supported using JMS or Transaction or Client Acknowledge Mode. See more further below.
 
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
@@ -55,7 +44,7 @@ for this component:
 
 == URI format
 
-[source]
+[source,text]
 ----
 sjms2:[queue:|topic:]destinationName[?options]
 ----
@@ -64,14 +53,14 @@ Where `destinationName` is a JMS queue or topic name. By default, the
 `destinationName` is interpreted as a queue name. For example, to
 connect to the queue, `FOO.BAR` use:
 
-[source]
+[source,text]
 ----
 sjms2:FOO.BAR
 ----
 
 You can include the optional `queue:` prefix, if you prefer:
 
-[source]
+[source,text]
 ----
 sjms2:queue:FOO.BAR
 ----
@@ -79,7 +68,7 @@ sjms2:queue:FOO.BAR
 To connect to a topic, you _must_ include the `topic:` prefix. For
 example, to connect to the topic, `Stocks.Prices`, use:
 
-[source]
+[source,text]
 ----
 sjms2:topic:Stocks.Prices
 ----
@@ -89,11 +78,8 @@ You append query options to the URI using the following format,
 
 == Component Options and Configurations
 
-
-
-
 // component options: START
-The Simple JMS2 component supports 18 options, which are listed below.
+The Simple JMS2 component supports 14 options, which are listed below.
 
 
 
@@ -103,31 +89,21 @@ The Simple JMS2 component supports 18 options, which are listed below.
 | *connectionCount* (common) | The maximum number of connections available to endpoints started under this component | 1 | Integer
 | *connectionFactory* (common) | *Autowired* A ConnectionFactory is required to enable the SjmsComponent. It can be set directly or set set as part of a ConnectionResource. |  | ConnectionFactory
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
-| *reconnectBackOff* (consumer) | Backoff in millis on consumer pool reconnection attempts | 5000 | long
-| *reconnectOnError* (consumer) | Try to apply reconnection logic on consumer pool | true | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. | true | boolean
-| *connectionClientId* (advanced) | The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionMaxWait* (advanced) | The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. | 5000 | long
-| *connectionResource* (advanced) | A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details. |  | ConnectionResource
-| *connectionTestOnBorrow* (advanced) | When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used. | true | boolean
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *jmsKeyFormatStrategy* (advanced) | Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The default strategy will safely marshal dots and hyphens (. and -). Can be used for JMS brokers which do not care whether JMS header keys contain illegal characters. You can provide your own implementation of the org.apache.camel.component.jms.JmsKeyFormatStrategy and refer to it using  [...]
 | *messageCreatedStrategy* (advanced) | To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message. |  | MessageCreatedStrategy
+| *recoveryInterval* (advanced) | Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds. | 5000 | long
+| *replyToOnTimeoutMaxConcurrent{zwsp}Consumers* (advanced) | Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request/reply over JMS. | 1 | int
+| *requestTimeoutCheckerInterval* (advanced) | Configures how often Camel should check for timed out Exchanges when doing request/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeout occurs, then you can lower this interval, to check more frequently. The timeout is determined by the option requestTimeout. | 1000 | long
 | *headerFilterStrategy* (filter) | To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
-| *connectionPassword* (security) | The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionUsername* (security) | The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *transactionCommitStrategy* (transaction) | To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch. |  | TransactionCommitStrategy
+| *password* (security) | Password to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
+| *username* (security) | Username to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
 |===
 // component options: END
 
 
-
-
-
-
-
-
 // endpoint options: START
 The Simple JMS2 endpoint is configured using URI syntax:
 
@@ -148,7 +124,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (43 parameters):
+=== Query Parameters (51 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -157,34 +133,40 @@ with the following path and query parameters:
 | *acknowledgementMode* (common) | The JMS acknowledgement name, which is one of: SESSION_TRANSACTED, CLIENT_ACKNOWLEDGE, AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE. There are 4 enums and the value can be one of: SESSION_TRANSACTED, CLIENT_ACKNOWLEDGE, AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE | AUTO_ACKNOWLEDGE | SessionAcknowledgementType
 | *disableReplyTo* (common) | Specifies whether Camel ignores the JMSReplyTo header in messages. If true, Camel does not send a reply back to the destination specified in the JMSReplyTo header. You can use this option if you want Camel to consume from a route and you do not want Camel to automatically send back a reply message because another component in your code handles the reply message. You can also use this option if you want to use Camel as a proxy between different message broker [...]
 | *replyTo* (common) | Provides an explicit ReplyTo destination (overrides any incoming value of Message.getJMSReplyTo() in consumer). |  | String
+| *testConnectionOnStartup* (common) | Specifies whether to test the connection on startup. This ensures that when Camel starts that all the JMS consumers have a valid connection to the JMS broker. If a connection cannot be granted then Camel throws an exception on startup. This ensures that Camel is not started with failed connections. The JMS producers is tested as well. | false | boolean
+| *asyncConsumer* (consumer) | Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asynchronous Routing Engine). This means that messages may be processed not 100% strictly in order. If disabled (as default) then the Exchange is fully processed before the JmsConsumer will pickup the next message from the JMS queue. Note if transac [...]
+| *autoStartup* (consumer) | Specifies whether the consumer container should auto-startup. | true | boolean
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
-| *consumerCount* (consumer) | Sets the number of consumer listeners used for this endpoint. | 1 | int
+| *concurrentConsumers* (consumer) | Specifies the default number of concurrent consumers when consuming from JMS (not for request/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. When doing request/reply over JMS then the option replyToConcurrentConsumers is used to control number of concurrent consumers on the reply message listener. | 1 | int
 | *durable* (consumer) | Sets topic consumer to durable. | false | boolean
 | *durableSubscriptionId* (consumer) | Sets the durable subscription Id required for durable topics. |  | String
-| *reconnectBackOff* (consumer) | Backoff in millis on consumer pool reconnection attempts | 5000 | long
-| *reconnectOnError* (consumer) | Try to apply reconnection logic on consumer pool | true | boolean
 | *replyToDeliveryPersistent* (consumer) | Specifies whether to use persistent delivery by default for replies. | true | boolean
 | *shared* (consumer) | Sets the consumer to shared. | false | boolean
 | *subscriptionId* (consumer) | Sets the subscription Id, required for durable or shared topics. |  | String
-| *synchronous* (consumer) | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). | true | boolean
+| *eagerLoadingOfProperties* (consumer) | Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes can catch early any issues with the underlying JMS provider and the use of JMS properties. See also the option eagerPoisonBody. | false | boolean
+| *eagerPoisonBody* (consumer) | If eagerLoadingOfProperties is enabled and the JMS message payload (JMS body or JMS properties) is poison (cannot be read/mapped), then set this text as the message body instead so the message can be processed (the cause of the poison are already stored as exception on the Exchange). This can be turned off by setting eagerPoisonBody=false. See also the option eagerLoadingOfProperties. | Poison JMS message due to ${exception.message} | String
 | *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
 | *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. There are 3 enums and the value can be one of: InOnly, InOut, InOptionalOut |  | ExchangePattern
 | *messageSelector* (consumer) | Sets the JMS Message selector syntax. |  | String
+| *replyToSameDestinationAllowed* (consumer) | Whether a JMS consumer is allowed to send a reply message to the same destination that the consumer is using to consume from. This prevents an endless loop by consuming and sending back the same message to itself. | false | boolean
 | *deliveryMode* (producer) | Specifies the delivery mode to be used. Possible values are those defined by javax.jms.DeliveryMode. NON_PERSISTENT = 1 and PERSISTENT = 2. There are 2 enums and the value can be one of: 1, 2 |  | Integer
 | *deliveryPersistent* (producer) | Specifies whether persistent delivery is used by default. | true | boolean
 | *explicitQosEnabled* (producer) | Set if the deliveryMode, priority or timeToLive qualities of service should be used when sending messages. This option is based on Spring's JmsTemplate. The deliveryMode, priority and timeToLive options are applied to the current endpoint. This contrasts with the preserveMessageQos option, which operates at message granularity, reading QoS properties exclusively from the Camel In message headers. | false | Boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *preserveMessageQos* (producer) | Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDeliveryMode, and JMSExpiration. You can provide all or only some of them. If not provided, Camel will fall back to use the values from the endpoint instead. So, when using this option, the headers override the values from the endpoint. The explicitQosEnable [...]
 | *priority* (producer) | Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in order for this option to have any effect. There are 9 enums and the value can be one of: 1, 2, 3, 4, 5, 6, 7, 8, 9 | 4 | int
+| *replyToConcurrentConsumers* (producer) | Specifies the default number of concurrent consumers when doing request/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. | 1 | int
 | *replyToOverride* (producer) | Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination. |  | String
+| *replyToType* (producer) | Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request/reply over JMS. Possible values are: Temporary, Shared, or Exclusive. By default Camel will use temporary queues. However if replyTo has been configured, then Shared is used by default. This option allows you to use exclusive queues instead of shared ones. See Camel JMS documentation for more details, and especially the notes about the implications if running  [...]
 | *requestTimeout* (producer) | The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeout value, and thus have per message individual timeout values. See also the requestTimeoutCheckerInterval option. | 20000 | long
 | *timeToLive* (producer) | When sending messages, specifies the time-to-live of the message (in milliseconds). | -1 | long
 | *allowNullBody* (producer) | Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown. | true | boolean
+| *disableTimeToLive* (producer) | Use this option to force disabling time to live. For example when you do request/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message being sent. The problem is that the sender and receiver systems have to have their clocks synchronized, so they are in sync. This is not always so easy to archive. So you can use disableTimeToLive=true to not set a time to live value on the sent message. Then the message w [...]
+| *includeSentJMSMessageID* (producer) | Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was used by the JMS client when the message was sent to the JMS destination. | false | boolean
 | *asyncStartListener* (advanced) | Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and/or failover. This will cause Camel to block while starting routes. By setting this option to true, you will let routes startup, while the JmsConsumer connects to the JMS broker using a dedicated thread in asynchronous mode. If this option is used, then b [...]
 | *asyncStopListener* (advanced) | Whether to stop the consumer message listener asynchronously, when stopping a route. | false | boolean
 | *connectionCount* (advanced) | *Deprecated* The maximum number of connections available to this endpoint |  | Integer
 | *connectionFactory* (advanced) | Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any |  | ConnectionFactory
-| *connectionResource* (advanced) | Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any |  | ConnectionResource
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *exceptionListener* (advanced) | Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions. |  | ExceptionListener
 | *headerFilterStrategy* (advanced) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
@@ -192,325 +174,112 @@ with the following path and query parameters:
 | *jmsKeyFormatStrategy* (advanced) | Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides two implementations out of the box: default and passthrough. The default strategy will safely marshal dots and hyphens (. and -). The passthrough strategy leaves the key as is. Can be used for JMS brokers which do not care whether JMS header keys contain illegal characters. You can provide your own implementation of the org.apache [...]
 | *mapJmsMessage* (advanced) | Specifies whether Camel should auto map the received JMS message to a suited payload type, such as javax.jms.TextMessage to a String etc. See section about how mapping works below for more details. | true | boolean
 | *messageCreatedStrategy* (advanced) | To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message. |  | MessageCreatedStrategy
+| *recoveryInterval* (advanced) | Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds. | 5000 | long
+| *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+| *transferException* (advanced) | If enabled and you are using Request Reply messaging (InOut) and an Exchange failed on the consumer side, then the caused Exception will be send back in response as a javax.jms.ObjectMessage. If the client is Camel, the returned Exception is rethrown. This allows you to use Camel JMS as a bridge in your routing - for example, using persistent queues to enable robust routing. Notice that if you also have transferExchange enabled, this option takes preced [...]
 | *errorHandlerLoggingLevel* (logging) | Allows to configure the default errorHandler logging level for logging uncaught exceptions. There are 6 enums and the value can be one of: TRACE, DEBUG, INFO, WARN, ERROR, OFF | WARN | LoggingLevel
 | *errorHandlerLogStackTrace* (logging) | Allows to control whether stacktraces should be logged or not, by the default errorHandler. | true | boolean
 | *transacted* (transaction) | Specifies whether to use transacted mode | false | boolean
-| *transactionCommitStrategy* (transaction) | Sets the commit strategy. |  | TransactionCommitStrategy
 | *sharedJMSSession* (transaction) | Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS providers, use jms component to leverage XA transaction. | true | boolean
 |===
 // endpoint options: END
 
 
+Below is an example of how to configure the `SjmsComponent` with its
+required `ConnectionFactory` provider.
 
 
+== Reuse endpoint and send to different destinations computed at runtime
 
+If you need to send messages to a lot of different JMS destinations, it
+makes sense to reuse a SJMS endpoint and specify the real destination in
+a message header. This allows Camel to reuse the same endpoint, but send
+to different destinations. This greatly reduces the number of endpoints
+created and economizes on memory and thread resources.
 
-Below is an example of how to configure the `Sjms2Component` with its
-required `ConnectionFactory` provider. It will create a single connection
-by default and store it using the component's internal pooling APIs to
-ensure that it is able to service Session creation requests in a thread
-safe manner.
-
-[source,java]
-----
-Sjms2Component component = new Sjms2Component();
-component.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-getContext().addComponent("sjms2", component);
-----
-
-For a SJMS2 component that is required to support a durable subscription,
-you can override the default `ConnectionFactoryResource` instance and set
-the `clientId` property.
-
-[source,java]
-----
-ConnectionFactoryResource connectionResource = new ConnectionFactoryResource();
-connectionResource.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-connectionResource.setClientId("myclient-id");
-
-Sjms2Component component = new Sjms2Component();
-component.setConnectionResource(connectionResource);
-component.setMaxConnections(1);
-----
+TIP: Using xref:{eip-vc}:eips:toD-eip.adoc[toD] is easier than specifying the dynamic destination with a header
 
-== Producer Usage
+You can specify the destination in the following headers:
 
-=== InOnly Producer - (Default)
+[width="100%",cols="10%,10%,80%",options="header",]
+|=====================================================================
+|Header |Type |Description
+|`CamelJmsDestinationName` |`String` |The destination name.
+|=====================================================================
 
-The _InOnly_ producer is the default behavior of the SJMS2 Producer
-Endpoint.
+For example, the following route shows how you can compute a destination
+at run time and use it to override the destination appearing in the JMS
+URL:
 
 [source,java]
-----
-from("direct:start")
-    .to("sjms2:queue:bar");
-----
-
-=== InOut Producer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI. By default it will use a dedicated TemporaryQueue for each
-consumer.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms2:queue:bar?exchangePattern=InOut");
-----
-
-You can specify a `replyTo` though which can provide a better
-monitor point.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms2:queue:bar?replyTo=my.reply.to.queue");
-----
+--------------------------------
+from("file://inbox")
+  .to("bean:computeDestination")
+  .to("sjms2:queue:dummy");
+--------------------------------
 
-== Consumer Usage
+The queue name, `dummy`, is just a placeholder. It must be provided as
+part of the JMS endpoint URL, but it will be ignored in this example.
 
-=== Durable Shared Subscription
-
-To create a durable subscription that can be shared between one or more consumers.
-Use a JMS 2.0 compliant connection factory and specify a common subscriptionId. Then set the subscription properties durable and shared to true.
-
-[source,java]
-----
-from("sjms2:topic:foo?consumerCount=3&subscriptionId=bar&durable=true&shared=true")
-    .to("mock:result");
-
-from("sjms2:topic:foo?consumerCount=2&subscriptionId=bar&durable=true&shared=true")
-    .to("mock:result");
-----
-
-=== InOnly Consumer - (Default)
-
-The _InOnly_ xonsumer is the default Exchange behavior of the SJMS2
-Consumer Endpoint.
+In the `computeDestination` bean, specify the real destination by
+setting the `CamelJmsDestinationName` header as follows:
 
 [source,java]
-----
-from("sjms2:queue:bar")
-    .to("mock:result");
-----
-
-=== InOut Consumer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI.
-
-[source,java]
-----
-from("sjms2:queue:in.out.test?exchangePattern=InOut")
-    .transform(constant("Bye Camel"));
-----
-
-== Advanced Usage Notes
-
-=== Plugable Connection Resource Management [[SJMS2-connectionresource]]
-
-SJMS2 provides JMS
-http://docs.oracle.com/javaee/5/api/javax/jms/Connection.html[`Connection`]
-resource management through built-in connection pooling. This eliminates
-the need to depend on third party API pooling logic. However there may
-be times that you are required to use an external Connection resource
-manager such as those provided by J2EE or OSGi containers. For this SJMS2
-provides an interface that can be used to override the internal SJMS2
-Connection pooling capabilities. This is accomplished through the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionResource.java[`ConnectionResource`]
-interface.
-
-The
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionResource.java[`ConnectionResource`]
-provides methods for borrowing and returning Connections as needed is
-the contract used to provide
-http://docs.oracle.com/javaee/5/api/javax/jms/Connection.html[`Connection`]
-pools to the SJMS2 component. A user should use when it is necessary to
-integrate SJMS2 with an external connection pooling manager.
-
-It is recommended though that for standard
-http://docs.oracle.com/javaee/5/api/javax/jms/ConnectionFactory.html[`ConnectionFactory`]
-providers you use the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/it/ConnectionResourceIT.java[`ConnectionFactoryResource`]
-implementation that is provided with SJMS2 as-is or extend as it is
-optimized for this component.
-
-Below is an example of using the plugable ConnectionResource with the
-ActiveMQ `PooledConnectionFactory`:
-
-[source,java]
-----
-public class AMQConnectionResource implements ConnectionResource {
-    private PooledConnectionFactory pcf;
-
-    public AMQConnectionResource(String connectString, int maxConnections) {
-        super();
-        pcf = new PooledConnectionFactory(connectString);
-        pcf.setMaxConnections(maxConnections);
-        pcf.start();
-    }
-
-    public void stop() {
-        pcf.stop();
-    }
-
-    @Override
-    public Connection borrowConnection() throws Exception {
-        Connection answer = pcf.createConnection();
-        answer.start();
-        return answer;
-    }
-
-    @Override
-    public Connection borrowConnection(long timeout) throws Exception {
-        // SNIPPED...
-    }
-
-    @Override
-    public void returnConnection(Connection connection) throws Exception {
-        // Do nothing since there isn't a way to return a Connection
-        // to the instance of PooledConnectionFactory
-        log.info("Connection returned");
-    }
+-------------------------------------------------------------------------
+public void setJmsHeader(Exchange exchange) {
+   String id = ....
+   exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id");
 }
-----
-
-Then pass in the `ConnectionResource` to the `Sjms2Component`:
-
-[source,java]
-----
-CamelContext camelContext = new DefaultCamelContext();
-AMQConnectionResource pool = new AMQConnectionResource("tcp://localhost:33333", 1);
-Sjms2Component component = new Sjms2Component();
-component.setConnectionResource(pool);
-camelContext.addComponent("sjms2", component);
-----
-
-To see the full example of its usage please refer to the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/it/ConnectionResourceIT.java[`ConnectionResourceIT`].
-
-=== Session, Consumer, & Producer Pooling & Caching Management
-
-Coming soon ...
-
-=== Batch Message Support
+-------------------------------------------------------------------------
 
-The Sjms2Producer supports publishing a collection of messages by
-creating an Exchange that encapsulates a `List`. This Sjms2Producer will
-take then iterate through the contents of the List and publish each
-message individually.
+Then Camel will read this header and use it as the destination instead
+of the one configured on the endpoint. So, in this example Camel sends
+the message to `sjms2:queue:order:2`, assuming the `id` value was 2.
 
-If when producing a batch of messages there is the need to set headers
-that are unique to each message you can use the SJMS2
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/BatchMessage.java[`BatchMessage`]
-class. When the Sjms2Producer encounters a `BatchMessage` list it will
-iterate each `BatchMessage` and publish the included payload and headers.
+Keep in mind that the JMS producer removes both `CamelJmsDestinationName`
+headers from the exchange and do not propagate  them to the created JMS
+message in order to avoid the accidental loops
+in the routes (in scenarios when the message will be forwarded to the
+another JMS endpoint).
 
-Below is an example of using the BatchMessage class. First we create a
-list of `BatchMessage`:
+== Using toD
 
-[source,java]
-----
-List<BatchMessage<String>> messages = new ArrayList<BatchMessage<String>>();
-for (int i = 1; i <= messageCount; i++) {
-    String body = "Hello World " + i;
-    BatchMessage<String> message = new BatchMessage<String>(body, null);
-    messages.add(message);
-}
-----
+If you need to send messages to a lot of different JMS destinations, it
+makes sense to reuse a SJMS2 endpoint and specify the dynamic destinations
+with simple language using xref:{eip-vc}:eips:toD-eip.adoc[toD].
 
-Then publish the list:
+For example suppose you need to send messages to queues with order types,
+then using toD could for example be done as follows:
 
 [source,java]
-----
-template.sendBody("sjms2:queue:batch.queue", messages);
-----
+--------------------------------
+from("direct:order")
+  .toD("sjms2:order-${header.orderType}");
+--------------------------------
 
-=== Customizable Transaction Commit Strategies (Local JMS Transactions only)
-
-SJMS2 provides a developer the means to create a custom and plugable
-transaction strategy through the use of the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/TransactionCommitStrategy.java[`TransactionCommitStrategy`]
-interface. This allows a user to define a unique set of circumstances
-that the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/SessionTransactionSynchronization.java[`SessionTransactionSynchronization`]
-will use to determine when to commit the Session. An example of its use
-is the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/BatchTransactionCommitStrategy.java[`BatchTransactionCommitStrategy`]
-which is detailed further in the next section.
-
-=== Transacted Batch Consumers & Producers
-
-The SJMS2 component has been designed to support the batching of local JMS
-transactions on both the Producer and Consumer endpoints. How they are
-handled on each is very different though.
-
-The SJMS2 consumer endpoint is a straightforward implementation that will
-process X messages before committing them with the associated Session.
-To enable batched transaction on the consumer first enable transactions
-by setting the `transacted` parameter to true and then adding the
-`transactionBatchCount` and setting it to any value that is greater than
-0. For example the following configuration will commit the Session every
-10 messages:
-
-[source]
-----
-sjms2:queue:transacted.batch.consumer?transacted=true&transactionBatchCount=10
-----
-
-If an exception occurs during the processing of a batch on the consumer
-endpoint, the Session rollback is invoked causing the messages to be
-redelivered to the next available consumer. The counter is also reset to
-0 for the `BatchTransactionCommitStrategy` for the associated Session as
-well. It is the responsibility of the user to ensure they put hooks in
-their processors of batch messages to watch for messages with the
-JMSRedelivered header set to true. This is the indicator that messages
-were rolled back at some point and that a verification of a successful
-processing should occur.
-
-A transacted batch consumer also carries with it an instance of an
-internal timer that waits a default amount of time (5000ms) between
-messages before committing the open transactions on the Session. The
-default value of 5000ms (minimum of 1000ms) should be adequate for most
-use-cases but if further tuning is necessary simply set the
-`transactionBatchTimeout` parameter.
-
-[source]
-----
-sjms2:queue:transacted.batch.consumer?transacted=true&transactionBatchCount=10&transactionBatchTimeout=2000
-----
+== Additional Notes
 
-The minimal value that will be accepted is 1000ms as the amount of
-context switching may cause unnecessary performance impacts without
-gaining benefit.
+=== Local transactions
 
-The producer endpoint is handled much differently though. With the
-producer after each message is delivered to its destination the Exchange
-is closed and there is no longer a reference to that message. To make a
-available all the messages available for redelivery you simply enable
-transactions on a Producer Endpoint that is publishing BatchMessages.
-The transaction will commit at the conclusion of the exchange which
-includes all messages in the batch list. Nothing additional need be
-configured. For example:
+When using `transacted=true` then JMS Transacted Acknowledge Mode are in use.
+The SJMS2 component supports this from both the consumer and producers. If a consumer
+is transacted, then the active JMS Session will commit or rollback at the end of processing the message.
 
-[source,java]
-----
-List<BatchMessage<String>> messages = new ArrayList<BatchMessage<String>>();
-for (int i = 1; i <= messageCount; i++) {
-    String body = "Hello World " + i;
-    BatchMessage<String> message = new BatchMessage<String>(body, null);
-    messages.add(message);
-}
-----
+SJMS2 producers that are `transacted=true` will also defer until the end of processing the message
+before the the active JMS Session will commit or rollback.
 
-Now publish the List with transactions enabled:
+You can combine consumer and producer, such as:
 
 [source,java]
 ----
-template.sendBody("sjms2:queue:batch.queue?transacted=true", messages);
+from("sjms2:cheese?transacted=true")
+  .to("bean:foo")
+  .to("sjms2:foo?transacted=true")
+  .to("bean:bar");
 ----
 
-== Additional Notes
+Here the consumer and producer are both transacted, which means that only at the end of processing the message,
+then both the consumer and the producer will commit (or rollback in case of an exception during routing).
 
 === Message Header Format
 
@@ -530,12 +299,8 @@ messages:
 ** is replaced by _DOT_ and the reverse replacement when Camel consumes
 the message.
 ** is replaced by _HYPHEN_ and the reverse replacement when Camel
-consumes the message. +
-See also the option `jmsKeyFormatStrategy`, which allows use of your own
-custom strategy for formatting keys.
-
-For the `exchange.in.header`, the following rules apply for the header
-values:
+consumes the message.See also the option `jmsKeyFormatStrategy`,
+which allows use of your own custom strategy for formatting keys.
 
 === Message Content
 
@@ -550,40 +315,19 @@ dropped.
 === Clustering
 
 When using _InOut_ with SJMS2 in a clustered environment you must either
-use TemporaryQueue destinations or use a unique named reply to
+use TemporaryQueue destinations or use a unique reply to
 destination per InOut producer endpoint. Message correlation is handled
-by the endpoint, not with message selectors at the broker. The InOut
-Producer Endpoint uses Java Concurrency Exchangers cached by the Message
-`JMSCorrelationID`. This provides a nice performance increase while
-reducing the overhead on the broker since all the messages are consumed
-from the destination in the order they are produced by the interested
-consumer.
+by the producer, not with message selectors at the broker.
+
+[NOTE]
+====
+You should only use queues as reply-to destination types, topics is not recommended or fully supported.
+====
 
 Currently the only correlation strategy is to use the `JMSCorrelationId`.
 The _InOut_ Consumer uses this strategy as well ensuring that all
 responses messages to the included `JMSReplyTo` destination also have the
 `JMSCorrelationId` copied from the request as well.
 
-== Transaction Support [[SJMS2-transactions]]
-
-SJMS2 currently only supports the use of internal JMS Transactions. There
-is no support for the Camel Transaction Processor or the Java
-Transaction API (JTA).
-
-=== Does Springless Mean I Can't Use Spring?
-
-Not at all. Below is an example of the SJMS2 component using the XML DSL:
-
-[source,xml]
-----
-<route>
-    <from uri="direct:invoke.named.reply.to.queue" />
-    <to uri="sjms2:queue:named.reply.to.queue?replyTo=my.response.queue" />
-</route>
-----
-
-Springless refers to moving away from the dependency on the Spring JMS
-API. A new JMS client API is being developed from the ground up to power
-SJMS2.
 
 include::camel-spring-boot::page$sjms2-starter.adoc[]
diff --git a/components/camel-sjms/pom.xml b/components/camel-sjms/pom.xml
index d121fcf..e0eafc3 100644
--- a/components/camel-sjms/pom.xml
+++ b/components/camel-sjms/pom.xml
@@ -32,11 +32,6 @@
     <description>A pure Java JMS Camel Component</description>
 
     <properties>
-        <camel.osgi.private.pkg>
-            org.apache.camel.component.sjms.consumer,
-            org.apache.camel.component.sjms.producer,
-            org.apache.camel.component.sjms.tx
-        </camel.osgi.private.pkg>
         <camel.osgi.import>
             javax.jms;version="[1.1,3)",
             *
@@ -44,17 +39,12 @@
     </properties>
 
     <dependencies>
+
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-support</artifactId>
         </dependency>
 
-        <!-- TODO: remove our own pooling -->
-        <dependency>
-            <groupId>commons-pool</groupId>
-            <artifactId>commons-pool</artifactId>
-        </dependency>
-
         <dependency>
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-jms_1.1_spec</artifactId>
diff --git a/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsComponentConfigurer.java b/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsComponentConfigurer.java
index 505241f..566e482 100644
--- a/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsComponentConfigurer.java
+++ b/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsComponentConfigurer.java
@@ -25,22 +25,10 @@ public class SjmsComponentConfigurer extends PropertyConfigurerSupport implement
         case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
-        case "connectionclientid":
-        case "connectionClientId": target.setConnectionClientId(property(camelContext, java.lang.String.class, value)); return true;
         case "connectioncount":
         case "connectionCount": target.setConnectionCount(property(camelContext, java.lang.Integer.class, value)); return true;
         case "connectionfactory":
         case "connectionFactory": target.setConnectionFactory(property(camelContext, javax.jms.ConnectionFactory.class, value)); return true;
-        case "connectionmaxwait":
-        case "connectionMaxWait": target.setConnectionMaxWait(property(camelContext, long.class, value)); return true;
-        case "connectionpassword":
-        case "connectionPassword": target.setConnectionPassword(property(camelContext, java.lang.String.class, value)); return true;
-        case "connectionresource":
-        case "connectionResource": target.setConnectionResource(property(camelContext, org.apache.camel.component.sjms.jms.ConnectionResource.class, value)); return true;
-        case "connectiontestonborrow":
-        case "connectionTestOnBorrow": target.setConnectionTestOnBorrow(property(camelContext, boolean.class, value)); return true;
-        case "connectionusername":
-        case "connectionUsername": target.setConnectionUsername(property(camelContext, java.lang.String.class, value)); return true;
         case "destinationcreationstrategy":
         case "destinationCreationStrategy": target.setDestinationCreationStrategy(property(camelContext, org.apache.camel.component.sjms.jms.DestinationCreationStrategy.class, value)); return true;
         case "headerfilterstrategy":
@@ -51,10 +39,14 @@ public class SjmsComponentConfigurer extends PropertyConfigurerSupport implement
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
         case "messagecreatedstrategy":
         case "messageCreatedStrategy": target.setMessageCreatedStrategy(property(camelContext, org.apache.camel.component.sjms.jms.MessageCreatedStrategy.class, value)); return true;
+        case "password": target.setPassword(property(camelContext, java.lang.String.class, value)); return true;
         case "recoveryinterval":
         case "recoveryInterval": target.setRecoveryInterval(property(camelContext, java.time.Duration.class, value).toMillis()); return true;
-        case "transactioncommitstrategy":
-        case "transactionCommitStrategy": target.setTransactionCommitStrategy(property(camelContext, org.apache.camel.component.sjms.TransactionCommitStrategy.class, value)); return true;
+        case "replytoontimeoutmaxconcurrentconsumers":
+        case "replyToOnTimeoutMaxConcurrentConsumers": target.setReplyToOnTimeoutMaxConcurrentConsumers(property(camelContext, int.class, value)); return true;
+        case "requesttimeoutcheckerinterval":
+        case "requestTimeoutCheckerInterval": target.setRequestTimeoutCheckerInterval(property(camelContext, java.time.Duration.class, value).toMillis()); return true;
+        case "username": target.setUsername(property(camelContext, java.lang.String.class, value)); return true;
         default: return false;
         }
     }
@@ -71,22 +63,10 @@ public class SjmsComponentConfigurer extends PropertyConfigurerSupport implement
         case "autowiredEnabled": return boolean.class;
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return boolean.class;
-        case "connectionclientid":
-        case "connectionClientId": return java.lang.String.class;
         case "connectioncount":
         case "connectionCount": return java.lang.Integer.class;
         case "connectionfactory":
         case "connectionFactory": return javax.jms.ConnectionFactory.class;
-        case "connectionmaxwait":
-        case "connectionMaxWait": return long.class;
-        case "connectionpassword":
-        case "connectionPassword": return java.lang.String.class;
-        case "connectionresource":
-        case "connectionResource": return org.apache.camel.component.sjms.jms.ConnectionResource.class;
-        case "connectiontestonborrow":
-        case "connectionTestOnBorrow": return boolean.class;
-        case "connectionusername":
-        case "connectionUsername": return java.lang.String.class;
         case "destinationcreationstrategy":
         case "destinationCreationStrategy": return org.apache.camel.component.sjms.jms.DestinationCreationStrategy.class;
         case "headerfilterstrategy":
@@ -97,10 +77,14 @@ public class SjmsComponentConfigurer extends PropertyConfigurerSupport implement
         case "lazyStartProducer": return boolean.class;
         case "messagecreatedstrategy":
         case "messageCreatedStrategy": return org.apache.camel.component.sjms.jms.MessageCreatedStrategy.class;
+        case "password": return java.lang.String.class;
         case "recoveryinterval":
         case "recoveryInterval": return long.class;
-        case "transactioncommitstrategy":
-        case "transactionCommitStrategy": return org.apache.camel.component.sjms.TransactionCommitStrategy.class;
+        case "replytoontimeoutmaxconcurrentconsumers":
+        case "replyToOnTimeoutMaxConcurrentConsumers": return int.class;
+        case "requesttimeoutcheckerinterval":
+        case "requestTimeoutCheckerInterval": return long.class;
+        case "username": return java.lang.String.class;
         default: return null;
         }
     }
@@ -113,22 +97,10 @@ public class SjmsComponentConfigurer extends PropertyConfigurerSupport implement
         case "autowiredEnabled": return target.isAutowiredEnabled();
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return target.isBridgeErrorHandler();
-        case "connectionclientid":
-        case "connectionClientId": return target.getConnectionClientId();
         case "connectioncount":
         case "connectionCount": return target.getConnectionCount();
         case "connectionfactory":
         case "connectionFactory": return target.getConnectionFactory();
-        case "connectionmaxwait":
-        case "connectionMaxWait": return target.getConnectionMaxWait();
-        case "connectionpassword":
-        case "connectionPassword": return target.getConnectionPassword();
-        case "connectionresource":
-        case "connectionResource": return target.getConnectionResource();
-        case "connectiontestonborrow":
-        case "connectionTestOnBorrow": return target.isConnectionTestOnBorrow();
-        case "connectionusername":
-        case "connectionUsername": return target.getConnectionUsername();
         case "destinationcreationstrategy":
         case "destinationCreationStrategy": return target.getDestinationCreationStrategy();
         case "headerfilterstrategy":
@@ -139,10 +111,14 @@ public class SjmsComponentConfigurer extends PropertyConfigurerSupport implement
         case "lazyStartProducer": return target.isLazyStartProducer();
         case "messagecreatedstrategy":
         case "messageCreatedStrategy": return target.getMessageCreatedStrategy();
+        case "password": return target.getPassword();
         case "recoveryinterval":
         case "recoveryInterval": return target.getRecoveryInterval();
-        case "transactioncommitstrategy":
-        case "transactionCommitStrategy": return target.getTransactionCommitStrategy();
+        case "replytoontimeoutmaxconcurrentconsumers":
+        case "replyToOnTimeoutMaxConcurrentConsumers": return target.getReplyToOnTimeoutMaxConcurrentConsumers();
+        case "requesttimeoutcheckerinterval":
+        case "requestTimeoutCheckerInterval": return target.getRequestTimeoutCheckerInterval();
+        case "username": return target.getUsername();
         default: return null;
         }
     }
diff --git a/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointConfigurer.java b/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointConfigurer.java
index 7fd6f8c..9487e58 100644
--- a/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointConfigurer.java
+++ b/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointConfigurer.java
@@ -35,14 +35,12 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "autoStartup": target.setAutoStartup(property(camelContext, boolean.class, value)); return true;
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
+        case "concurrentconsumers":
+        case "concurrentConsumers": target.setConcurrentConsumers(property(camelContext, int.class, value)); return true;
         case "connectioncount":
         case "connectionCount": target.setConnectionCount(property(camelContext, java.lang.Integer.class, value)); return true;
         case "connectionfactory":
         case "connectionFactory": target.setConnectionFactory(property(camelContext, javax.jms.ConnectionFactory.class, value)); return true;
-        case "connectionresource":
-        case "connectionResource": target.setConnectionResource(property(camelContext, org.apache.camel.component.sjms.jms.ConnectionResource.class, value)); return true;
-        case "consumercount":
-        case "consumerCount": target.setConsumerCount(property(camelContext, int.class, value)); return true;
         case "deliverymode":
         case "deliveryMode": target.setDeliveryMode(property(camelContext, java.lang.Integer.class, value)); return true;
         case "deliverypersistent":
@@ -75,6 +73,8 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "headerFilterStrategy": target.setHeaderFilterStrategy(property(camelContext, org.apache.camel.spi.HeaderFilterStrategy.class, value)); return true;
         case "includealljmsxproperties":
         case "includeAllJMSXProperties": target.setIncludeAllJMSXProperties(property(camelContext, boolean.class, value)); return true;
+        case "includesentjmsmessageid":
+        case "includeSentJMSMessageID": target.setIncludeSentJMSMessageID(property(camelContext, boolean.class, value)); return true;
         case "jmskeyformatstrategy":
         case "jmsKeyFormatStrategy": target.setJmsKeyFormatStrategy(property(camelContext, org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy.class, value)); return true;
         case "lazystartproducer":
@@ -92,12 +92,16 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "recoveryInterval": target.setRecoveryInterval(property(camelContext, java.time.Duration.class, value).toMillis()); return true;
         case "replyto":
         case "replyTo": target.setReplyTo(property(camelContext, java.lang.String.class, value)); return true;
+        case "replytoconcurrentconsumers":
+        case "replyToConcurrentConsumers": target.setReplyToConcurrentConsumers(property(camelContext, int.class, value)); return true;
         case "replytodeliverypersistent":
         case "replyToDeliveryPersistent": target.setReplyToDeliveryPersistent(property(camelContext, boolean.class, value)); return true;
         case "replytooverride":
         case "replyToOverride": target.setReplyToOverride(property(camelContext, java.lang.String.class, value)); return true;
         case "replytosamedestinationallowed":
         case "replyToSameDestinationAllowed": target.setReplyToSameDestinationAllowed(property(camelContext, boolean.class, value)); return true;
+        case "replytotype":
+        case "replyToType": target.setReplyToType(property(camelContext, org.apache.camel.component.sjms.ReplyToType.class, value)); return true;
         case "requesttimeout":
         case "requestTimeout": target.setRequestTimeout(property(camelContext, java.time.Duration.class, value).toMillis()); return true;
         case "sharedjmssession":
@@ -108,8 +112,6 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "timetolive":
         case "timeToLive": target.setTimeToLive(property(camelContext, long.class, value)); return true;
         case "transacted": target.setTransacted(property(camelContext, boolean.class, value)); return true;
-        case "transactioncommitstrategy":
-        case "transactionCommitStrategy": target.setTransactionCommitStrategy(property(camelContext, org.apache.camel.component.sjms.TransactionCommitStrategy.class, value)); return true;
         case "transferexception":
         case "transferException": target.setTransferException(property(camelContext, boolean.class, value)); return true;
         default: return false;
@@ -133,14 +135,12 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "autoStartup": return boolean.class;
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return boolean.class;
+        case "concurrentconsumers":
+        case "concurrentConsumers": return int.class;
         case "connectioncount":
         case "connectionCount": return java.lang.Integer.class;
         case "connectionfactory":
         case "connectionFactory": return javax.jms.ConnectionFactory.class;
-        case "connectionresource":
-        case "connectionResource": return org.apache.camel.component.sjms.jms.ConnectionResource.class;
-        case "consumercount":
-        case "consumerCount": return int.class;
         case "deliverymode":
         case "deliveryMode": return java.lang.Integer.class;
         case "deliverypersistent":
@@ -173,6 +173,8 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "headerFilterStrategy": return org.apache.camel.spi.HeaderFilterStrategy.class;
         case "includealljmsxproperties":
         case "includeAllJMSXProperties": return boolean.class;
+        case "includesentjmsmessageid":
+        case "includeSentJMSMessageID": return boolean.class;
         case "jmskeyformatstrategy":
         case "jmsKeyFormatStrategy": return org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy.class;
         case "lazystartproducer":
@@ -190,12 +192,16 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "recoveryInterval": return long.class;
         case "replyto":
         case "replyTo": return java.lang.String.class;
+        case "replytoconcurrentconsumers":
+        case "replyToConcurrentConsumers": return int.class;
         case "replytodeliverypersistent":
         case "replyToDeliveryPersistent": return boolean.class;
         case "replytooverride":
         case "replyToOverride": return java.lang.String.class;
         case "replytosamedestinationallowed":
         case "replyToSameDestinationAllowed": return boolean.class;
+        case "replytotype":
+        case "replyToType": return org.apache.camel.component.sjms.ReplyToType.class;
         case "requesttimeout":
         case "requestTimeout": return long.class;
         case "sharedjmssession":
@@ -206,8 +212,6 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "timetolive":
         case "timeToLive": return long.class;
         case "transacted": return boolean.class;
-        case "transactioncommitstrategy":
-        case "transactionCommitStrategy": return org.apache.camel.component.sjms.TransactionCommitStrategy.class;
         case "transferexception":
         case "transferException": return boolean.class;
         default: return null;
@@ -232,14 +236,12 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "autoStartup": return target.isAutoStartup();
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+        case "concurrentconsumers":
+        case "concurrentConsumers": return target.getConcurrentConsumers();
         case "connectioncount":
         case "connectionCount": return target.getConnectionCount();
         case "connectionfactory":
         case "connectionFactory": return target.getConnectionFactory();
-        case "connectionresource":
-        case "connectionResource": return target.getConnectionResource();
-        case "consumercount":
-        case "consumerCount": return target.getConsumerCount();
         case "deliverymode":
         case "deliveryMode": return target.getDeliveryMode();
         case "deliverypersistent":
@@ -272,6 +274,8 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "headerFilterStrategy": return target.getHeaderFilterStrategy();
         case "includealljmsxproperties":
         case "includeAllJMSXProperties": return target.isIncludeAllJMSXProperties();
+        case "includesentjmsmessageid":
+        case "includeSentJMSMessageID": return target.isIncludeSentJMSMessageID();
         case "jmskeyformatstrategy":
         case "jmsKeyFormatStrategy": return target.getJmsKeyFormatStrategy();
         case "lazystartproducer":
@@ -289,12 +293,16 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "recoveryInterval": return target.getRecoveryInterval();
         case "replyto":
         case "replyTo": return target.getReplyTo();
+        case "replytoconcurrentconsumers":
+        case "replyToConcurrentConsumers": return target.getReplyToConcurrentConsumers();
         case "replytodeliverypersistent":
         case "replyToDeliveryPersistent": return target.isReplyToDeliveryPersistent();
         case "replytooverride":
         case "replyToOverride": return target.getReplyToOverride();
         case "replytosamedestinationallowed":
         case "replyToSameDestinationAllowed": return target.isReplyToSameDestinationAllowed();
+        case "replytotype":
+        case "replyToType": return target.getReplyToType();
         case "requesttimeout":
         case "requestTimeout": return target.getRequestTimeout();
         case "sharedjmssession":
@@ -305,8 +313,6 @@ public class SjmsEndpointConfigurer extends PropertyConfigurerSupport implements
         case "timetolive":
         case "timeToLive": return target.getTimeToLive();
         case "transacted": return target.isTransacted();
-        case "transactioncommitstrategy":
-        case "transactionCommitStrategy": return target.getTransactionCommitStrategy();
         case "transferexception":
         case "transferException": return target.isTransferException();
         default: return null;
diff --git a/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointUriFactory.java b/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointUriFactory.java
index d84eb11..717a7ff 100644
--- a/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointUriFactory.java
+++ b/components/camel-sjms/src/generated/java/org/apache/camel/component/sjms/SjmsEndpointUriFactory.java
@@ -20,7 +20,8 @@ public class SjmsEndpointUriFactory extends org.apache.camel.support.component.E
     private static final Set<String> PROPERTY_NAMES;
     private static final Set<String> SECRET_PROPERTY_NAMES;
     static {
-        Set<String> props = new HashSet<>(49);
+        Set<String> props = new HashSet<>(50);
+        props.add("includeSentJMSMessageID");
         props.add("asyncConsumer");
         props.add("mapJmsMessage");
         props.add("synchronous");
@@ -35,21 +36,21 @@ public class SjmsEndpointUriFactory extends org.apache.camel.support.component.E
         props.add("destinationType");
         props.add("asyncStartListener");
         props.add("eagerPoisonBody");
+        props.add("replyToConcurrentConsumers");
         props.add("destinationCreationStrategy");
         props.add("disableTimeToLive");
         props.add("messageSelector");
         props.add("deliveryPersistent");
         props.add("priority");
+        props.add("concurrentConsumers");
         props.add("acknowledgementMode");
         props.add("lazyStartProducer");
-        props.add("transactionCommitStrategy");
         props.add("replyTo");
         props.add("replyToOverride");
         props.add("errorHandlerLoggingLevel");
         props.add("durableSubscriptionId");
         props.add("exceptionHandler");
         props.add("connectionCount");
-        props.add("connectionResource");
         props.add("explicitQosEnabled");
         props.add("transacted");
         props.add("autoStartup");
@@ -62,10 +63,10 @@ public class SjmsEndpointUriFactory extends org.apache.camel.support.component.E
         props.add("allowNullBody");
         props.add("replyToDeliveryPersistent");
         props.add("disableReplyTo");
-        props.add("consumerCount");
         props.add("recoveryInterval");
         props.add("exchangePattern");
         props.add("preserveMessageQos");
+        props.add("replyToType");
         props.add("testConnectionOnStartup");
         props.add("connectionFactory");
         props.add("replyToSameDestinationAllowed");
diff --git a/components/camel-sjms/src/generated/resources/org/apache/camel/component/sjms/sjms.json b/components/camel-sjms/src/generated/resources/org/apache/camel/component/sjms/sjms.json
index 040eaa9..9e065f0 100644
--- a/components/camel-sjms/src/generated/resources/org/apache/camel/component/sjms/sjms.json
+++ b/components/camel-sjms/src/generated/resources/org/apache/camel/component/sjms/sjms.json
@@ -27,18 +27,15 @@
     "bridgeErrorHandler": { "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a me [...]
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during star [...]
     "autowiredEnabled": { "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which t [...]
-    "connectionClientId": { "kind": "property", "displayName": "Connection Client Id", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionMaxWait": { "kind": "property", "displayName": "Connection Max Wait", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5000, "description": "The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionResource": { "kind": "property", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details." },
-    "connectionTestOnBorrow": { "kind": "property", "displayName": "Connection Test On Borrow", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used." },
     "destinationCreationStrategy": { "kind": "property", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "jmsKeyFormatStrategy": { "kind": "property", "displayName": "Jms Key Format Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The defau [...]
     "messageCreatedStrategy": { "kind": "property", "displayName": "Message Created Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.MessageCreatedStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message." },
     "recoveryInterval": { "kind": "property", "displayName": "Recovery Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds." },
+    "replyToOnTimeoutMaxConcurrentConsumers": { "kind": "property", "displayName": "Reply To On Timeout Max Concurrent Consumers", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request\/reply over JMS." },
+    "requestTimeoutCheckerInterval": { "kind": "property", "displayName": "Request Timeout Checker Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Configures how often Camel should check for timed out Exchanges when doing request\/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeou [...]
     "headerFilterStrategy": { "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." },
-    "connectionPassword": { "kind": "property", "displayName": "Connection Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionUsername": { "kind": "property", "displayName": "Connection Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "transactionCommitStrategy": { "kind": "property", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch." }
+    "password": { "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." },
+    "username": { "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Username to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." }
   },
   "properties": {
     "destinationType": { "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" },
@@ -50,7 +47,7 @@
     "asyncConsumer": { "kind": "parameter", "displayName": "Async Consumer", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asy [...]
     "autoStartup": { "kind": "parameter", "displayName": "Auto Startup", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether the consumer container should auto-startup." },
     "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a m [...]
-    "consumerCount": { "kind": "parameter", "displayName": "Consumer Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the number of consumer listeners used for this endpoint." },
+    "concurrentConsumers": { "kind": "parameter", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when consuming from JMS (not for request\/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads. When doing r [...]
     "durableSubscriptionId": { "kind": "parameter", "displayName": "Durable Subscription Id", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the durable subscription Id required for durable topics." },
     "replyToDeliveryPersistent": { "kind": "parameter", "displayName": "Reply To Delivery Persistent", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to use persistent delivery by default for replies." },
     "eagerLoadingOfProperties": { "kind": "parameter", "displayName": "Eager Loading Of Properties", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes c [...]
@@ -65,16 +62,18 @@
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during sta [...]
     "preserveMessageQos": { "kind": "parameter", "displayName": "Preserve Message Qos", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDelive [...]
     "priority": { "kind": "parameter", "displayName": "Priority", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "enum": [ "1", "2", "3", "4", "5", "6", "7", "8", "9" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": 4, "description": "Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in orde [...]
+    "replyToConcurrentConsumers": { "kind": "parameter", "displayName": "Reply To Concurrent Consumers", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when doing request\/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads." },
     "replyToOverride": { "kind": "parameter", "displayName": "Reply To Override", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination." },
+    "replyToType": { "kind": "parameter", "displayName": "Reply To Type", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.ReplyToType", "enum": [ "Temporary", "Exclusive" ], "deprecated": false, "autowired": false, "secret": false, "description": "Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request\/reply over JMS. Possible values are: Temporary, Shared, or Exclusi [...]
     "requestTimeout": { "kind": "parameter", "displayName": "Request Timeout", "group": "producer", "label": "producer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeou [...]
     "timeToLive": { "kind": "parameter", "displayName": "Time To Live", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": -1, "description": "When sending messages, specifies the time-to-live of the message (in milliseconds)." },
     "allowNullBody": { "kind": "parameter", "displayName": "Allow Null Body", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown." },
     "disableTimeToLive": { "kind": "parameter", "displayName": "Disable Time To Live", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Use this option to force disabling time to live. For example when you do request\/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message  [...]
+    "includeSentJMSMessageID": { "kind": "parameter", "displayName": "Include Sent JMSMessage ID", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was  [...]
     "asyncStartListener": { "kind": "parameter", "displayName": "Async Start Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and\/o [...]
     "asyncStopListener": { "kind": "parameter", "displayName": "Async Stop Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to stop the consumer message listener asynchronously, when stopping a route." },
     "connectionCount": { "kind": "parameter", "displayName": "Connection Count", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": true, "autowired": false, "secret": false, "description": "The maximum number of connections available to this endpoint" },
     "connectionFactory": { "kind": "parameter", "displayName": "Connection Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ConnectionFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any" },
-    "connectionResource": { "kind": "parameter", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any" },
     "destinationCreationStrategy": { "kind": "parameter", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "exceptionListener": { "kind": "parameter", "displayName": "Exception Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ExceptionListener", "deprecated": false, "autowired": false, "secret": false, "description": "Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions." },
     "headerFilterStrategy": { "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter header to and from Camel message." },
@@ -88,7 +87,6 @@
     "errorHandlerLoggingLevel": { "kind": "parameter", "displayName": "Error Handler Logging Level", "group": "logging", "label": "consumer,logging", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "WARN", "description": "Allows to configure the default errorHandler logging level for logging uncaught exceptions." },
     "errorHandlerLogStackTrace": { "kind": "parameter", "displayName": "Error Handler Log Stack Trace", "group": "logging", "label": "consumer,logging", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Allows to control whether stacktraces should be logged or not, by the default errorHandler." },
     "transacted": { "kind": "parameter", "displayName": "Transacted", "group": "transaction", "label": "transaction", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to use transacted mode" },
-    "transactionCommitStrategy": { "kind": "parameter", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the commit strategy." },
     "sharedJMSSession": { "kind": "parameter", "displayName": "Shared JMSSession", "group": "transaction (advanced)", "label": "transaction,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS provi [...]
   }
 }
diff --git a/components/camel-sjms/src/main/docs/sjms-component.adoc b/components/camel-sjms/src/main/docs/sjms-component.adoc
index cdabfaa..eaf6c55 100644
--- a/components/camel-sjms/src/main/docs/sjms-component.adoc
+++ b/components/camel-sjms/src/main/docs/sjms-component.adoc
@@ -12,33 +12,22 @@ include::{cq-version}@camel-quarkus:ROOT:partial$reference/components/sjms.adoc[
 
 *{component-header}*
 
-The Simple JMS Component, or SJMS, is a JMS client for use with Camel
-that uses well known best practices when it comes to JMS client creation
-and configuration. SJMS contains a brand new JMS client API written
-explicitly for Camel eliminating third party messaging implementations
-keeping it light and resilient. The following features is included:
+The Simple JMS Component is a JMS component that only uses JMS APIs
+and no 3rd-party framework such as Spring JMS.
 
-// TODO: Update this after refactor
+The component was reworked from Camel 3.8 onwards
+to be similar to the existing Camel JMS component that is based on Spring JMS.
 
-* Standard Queue and Topic Support (Durable & Non-Durable)
-* InOnly & InOut MEP Support
-* Asynchronous Producer and Consumer Processing
-* Internal JMS Transaction Support
+The reason is to offer many of the same features and functionality from the JMS component,
+but for users that requires lightweight without having to include the Spring Framework.
 
-Additional key features include:
+There are some advanced features in the Spring JMS component that has been omitted, such as
+shared queues for request/reply. Spring JMS offers fine grained tunings for concurrency settings,
+which can be tweaked for dynamic scaling up and down depending on load. This is a special feature in Spring JMS
+that would require substantial code to implement in SJMS.
 
-* Plugable Connection Resource Management
-* Session, Consumer, & Producer Pooling & Caching Management
-* Support for Customizable Transaction Commit Strategies (Local JMS
-Transactions only)
-
-[NOTE]
-====
-*Why the S in SJMS*
-
-S stands for Simple and Standard and Springless. Also camel-jms was
-already taken.
-====
+The SJMS component does not support for Spring or JTA Transaction, however support for internal local transactions
+is supported using JMS or Transaction or Client Acknowledge Mode. See more further below.
 
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
@@ -90,7 +79,7 @@ You append query options to the URI using the following format,
 == Component Options and Configurations
 
 // component options: START
-The Simple JMS component supports 17 options, which are listed below.
+The Simple JMS component supports 14 options, which are listed below.
 
 
 
@@ -102,18 +91,15 @@ The Simple JMS component supports 17 options, which are listed below.
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. | true | boolean
-| *connectionClientId* (advanced) | The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionMaxWait* (advanced) | The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. | 5000 | long
-| *connectionResource* (advanced) | A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details. |  | ConnectionResource
-| *connectionTestOnBorrow* (advanced) | When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used. | true | boolean
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *jmsKeyFormatStrategy* (advanced) | Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The default strategy will safely marshal dots and hyphens (. and -). Can be used for JMS brokers which do not care whether JMS header keys contain illegal characters. You can provide your own implementation of the org.apache.camel.component.jms.JmsKeyFormatStrategy and refer to it using  [...]
 | *messageCreatedStrategy* (advanced) | To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message. |  | MessageCreatedStrategy
 | *recoveryInterval* (advanced) | Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds. | 5000 | long
+| *replyToOnTimeoutMaxConcurrent{zwsp}Consumers* (advanced) | Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request/reply over JMS. | 1 | int
+| *requestTimeoutCheckerInterval* (advanced) | Configures how often Camel should check for timed out Exchanges when doing request/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeout occurs, then you can lower this interval, to check more frequently. The timeout is determined by the option requestTimeout. | 1000 | long
 | *headerFilterStrategy* (filter) | To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
-| *connectionPassword* (security) | The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionUsername* (security) | The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *transactionCommitStrategy* (transaction) | To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch. |  | TransactionCommitStrategy
+| *password* (security) | Password to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
+| *username* (security) | Username to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
 |===
 // component options: END
 
@@ -138,7 +124,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (47 parameters):
+=== Query Parameters (48 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -151,7 +137,7 @@ with the following path and query parameters:
 | *asyncConsumer* (consumer) | Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asynchronous Routing Engine). This means that messages may be processed not 100% strictly in order. If disabled (as default) then the Exchange is fully processed before the JmsConsumer will pickup the next message from the JMS queue. Note if transac [...]
 | *autoStartup* (consumer) | Specifies whether the consumer container should auto-startup. | true | boolean
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
-| *consumerCount* (consumer) | Sets the number of consumer listeners used for this endpoint. | 1 | int
+| *concurrentConsumers* (consumer) | Specifies the default number of concurrent consumers when consuming from JMS (not for request/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. When doing request/reply over JMS then the option replyToConcurrentConsumers is used to control number of concurrent consumers on the reply message listener. | 1 | int
 | *durableSubscriptionId* (consumer) | Sets the durable subscription Id required for durable topics. |  | String
 | *replyToDeliveryPersistent* (consumer) | Specifies whether to use persistent delivery by default for replies. | true | boolean
 | *eagerLoadingOfProperties* (consumer) | Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes can catch early any issues with the underlying JMS provider and the use of JMS properties. See also the option eagerPoisonBody. | false | boolean
@@ -166,16 +152,18 @@ with the following path and query parameters:
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *preserveMessageQos* (producer) | Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDeliveryMode, and JMSExpiration. You can provide all or only some of them. If not provided, Camel will fall back to use the values from the endpoint instead. So, when using this option, the headers override the values from the endpoint. The explicitQosEnable [...]
 | *priority* (producer) | Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in order for this option to have any effect. There are 9 enums and the value can be one of: 1, 2, 3, 4, 5, 6, 7, 8, 9 | 4 | int
+| *replyToConcurrentConsumers* (producer) | Specifies the default number of concurrent consumers when doing request/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. | 1 | int
 | *replyToOverride* (producer) | Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination. |  | String
+| *replyToType* (producer) | Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request/reply over JMS. Possible values are: Temporary, Shared, or Exclusive. By default Camel will use temporary queues. However if replyTo has been configured, then Shared is used by default. This option allows you to use exclusive queues instead of shared ones. See Camel JMS documentation for more details, and especially the notes about the implications if running  [...]
 | *requestTimeout* (producer) | The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeout value, and thus have per message individual timeout values. See also the requestTimeoutCheckerInterval option. | 20000 | long
 | *timeToLive* (producer) | When sending messages, specifies the time-to-live of the message (in milliseconds). | -1 | long
 | *allowNullBody* (producer) | Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown. | true | boolean
 | *disableTimeToLive* (producer) | Use this option to force disabling time to live. For example when you do request/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message being sent. The problem is that the sender and receiver systems have to have their clocks synchronized, so they are in sync. This is not always so easy to archive. So you can use disableTimeToLive=true to not set a time to live value on the sent message. Then the message w [...]
+| *includeSentJMSMessageID* (producer) | Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was used by the JMS client when the message was sent to the JMS destination. | false | boolean
 | *asyncStartListener* (advanced) | Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and/or failover. This will cause Camel to block while starting routes. By setting this option to true, you will let routes startup, while the JmsConsumer connects to the JMS broker using a dedicated thread in asynchronous mode. If this option is used, then b [...]
 | *asyncStopListener* (advanced) | Whether to stop the consumer message listener asynchronously, when stopping a route. | false | boolean
 | *connectionCount* (advanced) | *Deprecated* The maximum number of connections available to this endpoint |  | Integer
 | *connectionFactory* (advanced) | Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any |  | ConnectionFactory
-| *connectionResource* (advanced) | Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any |  | ConnectionResource
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *exceptionListener* (advanced) | Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions. |  | ExceptionListener
 | *headerFilterStrategy* (advanced) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
@@ -189,97 +177,13 @@ with the following path and query parameters:
 | *errorHandlerLoggingLevel* (logging) | Allows to configure the default errorHandler logging level for logging uncaught exceptions. There are 6 enums and the value can be one of: TRACE, DEBUG, INFO, WARN, ERROR, OFF | WARN | LoggingLevel
 | *errorHandlerLogStackTrace* (logging) | Allows to control whether stacktraces should be logged or not, by the default errorHandler. | true | boolean
 | *transacted* (transaction) | Specifies whether to use transacted mode | false | boolean
-| *transactionCommitStrategy* (transaction) | Sets the commit strategy. |  | TransactionCommitStrategy
 | *sharedJMSSession* (transaction) | Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS providers, use jms component to leverage XA transaction. | true | boolean
 |===
 // endpoint options: END
 
 
 Below is an example of how to configure the `SjmsComponent` with its
-required `ConnectionFactory` provider. It will create a single connection
-by default and store it using the components internal pooling APIs to
-ensure that it is able to service Session creation requests in a thread
-safe manner.
-
-[source,java]
-----
-SjmsComponent component = new SjmsComponent();
-component.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-getContext().addComponent("sjms", component);
-----
-
-For a SJMS component that is required to support a durable subscription,
-you can override the default `ConnectionFactoryResource` instance and set
-the `clientId` property.
-
-[source,java]
-----
-ConnectionFactoryResource connectionResource = new ConnectionFactoryResource();
-connectionResource.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-connectionResource.setClientId("myclient-id");
-
-SjmsComponent component = new SjmsComponent();
-component.setConnectionResource(connectionResource);
-component.setMaxConnections(1);
-----
-
-== Producer Usage
-
-=== InOnly Producer - (Default)
-
-The _InOnly_ producer is the default behavior of the SJMS Producer
-Endpoint.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms:queue:bar");
-----
-
-=== InOut Producer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI. By default it will use a dedicated TemporaryQueue for each
-consumer.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms:queue:bar?exchangePattern=InOut");
-----
-
-You can specify a `replyTo` though which can provide a better
-monitor point.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms:queue:bar?replyTo=my.reply.to.queue");
-----
-
-== Consumer Usage
-
-=== InOnly Consumer - (Default)
-
-The _InOnly_ consumer is the default Exchange behavior of the SJMS
-Consumer Endpoint.
-
-[source,java]
-----
-from("sjms:queue:bar")
-    .to("mock:result");
-----
-
-=== InOut Consumer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI.
-
-[source,java]
-----
-from("sjms:queue:in.out.test?exchangePattern=InOut")
-    .transform(constant("Bye Camel"));
-----
+required `ConnectionFactory` provider.
 
 
 == Reuse endpoint and send to different destinations computed at runtime
@@ -350,89 +254,29 @@ from("direct:order")
   .toD("sjms:order-${header.orderType}");
 --------------------------------
 
-== Advanced Usage Notes
-
-=== Plugable Connection Resource Management [[SJMS-connectionresource]]
-
-SJMS provides JMS `Connection`
-resource management through built-in connection pooling. This eliminates
-the need to depend on third party API pooling logic. However there may
-be times that you are required to use an external Connection resource
-manager such as those provided by J2EE or OSGi containers. For this SJMS
-provides an interface that can be used to override the internal SJMS
-Connection pooling capabilities. This is accomplished through the `ConnectionResource` interface.
-
-The `ConnectionResource`
-provides methods for borrowing and returning Connections as needed is
-the contract used to provide `Connection`
-pools to the SJMS component. A user should use when it is necessary to
-integrate SJMS with an external connection pooling manager.
+== Additional Notes
 
-It is recommended though that for standard JMS `ConnectionFactory`
-providers you use the `ConnectionFactoryResource`
-implementation that is provided with SJMS as-is or extend as it is
-optimized for this component.
+=== Local transactions
 
-Below is an example of using the plugable ConnectionResource with the
-ActiveMQ `PooledConnectionFactory`:
+When using `transacted=true` then JMS Transacted Acknowledge Mode are in use.
+The SJMS component supports this from both the consumer and producers. If a consumer
+is transacted, then the active JMS Session will commit or rollback at the end of processing the message.
 
-[source,java]
-----
-public class AMQConnectionResource implements ConnectionResource {
-    private PooledConnectionFactory pcf;
-
-    public AMQConnectionResource(String connectString, int maxConnections) {
-        super();
-        pcf = new PooledConnectionFactory(connectString);
-        pcf.setMaxConnections(maxConnections);
-        pcf.start();
-    }
-
-    public void stop() {
-        pcf.stop();
-    }
-
-    @Override
-    public Connection borrowConnection() throws Exception {
-        Connection answer = pcf.createConnection();
-        answer.start();
-        return answer;
-    }
-
-    @Override
-    public Connection borrowConnection(long timeout) throws Exception {
-        // SNIPPED...
-    }
-
-    @Override
-    public void returnConnection(Connection connection) throws Exception {
-        // Do nothing since there isn't a way to return a Connection
-        // to the instance of PooledConnectionFactory
-        log.info("Connection returned");
-    }
-}
-----
+SJMS producers that are `transacted=true` will also defer until the end of processing the message
+before the the active JMS Session will commit or rollback.
 
-Then pass in the `ConnectionResource` to the `SjmsComponent`:
+You can combine consumer and producer, such as:
 
 [source,java]
 ----
-CamelContext camelContext = new DefaultCamelContext();
-AMQConnectionResource pool = new AMQConnectionResource("tcp://localhost:33333", 1);
-SjmsComponent component = new SjmsComponent();
-component.setConnectionResource(pool);
-camelContext.addComponent("sjms", component);
+from("sjms:cheese?transacted=true")
+  .to("bean:foo")
+  .to("sjms:foo?transacted=true")
+  .to("bean:bar");
 ----
 
-=== Customizable Transaction Commit Strategies (Local JMS Transactions only)
-
-SJMS provides a developer the means to create a custom and plugable
-transaction strategy through the use of the `TransactionCommitStrategy`
-interface. This allows a user to define a unique set of circumstances
-that the `SessionTransactionSynchronization`
-will use to determine when to commit the Session.
-
-== Additional Notes
+Here the consumer and producer are both transacted, which means that only at the end of processing the message,
+then both the consumer and the producer will commit (or rollback in case of an exception during routing).
 
 === Message Header Format
 
@@ -468,18 +312,13 @@ dropped.
 === Clustering
 
 When using _InOut_ with SJMS in a clustered environment you must either
-use TemporaryQueue destinations or use a unique named reply to
+use TemporaryQueue destinations or use a unique reply to
 destination per InOut producer endpoint. Message correlation is handled
-by the endpoint, not with message selectors at the broker. The InOut
-Producer Endpoint uses Java Concurrency Exchangers cached by the Message
-`JMSCorrelationID`. This provides a nice performance increase while
-reducing the overhead on the broker since all the messages are consumed
-from the destination in the order they are produced by the interested
-consumer.
+by the producer, not with message selectors at the broker.
 
 [NOTE]
 ====
-You should only use queues as destination types, topics is not recommended or fully supported.
+You should only use queues as reply-to destination types, topics is not recommended or fully supported.
 ====
 
 Currently the only correlation strategy is to use the `JMSCorrelationId`.
@@ -487,26 +326,5 @@ The _InOut_ Consumer uses this strategy as well ensuring that all
 responses messages to the included `JMSReplyTo` destination also have the
 `JMSCorrelationId` copied from the request as well.
 
-== Transaction Support [[SJMS-transactions]]
-
-SJMS currently only supports the use of internal JMS Transactions. There
-is no support for the Camel Transaction Processor or the Java
-Transaction API (JTA).
-
-=== Does Springless Mean I Can't Use Spring?
-
-Not at all. Below is an example of the SJMS component using the Spring XML:
-
-[source,xml]
-----
-<route>
-    <from uri="direct:invoke.named.reply.to.queue" />
-    <to uri="sjms:queue:named.reply.to.queue?namedReplyTo=my.response.queue" />
-</route>
-----
-
-Springless refers to moving away from the dependency on the Spring JMS
-API. A new JMS client API is being developed from the ground up to power
-SJMS.
 
 include::camel-spring-boot::page$sjms-starter.adoc[]
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageConsumerResources.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageConsumerResources.java
deleted file mode 100644
index 6ed1e19..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageConsumerResources.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.component.sjms;
-
-import javax.jms.Destination;
-import javax.jms.MessageConsumer;
-import javax.jms.Session;
-
-@Deprecated
-public class MessageConsumerResources {
-
-    private final Session session;
-    private final MessageConsumer messageConsumer;
-    private final Destination replyToDestination;
-
-    public MessageConsumerResources(MessageConsumer messageConsumer) {
-        this(null, messageConsumer, null);
-    }
-
-    public MessageConsumerResources(Session session, MessageConsumer messageConsumer) {
-        this(session, messageConsumer, null);
-    }
-
-    public MessageConsumerResources(Session session, MessageConsumer messageConsumer, Destination replyToDestination) {
-        this.session = session;
-        this.messageConsumer = messageConsumer;
-        this.replyToDestination = replyToDestination;
-    }
-
-    public Session getSession() {
-        return session;
-    }
-
-    public MessageConsumer getMessageConsumer() {
-        return messageConsumer;
-    }
-
-    public Destination getReplyToDestination() {
-        return replyToDestination;
-    }
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageListenerContainer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageListenerContainer.java
index e85772a..02a8b55 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageListenerContainer.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageListenerContainer.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.sjms;
 
 import javax.jms.ConnectionFactory;
+import javax.jms.ExceptionListener;
 
 import org.apache.camel.AfterPropertiesConfigured;
 import org.apache.camel.Service;
@@ -27,4 +28,6 @@ public interface MessageListenerContainer extends Service, AfterPropertiesConfig
 
     void setMessageListener(SessionMessageListener messageListener);
 
+    void setExceptionListener(ExceptionListener exceptionListener);
+
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/OldSjmsConsumer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/OldSjmsConsumer.java
deleted file mode 100644
index 9138957..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/OldSjmsConsumer.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * 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.component.sjms;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.WeakHashMap;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.stream.Collectors;
-
-import javax.jms.Connection;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.Session;
-
-import org.apache.camel.Endpoint;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Processor;
-import org.apache.camel.component.sjms.consumer.AbstractMessageHandler;
-import org.apache.camel.component.sjms.consumer.InOnlyMessageHandler;
-import org.apache.camel.component.sjms.consumer.InOutMessageHandler;
-import org.apache.camel.component.sjms.jms.ConnectionResource;
-import org.apache.camel.component.sjms.tx.DefaultTransactionCommitStrategy;
-import org.apache.camel.component.sjms.tx.SessionTransactionSynchronization;
-import org.apache.camel.spi.Synchronization;
-import org.apache.camel.support.DefaultConsumer;
-import org.apache.camel.util.backoff.BackOff;
-import org.apache.camel.util.backoff.BackOffTimer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The SjmsConsumer is the base class for the SJMS MessageListener pool.
- */
-@Deprecated
-public class OldSjmsConsumer extends DefaultConsumer {
-
-    private static final Logger LOG = LoggerFactory.getLogger(OldSjmsConsumer.class);
-
-    private final Map<Connection, List<MessageConsumerResources>> consumers = new WeakHashMap<>();
-    private ScheduledExecutorService scheduler;
-    private Future<?> asyncStart;
-    private BackOffTimer.Task rescheduleTask;
-
-    public OldSjmsConsumer(Endpoint endpoint, Processor processor) {
-        super(endpoint, processor);
-    }
-
-    @Override
-    public SjmsEndpoint getEndpoint() {
-        return (SjmsEndpoint) super.getEndpoint();
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        super.doStart();
-
-        this.scheduler = getEndpoint().getCamelContext().getExecutorServiceManager().newDefaultScheduledThreadPool(this,
-                "SjmsConsumer");
-        if (getEndpoint().isAsyncStartListener()) {
-            asyncStart = getEndpoint().getComponent().getAsyncStartStopExecutorService().submit(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        fillConsumersPool();
-                    } catch (Throwable e) {
-                        LOG.warn("Error starting listener container on destination: " + getDestinationName()
-                                 + ". This exception will be ignored.",
-                                e);
-                        scheduleRefill(); //we should try to fill consumer pool on next time
-                    }
-                }
-
-                @Override
-                public String toString() {
-                    return "AsyncStartListenerTask[" + getDestinationName() + "]";
-                }
-            });
-        } else {
-            fillConsumersPool();
-        }
-    }
-
-    private void fillConsumersPool() throws Exception {
-        synchronized (consumers) {
-            while (consumers.values().stream().collect(Collectors.summarizingInt(List::size)).getSum() < getConsumerCount()) {
-                addConsumer();
-            }
-        }
-    }
-
-    public void destroyObject(MessageConsumerResources model) {
-        try {
-            if (model.getMessageConsumer() != null) {
-                model.getMessageConsumer().close();
-            }
-
-            // If the resource has a
-            if (model.getSession() != null) {
-                if (model.getSession().getTransacted()) {
-                    try {
-                        model.getSession().rollback();
-                    } catch (Exception e) {
-                        // Do nothing. Just make sure we are cleaned up
-                    }
-                }
-                model.getSession().close();
-            }
-        } catch (JMSException ex) {
-            LOG.warn("Exception caught on closing consumer", ex);
-        }
-    }
-
-    @Override
-    protected void doStop() throws Exception {
-        super.doStop();
-        if (asyncStart != null && !asyncStart.isDone()) {
-            asyncStart.cancel(true);
-        }
-        if (rescheduleTask != null) {
-            rescheduleTask.cancel();
-        }
-        if (getEndpoint().isAsyncStopListener()) {
-            getEndpoint().getComponent().getAsyncStartStopExecutorService().submit(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        synchronized (consumers) {
-                            consumers.values().stream().flatMap(Collection::stream).forEach(OldSjmsConsumer.this::destroyObject);
-                            consumers.clear();
-                        }
-                    } catch (Throwable e) {
-                        LOG.warn("Error stopping listener container on destination: " + getDestinationName()
-                                 + ". This exception will be ignored.",
-                                e);
-                    }
-                }
-
-                @Override
-                public String toString() {
-                    return "AsyncStopListenerTask[" + getDestinationName() + "]";
-                }
-            });
-        } else {
-            synchronized (consumers) {
-                consumers.values().stream().flatMap(Collection::stream).forEach(OldSjmsConsumer.this::destroyObject);
-                consumers.clear();
-            }
-        }
-        if (this.scheduler != null) {
-            getEndpoint().getCamelContext().getExecutorServiceManager().shutdownGraceful(this.scheduler);
-        }
-    }
-
-    /**
-     * Creates a {@link MessageConsumerResources} with a dedicated {@link Session} required for transacted and InOut
-     * consumers.
-     */
-    private void addConsumer() throws Exception {
-        MessageConsumerResources answer;
-        ConnectionResource connectionResource = getOrCreateConnectionResource();
-        Connection conn = connectionResource.borrowConnection();
-        try {
-            Session session = conn.createSession(isTransacted(),
-                    isTransacted() ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
-            MessageConsumer messageConsumer = getEndpoint().getJmsObjectFactory().createMessageConsumer(session, getEndpoint());
-            MessageListener handler = createMessageHandler(session);
-            messageConsumer.setMessageListener(handler);
-
-            ExceptionListener exceptionListener = conn.getExceptionListener();
-            ReconnectExceptionListener reconnectExceptionListener = new ReconnectExceptionListener(conn);
-            if (exceptionListener == null) {
-                exceptionListener = reconnectExceptionListener;
-            } else {
-                exceptionListener = new AggregatedExceptionListener(exceptionListener, reconnectExceptionListener);
-            }
-            conn.setExceptionListener(exceptionListener);
-            answer = new MessageConsumerResources(session, messageConsumer);
-            consumers.compute(conn, (key, oldValue) -> {
-                if (oldValue == null) {
-                    oldValue = new ArrayList<>();
-                }
-                oldValue.add(answer);
-                return oldValue;
-            });
-        } catch (Exception e) {
-            LOG.error("Unable to create the MessageConsumer", e);
-            throw e;
-        } finally {
-            connectionResource.returnConnection(conn);
-        }
-    }
-
-    /**
-     * Helper factory method used to create a MessageListener based on the MEP
-     *
-     * @param  session a session is only required if we are a transacted consumer
-     * @return         the listener
-     */
-    protected MessageListener createMessageHandler(Session session) {
-        TransactionCommitStrategy commitStrategy;
-        if (getTransactionCommitStrategy() != null) {
-            commitStrategy = getTransactionCommitStrategy();
-        } else {
-            commitStrategy = new DefaultTransactionCommitStrategy();
-        }
-
-        Synchronization synchronization = new SessionTransactionSynchronization(null, session, commitStrategy, false);
-
-        AbstractMessageHandler messageHandler;
-        if (getEndpoint().getExchangePattern().equals(ExchangePattern.InOnly)) {
-            if (isTransacted() || isSynchronous()) {
-                messageHandler = new InOnlyMessageHandler(getEndpoint(), scheduler, synchronization);
-            } else {
-                messageHandler = new InOnlyMessageHandler(getEndpoint(), scheduler);
-            }
-        } else {
-            if (isTransacted() || isSynchronous()) {
-                messageHandler = new InOutMessageHandler(getEndpoint(), scheduler, synchronization);
-            } else {
-                messageHandler = new InOutMessageHandler(getEndpoint(), scheduler);
-            }
-        }
-
-        messageHandler.setSession(session);
-        messageHandler.setProcessor(getAsyncProcessor());
-        messageHandler.setSynchronous(isSynchronous());
-        messageHandler.setTransacted(isTransacted());
-        messageHandler.setSharedJMSSession(isSharedJMSSession());
-        messageHandler.setTopic(isTopic());
-        return messageHandler;
-    }
-
-    /**
-     * @deprecated use {@link #getOrCreateConnectionResource()}
-     */
-    @Deprecated
-    protected ConnectionResource getConnectionResource() {
-        return getEndpoint().getConnectionResource();
-    }
-
-    protected ConnectionResource getOrCreateConnectionResource() {
-        ConnectionResource answer = getEndpoint().getConnectionResource();
-        if (answer == null) {
-            answer = getEndpoint().createConnectionResource(this);
-        }
-        return answer;
-    }
-
-    public int getAcknowledgementMode() {
-        return getEndpoint().getAcknowledgementMode().intValue();
-    }
-
-    /**
-     * Use to determine if transactions are enabled or disabled.
-     *
-     * @return true if transacted, otherwise false
-     */
-    public boolean isTransacted() {
-        return getEndpoint().isTransacted();
-    }
-
-    /**
-     * Use to determine if JMS session should be propagated to share with other SJMS endpoints.
-     *
-     * @return true if shared, otherwise false
-     */
-    public boolean isSharedJMSSession() {
-        return getEndpoint().isSharedJMSSession();
-    }
-
-    /**
-     * Use to determine whether or not to process exchanges synchronously.
-     *
-     * @return true if synchronous
-     */
-    public boolean isSynchronous() {
-        return getEndpoint().isSynchronous();
-    }
-
-    /**
-     * The destination name for this consumer.
-     *
-     * @return String
-     */
-    public String getDestinationName() {
-        return getEndpoint().getDestinationName();
-    }
-
-    /**
-     * Returns the number of consumer listeners.
-     *
-     * @return the consumerCount
-     */
-    public int getConsumerCount() {
-        return getEndpoint().getConsumerCount();
-    }
-
-    /**
-     * Flag set by the endpoint used by consumers and producers to determine if the consumer is a JMS Topic.
-     *
-     * @return the topic true if consumer is a JMS Topic, default is false
-     */
-    public boolean isTopic() {
-        return getEndpoint().isTopic();
-    }
-
-    /**
-     * Gets the JMS Message selector syntax.
-     */
-    public String getMessageSelector() {
-        return getEndpoint().getMessageSelector();
-    }
-
-    /**
-     * Gets the durable subscription Id.
-     *
-     * @return the durableSubscriptionId
-     */
-    public String getDurableSubscriptionId() {
-        return getEndpoint().getDurableSubscriptionId();
-    }
-
-    /**
-     * Gets the commit strategy.
-     *
-     * @return the transactionCommitStrategy
-     */
-    public TransactionCommitStrategy getTransactionCommitStrategy() {
-        return getEndpoint().getTransactionCommitStrategy();
-    }
-
-    private boolean refillPool(BackOffTimer.Task task) {
-        LOG.debug("Refill consumers pool task running");
-        try {
-            fillConsumersPool();
-            LOG.info("Refill consumers pool completed (attempt: {})", task.getCurrentAttempts());
-            return false;
-        } catch (Exception ex) {
-            LOG.warn(
-                    "Refill consumers pool failed (attempt: {}) due to: {}. Will try again in {} millis. (stacktrace in DEBUG level)",
-                    task.getCurrentAttempts(), ex.getMessage(), task.getCurrentDelay());
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Refill consumers pool failed", ex);
-            }
-        }
-        return true;
-    }
-
-    private void scheduleRefill() {
-        if (rescheduleTask == null || rescheduleTask.getStatus() != BackOffTimer.Task.Status.Active) {
-            BackOff backOff = BackOff.builder().delay(getEndpoint().getRecoveryInterval()).build();
-            rescheduleTask = new BackOffTimer(scheduler).schedule(backOff, this::refillPool);
-        }
-    }
-
-    private final class ReconnectExceptionListener implements ExceptionListener {
-        private final WeakReference<Connection> connection;
-
-        private ReconnectExceptionListener(Connection connection) {
-            this.connection = new WeakReference<>(connection);
-        }
-
-        @Override
-        public void onException(JMSException exception) {
-            LOG.debug("Handling JMSException for reconnecting", exception);
-            Connection currentConnection = connection.get();
-            if (currentConnection != null) {
-                synchronized (consumers) {
-                    List<MessageConsumerResources> toClose = consumers.get(currentConnection);
-                    if (toClose != null) {
-                        toClose.forEach(OldSjmsConsumer.this::destroyObject);
-                    }
-                    consumers.remove(currentConnection);
-                }
-                scheduleRefill();
-            }
-        }
-
-        //hash and equals to prevent multiple instances for same connection
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-            ReconnectExceptionListener that = (ReconnectExceptionListener) o;
-            return Objects.equals(connection.get(), that.connection.get());
-        }
-
-        @Override
-        public int hashCode() {
-            final Connection currentConnection = this.connection.get();
-            return currentConnection == null ? 0 : currentConnection.hashCode();
-        }
-    }
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/ReplyToType.java
similarity index 62%
copy from components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java
copy to components/camel-sjms/src/main/java/org/apache/camel/component/sjms/ReplyToType.java
index a6fbfac..d40808f 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/ReplyToType.java
@@ -14,23 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.sjms.tx;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.TransactionCommitStrategy;
+package org.apache.camel.component.sjms;
 
 /**
- * The default commit strategy for all transaction.
+ * Types for replyTo queues
  */
-public class DefaultTransactionCommitStrategy implements TransactionCommitStrategy {
+public enum ReplyToType {
 
-    @Override
-    public boolean commit(Exchange exchange) throws Exception {
-        return true;
-    }
+    Temporary,
+    Exclusive
 
-    @Override
-    public boolean rollback(Exchange exchange) throws Exception {
-        return true;
-    }
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsComponent.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsComponent.java
index a8865f4..e63a069 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsComponent.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsComponent.java
@@ -24,18 +24,15 @@ import javax.jms.ConnectionFactory;
 import org.apache.camel.CamelException;
 import org.apache.camel.Endpoint;
 import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.sjms.jms.ConnectionResource;
 import org.apache.camel.component.sjms.jms.DefaultJmsKeyFormatStrategy;
 import org.apache.camel.component.sjms.jms.DestinationCreationStrategy;
 import org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy;
 import org.apache.camel.component.sjms.jms.MessageCreatedStrategy;
 import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.support.HeaderFilterStrategyComponent;
 
-/**
- * The <a href="http://camel.apache.org/sjms">Simple JMS</a> component.
- */
 @Component("sjms")
 public class SjmsComponent extends HeaderFilterStrategyComponent {
 
@@ -44,10 +41,16 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
     @Metadata(label = "common", autowired = true,
               description = "A ConnectionFactory is required to enable the SjmsComponent. It can be set directly or set set as part of a ConnectionResource.")
     private ConnectionFactory connectionFactory;
-    @Metadata(label = "advanced",
-              description = "A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory."
-                            + " See Plugable Connection Resource Management for further details.")
-    private ConnectionResource connectionResource;
+    @Metadata(label = "security", secret = true,
+              description = "Username to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory.")
+    private String username;
+    @Metadata(label = "security", secret = true,
+              description = "Password to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory.")
+    private String password;
+    @UriParam(description = "Sets the JMS client ID to use. Note that this value, if specified, must be unique and can only be used by a single JMS connection instance."
+                            + " It is typically only required for durable topic subscriptions."
+                            + " If using Apache ActiveMQ you may prefer to use Virtual Topics instead.")
+    private String clientId;
     @Metadata(label = "advanced",
               description = "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification."
                             + " Camel provides one implementation out of the box: default. The default strategy will safely marshal dots and hyphens (. and -)."
@@ -57,38 +60,24 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
     @Metadata(defaultValue = "1",
               description = "The maximum number of connections available to endpoints started under this component")
     private Integer connectionCount = 1;
-    @Metadata(label = "transaction",
-              description = "To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch.")
-    private TransactionCommitStrategy transactionCommitStrategy;
     @Metadata(label = "advanced", description = "To use a custom DestinationCreationStrategy.")
     private DestinationCreationStrategy destinationCreationStrategy;
     @Metadata(label = "advanced",
               description = "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances"
                             + " of javax.jms.Message objects when Camel is sending a JMS message.")
     private MessageCreatedStrategy messageCreatedStrategy;
-    @Metadata(label = "advanced", defaultValue = "true",
-              description = "When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource"
-                            + " then should each javax.jms.Connection be tested before being used.")
-    private boolean connectionTestOnBorrow = true;
-    @Metadata(label = "security", secret = true,
-              description = "The username to use when creating javax.jms.Connection when using the"
-                            + " default org.apache.camel.component.sjms.jms.ConnectionFactoryResource.")
-    private String connectionUsername;
-    @Metadata(label = "security", secret = true,
-              description = "The password to use when creating javax.jms.Connection when using the"
-                            + " default org.apache.camel.component.sjms.jms.ConnectionFactoryResource.")
-    private String connectionPassword;
-    @Metadata(label = "advanced", description = "The client ID to use when creating javax.jms.Connection when using the"
-                                                + " default org.apache.camel.component.sjms.jms.ConnectionFactoryResource.")
-    private String connectionClientId;
-    @Metadata(label = "advanced", defaultValue = "5000",
-              description = "The max wait time in millis to block and wait on free connection when the pool"
-                            + " is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource.")
-    private long connectionMaxWait = 5000;
     @Metadata(defaultValue = "5000", label = "advanced", javaType = "java.time.Duration",
               description = "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds."
                             + " The default is 5000 ms, that is, 5 seconds.")
     private long recoveryInterval = 5000;
+    @Metadata(defaultValue = "1000", label = "advanced", javaType = "java.time.Duration",
+              description = "Configures how often Camel should check for timed out Exchanges when doing request/reply over JMS."
+                            + " By default Camel checks once per second. But if you must react faster when a timeout occurs,"
+                            + " then you can lower this interval, to check more frequently. The timeout is determined by the option requestTimeout.")
+    private long requestTimeoutCheckerInterval = 1000L;
+    @Metadata(label = "advanced", defaultValue = "1",
+              description = "Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request/reply over JMS.")
+    private int replyToOnTimeoutMaxConcurrentConsumers = 1;
 
     public SjmsComponent() {
     }
@@ -103,9 +92,6 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
         if (endpoint.isTransacted()) {
             endpoint.setSynchronous(true);
         }
-        if (transactionCommitStrategy != null) {
-            endpoint.setTransactionCommitStrategy(transactionCommitStrategy);
-        }
         if (destinationCreationStrategy != null) {
             endpoint.setDestinationCreationStrategy(destinationCreationStrategy);
         }
@@ -164,10 +150,6 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
         return asyncStartStopExecutorService;
     }
 
-    /**
-     * A ConnectionFactory is required to enable the SjmsComponent. It can be set directly or set set as part of a
-     * ConnectionResource.
-     */
     public void setConnectionFactory(ConnectionFactory connectionFactory) {
         this.connectionFactory = connectionFactory;
     }
@@ -176,21 +158,6 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
         return connectionFactory;
     }
 
-    /**
-     * A ConnectionResource is an interface that allows for customization and container control of the
-     * ConnectionFactory. See Plugable Connection Resource Management for further details.
-     */
-    public void setConnectionResource(ConnectionResource connectionResource) {
-        this.connectionResource = connectionResource;
-    }
-
-    public ConnectionResource getConnectionResource() {
-        return connectionResource;
-    }
-
-    /**
-     * The maximum number of connections available to endpoints started under this component
-     */
     public void setConnectionCount(Integer maxConnections) {
         this.connectionCount = maxConnections;
     }
@@ -199,13 +166,6 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
         return connectionCount;
     }
 
-    /**
-     * Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel
-     * provides one implementation out of the box: default. The default strategy will safely marshal dots and hyphens (.
-     * and -). Can be used for JMS brokers which do not care whether JMS header keys contain illegal characters. You can
-     * provide your own implementation of the org.apache.camel.component.jms.JmsKeyFormatStrategy and refer to it using
-     * the # notation.
-     */
     public void setJmsKeyFormatStrategy(JmsKeyFormatStrategy jmsKeyFormatStrategy) {
         this.jmsKeyFormatStrategy = jmsKeyFormatStrategy;
     }
@@ -214,25 +174,10 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
         return jmsKeyFormatStrategy;
     }
 
-    public TransactionCommitStrategy getTransactionCommitStrategy() {
-        return transactionCommitStrategy;
-    }
-
-    /**
-     * To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and
-     * batch.
-     */
-    public void setTransactionCommitStrategy(TransactionCommitStrategy commitStrategy) {
-        this.transactionCommitStrategy = commitStrategy;
-    }
-
     public DestinationCreationStrategy getDestinationCreationStrategy() {
         return destinationCreationStrategy;
     }
 
-    /**
-     * To use a custom DestinationCreationStrategy.
-     */
     public void setDestinationCreationStrategy(DestinationCreationStrategy destinationCreationStrategy) {
         this.destinationCreationStrategy = destinationCreationStrategy;
     }
@@ -241,79 +186,55 @@ public class SjmsComponent extends HeaderFilterStrategyComponent {
         return messageCreatedStrategy;
     }
 
-    /**
-     * To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of
-     * <tt>javax.jms.Message</tt> objects when Camel is sending a JMS message.
-     */
     public void setMessageCreatedStrategy(MessageCreatedStrategy messageCreatedStrategy) {
         this.messageCreatedStrategy = messageCreatedStrategy;
     }
 
-    public boolean isConnectionTestOnBorrow() {
-        return connectionTestOnBorrow;
+    public String getUsername() {
+        return username;
     }
 
-    /**
-     * When using the default {@link org.apache.camel.component.sjms.jms.ConnectionFactoryResource} then should each
-     * {@link javax.jms.Connection} be tested before being used.
-     */
-    public void setConnectionTestOnBorrow(boolean connectionTestOnBorrow) {
-        this.connectionTestOnBorrow = connectionTestOnBorrow;
+    public void setUsername(String username) {
+        this.username = username;
     }
 
-    public String getConnectionUsername() {
-        return connectionUsername;
+    public String getPassword() {
+        return password;
     }
 
-    /**
-     * The username to use when creating {@link javax.jms.Connection} when using the default
-     * {@link org.apache.camel.component.sjms.jms.ConnectionFactoryResource}.
-     */
-    public void setConnectionUsername(String connectionUsername) {
-        this.connectionUsername = connectionUsername;
+    public void setPassword(String password) {
+        this.password = password;
     }
 
-    public String getConnectionPassword() {
-        return connectionPassword;
+    public String getClientId() {
+        return clientId;
     }
 
-    /**
-     * The password to use when creating {@link javax.jms.Connection} when using the default
-     * {@link org.apache.camel.component.sjms.jms.ConnectionFactoryResource}.
-     */
-    public void setConnectionPassword(String connectionPassword) {
-        this.connectionPassword = connectionPassword;
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
     }
 
-    public String getConnectionClientId() {
-        return connectionClientId;
+    public long getRecoveryInterval() {
+        return recoveryInterval;
     }
 
-    /**
-     * The client ID to use when creating {@link javax.jms.Connection} when using the default
-     * {@link org.apache.camel.component.sjms.jms.ConnectionFactoryResource}.
-     */
-    public void setConnectionClientId(String connectionClientId) {
-        this.connectionClientId = connectionClientId;
+    public void setRecoveryInterval(long recoveryInterval) {
+        this.recoveryInterval = recoveryInterval;
     }
 
-    public long getConnectionMaxWait() {
-        return connectionMaxWait;
+    public long getRequestTimeoutCheckerInterval() {
+        return requestTimeoutCheckerInterval;
     }
 
-    /**
-     * The max wait time in millis to block and wait on free connection when the pool is exhausted when using the
-     * default {@link org.apache.camel.component.sjms.jms.ConnectionFactoryResource}.
-     */
-    public void setConnectionMaxWait(long connectionMaxWait) {
-        this.connectionMaxWait = connectionMaxWait;
+    public void setRequestTimeoutCheckerInterval(long requestTimeoutCheckerInterval) {
+        this.requestTimeoutCheckerInterval = requestTimeoutCheckerInterval;
     }
 
-    public long getRecoveryInterval() {
-        return recoveryInterval;
+    public int getReplyToOnTimeoutMaxConcurrentConsumers() {
+        return replyToOnTimeoutMaxConcurrentConsumers;
     }
 
-    public void setRecoveryInterval(long recoveryInterval) {
-        this.recoveryInterval = recoveryInterval;
+    public void setReplyToOnTimeoutMaxConcurrentConsumers(int replyToOnTimeoutMaxConcurrentConsumers) {
+        this.replyToOnTimeoutMaxConcurrentConsumers = replyToOnTimeoutMaxConcurrentConsumers;
     }
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java
index ee3c230..5c146a3 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java
@@ -34,11 +34,8 @@ import org.apache.camel.LoggingLevel;
 import org.apache.camel.MultipleConsumersSupport;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
-import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.component.sjms.consumer.EndpointMessageListener;
 import org.apache.camel.component.sjms.consumer.SimpleMessageListenerContainer;
-import org.apache.camel.component.sjms.jms.ConnectionFactoryResource;
-import org.apache.camel.component.sjms.jms.ConnectionResource;
 import org.apache.camel.component.sjms.jms.DefaultDestinationCreationStrategy;
 import org.apache.camel.component.sjms.jms.DefaultJmsKeyFormatStrategy;
 import org.apache.camel.component.sjms.jms.DestinationCreationStrategy;
@@ -46,11 +43,10 @@ import org.apache.camel.component.sjms.jms.DestinationNameParser;
 import org.apache.camel.component.sjms.jms.Jms11ObjectFactory;
 import org.apache.camel.component.sjms.jms.JmsBinding;
 import org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy;
+import org.apache.camel.component.sjms.jms.JmsMessageHelper;
 import org.apache.camel.component.sjms.jms.JmsObjectFactory;
 import org.apache.camel.component.sjms.jms.MessageCreatedStrategy;
 import org.apache.camel.component.sjms.jms.SessionAcknowledgementType;
-import org.apache.camel.component.sjms.producer.InOnlyProducer;
-import org.apache.camel.component.sjms.producer.InOutProducer;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
 import org.apache.camel.spi.Metadata;
@@ -59,9 +55,8 @@ import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriPath;
 import org.apache.camel.support.DefaultEndpoint;
 import org.apache.camel.support.EndpointHelper;
-import org.apache.camel.support.LoggingExceptionHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.camel.support.SynchronousDelegateProducer;
+import org.apache.camel.util.StringHelper;
 
 /**
  * Send and receive messages to/from a JMS Queue or Topic using plain JMS 1.x API.
@@ -73,8 +68,6 @@ import org.slf4j.LoggerFactory;
 public class SjmsEndpoint extends DefaultEndpoint
         implements AsyncEndpoint, MultipleConsumersSupport, HeaderFilterStrategyAware {
 
-    private static final Logger LOG = LoggerFactory.getLogger(SjmsEndpoint.class);
-
     private boolean topic;
     private JmsBinding binding;
 
@@ -100,13 +93,28 @@ public class SjmsEndpoint extends DefaultEndpoint
     @UriParam(label = "common",
               description = "Provides an explicit ReplyTo destination (overrides any incoming value of Message.getJMSReplyTo() in consumer).")
     private String replyTo;
+    @UriParam(label = "producer",
+              description = "Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request/reply over JMS."
+                            + " Possible values are: Temporary, Shared, or Exclusive."
+                            + " By default Camel will use temporary queues. However if replyTo has been configured, then Shared is used by default."
+                            + " This option allows you to use exclusive queues instead of shared ones."
+                            + " See Camel JMS documentation for more details, and especially the notes about the implications if running in a clustered environment,"
+                            + " and the fact that Shared reply queues has lower performance than its alternatives Temporary and Exclusive.")
+    private ReplyToType replyToType;
     @UriParam(defaultValue = "AUTO_ACKNOWLEDGE",
               enums = "SESSION_TRANSACTED,CLIENT_ACKNOWLEDGE,AUTO_ACKNOWLEDGE,DUPS_OK_ACKNOWLEDGE",
               description = "The JMS acknowledgement name, which is one of: SESSION_TRANSACTED, CLIENT_ACKNOWLEDGE, AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE")
     private SessionAcknowledgementType acknowledgementMode = SessionAcknowledgementType.AUTO_ACKNOWLEDGE;
-    @UriParam(label = "consumer", defaultValue = "1",
-              description = "Sets the number of consumer listeners used for this endpoint.")
-    private int consumerCount = 1;
+    @UriParam(defaultValue = "1", label = "consumer",
+              description = "Specifies the default number of concurrent consumers when consuming from JMS (not for request/reply over JMS)."
+                            + " See also the maxMessagesPerTask option to control dynamic scaling up/down of threads."
+                            + " When doing request/reply over JMS then the option replyToConcurrentConsumers is used to control number"
+                            + " of concurrent consumers on the reply message listener.")
+    private int concurrentConsumers = 1;
+    @UriParam(defaultValue = "1", label = "producer",
+              description = "Specifies the default number of concurrent consumers when doing request/reply over JMS."
+                            + " See also the maxMessagesPerTask option to control dynamic scaling up/down of threads.")
+    private int replyToConcurrentConsumers = 1;
     @UriParam(label = "producer", defaultValue = "false",
               description = "Set if the deliveryMode, priority or timeToLive qualities of service should be used when sending messages."
                             + " This option is based on Spring's JmsTemplate. The deliveryMode, priority and timeToLive options are applied to the current endpoint."
@@ -203,9 +211,6 @@ public class SjmsEndpoint extends DefaultEndpoint
               description = "Specifies whether Camel should auto map the received JMS message to a suited payload type, such as javax.jms.TextMessage to a String etc."
                             + " See section about how mapping works below for more details.")
     private boolean mapJmsMessage = true;
-    @UriParam(label = "transaction",
-              description = "Sets the commit strategy.")
-    private TransactionCommitStrategy transactionCommitStrategy;
     @UriParam(label = "advanced",
               description = "To use a custom DestinationCreationStrategy.")
     private DestinationCreationStrategy destinationCreationStrategy = new DefaultDestinationCreationStrategy();
@@ -219,9 +224,6 @@ public class SjmsEndpoint extends DefaultEndpoint
                             + " You can provide your own implementation of the org.apache.camel.component.jms.JmsKeyFormatStrategy and refer to it using the # notation.")
     private JmsKeyFormatStrategy jmsKeyFormatStrategy;
     @UriParam(label = "advanced",
-              description = "Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any")
-    private ConnectionResource connectionResource;
-    @UriParam(label = "advanced",
               description = "Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any")
     private ConnectionFactory connectionFactory;
     @UriParam(label = "advanced",
@@ -270,6 +272,11 @@ public class SjmsEndpoint extends DefaultEndpoint
                             + " Note if transacted has been enabled, then asyncConsumer=true does not run asynchronously, as transaction"
                             + "  must be executed synchronously (Camel 3.0 may support async transactions).")
     private boolean asyncConsumer;
+    @UriParam(label = "producer,advanced",
+              description = "Only applicable when sending to JMS destination using InOnly (eg fire and forget)."
+                            + " Enabling this option will enrich the Camel Exchange with the actual JMSMessageID"
+                            + " that was used by the JMS client when the message was sent to the JMS destination.")
+    private boolean includeSentJMSMessageID;
 
     private JmsObjectFactory jmsObjectFactory = new Jms11ObjectFactory();
 
@@ -287,21 +294,48 @@ public class SjmsEndpoint extends DefaultEndpoint
         return (SjmsComponent) super.getComponent();
     }
 
+    /**
+     * Gets the destination name which was configured from the endpoint uri.
+     *
+     * @return the destination name resolved from the endpoint uri
+     */
+    public String getEndpointConfiguredDestinationName() {
+        String remainder = StringHelper.after(getEndpointKey(), "//");
+        if (remainder != null && remainder.contains("?")) {
+            // remove parameters
+            remainder = StringHelper.before(remainder, "?");
+        }
+        return JmsMessageHelper.normalizeDestinationName(remainder);
+    }
+
     @Override
     public Producer createProducer() throws Exception {
-        SjmsProducer producer;
-        // TODO: Merge inOutProducer and InOnlyProducer into one class so this can be dynamic via exchange MEP
-        if (!isDisableReplyTo() && getExchangePattern().equals(ExchangePattern.InOut)) {
-            producer = new InOutProducer(this);
+        if (isTransacted() && getExchangePattern().isOutCapable()) {
+            throw new IllegalArgumentException("SjmsProducer cannot be both transacted=true and exchangePattern=InOut");
+        }
+
+        Producer answer = new SjmsProducer(this);
+        if (isSynchronous()) {
+            return new SynchronousDelegateProducer(answer);
         } else {
-            producer = new InOnlyProducer(this);
+            return answer;
         }
-        return producer;
     }
 
     @Override
     public Consumer createConsumer(Processor processor) throws Exception {
         EndpointMessageListener listener = new EndpointMessageListener(this, processor);
+        configureMessageListener(listener);
+
+        MessageListenerContainer container = createMessageListenerContainer(this);
+        container.setMessageListener(listener);
+
+        SjmsConsumer consumer = new SjmsConsumer(this, processor, container);
+        configureConsumer(consumer);
+        return consumer;
+    }
+
+    public void configureMessageListener(EndpointMessageListener listener) {
         if (isDisableReplyTo()) {
             listener.setDisableReplyTo(true);
         }
@@ -313,13 +347,6 @@ public class SjmsEndpoint extends DefaultEndpoint
             listener.setReplyToDestination(getReplyTo());
         }
         listener.setAsync(isAsyncConsumer());
-
-        MessageListenerContainer container = createMessageListenerContainer(this);
-        container.setMessageListener(listener);
-
-        SjmsConsumer consumer = new SjmsConsumer(this, processor, container);
-        configureConsumer(consumer);
-        return consumer;
     }
 
     @Override
@@ -327,37 +354,6 @@ public class SjmsEndpoint extends DefaultEndpoint
         return true;
     }
 
-    @Deprecated
-    public ConnectionResource createConnectionResource(Object source) {
-        if (getConnectionFactory() == null) {
-            throw new IllegalArgumentException(
-                    String.format("ConnectionResource or ConnectionFactory must be configured for %s", this));
-        }
-
-        try {
-            LOG.debug("Creating ConnectionResource with connectionCount: {} using ConnectionFactory: {}",
-                    getConnectionCount(), getConnectionFactory());
-            // We always use a connection pool, even for a pool of 1
-            ConnectionFactoryResource connections = new ConnectionFactoryResource(
-                    getConnectionCount(), getConnectionFactory(),
-                    getComponent().getConnectionUsername(), getComponent().getConnectionPassword(),
-                    getComponent().getConnectionClientId(),
-                    getComponent().getConnectionMaxWait(), getComponent().isConnectionTestOnBorrow());
-            if (exceptionListener != null) {
-                connections.setExceptionListener(exceptionListener);
-            } else {
-                // add a exception listener that logs so we can see any errors that happens
-                ExceptionListener listener = new SjmsLoggingExceptionListener(
-                        new LoggingExceptionHandler(getCamelContext(), source.getClass()), isErrorHandlerLogStackTrace());
-                connections.setExceptionListener(listener);
-            }
-            connections.fillPool();
-            return connections;
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeCamelException(e);
-        }
-    }
-
     public Exchange createExchange(Message message, Session session) {
         Exchange exchange = createExchange(getExchangePattern());
         exchange.setIn(new SjmsMessage(exchange, message, session, getBinding()));
@@ -379,6 +375,7 @@ public class SjmsEndpoint extends DefaultEndpoint
             }
             template.setQoSSettings(dm, getPriority(), getTimeToLive());
         }
+        template.setDestinationCreationStrategy(getDestinationCreationStrategy());
 
         return template;
     }
@@ -399,11 +396,15 @@ public class SjmsEndpoint extends DefaultEndpoint
                 template.setQoSSettings(0, 0, ttl);
             }
         }
+        template.setDestinationCreationStrategy(getDestinationCreationStrategy());
+
         return template;
     }
 
     public MessageListenerContainer createMessageListenerContainer(SjmsEndpoint endpoint) throws Exception {
-        return new SimpleMessageListenerContainer(endpoint);
+        SimpleMessageListenerContainer answer = new SimpleMessageListenerContainer(endpoint);
+        answer.setConcurrentConsumers(concurrentConsumers);
+        return answer;
     }
 
     /**
@@ -497,30 +498,6 @@ public class SjmsEndpoint extends DefaultEndpoint
         this.includeAllJMSXProperties = includeAllJMSXProperties;
     }
 
-    public ConnectionResource getConnectionResource() {
-        ConnectionResource answer = null;
-        if (connectionResource != null) {
-            answer = connectionResource;
-        }
-        if (answer == null) {
-            answer = getComponent().getConnectionResource();
-        }
-        return answer;
-    }
-
-    /**
-     * Initializes the connectionResource for the endpoint, which takes precedence over the component's
-     * connectionResource, if any
-     */
-    public void setConnectionResource(ConnectionResource connectionResource) {
-        this.connectionResource = connectionResource;
-    }
-
-    public void setConnectionResource(String connectionResource) {
-        this.connectionResource
-                = EndpointHelper.resolveReferenceParameter(getCamelContext(), connectionResource, ConnectionResource.class);
-    }
-
     public SessionAcknowledgementType getAcknowledgementMode() {
         return acknowledgementMode;
     }
@@ -540,15 +517,20 @@ public class SjmsEndpoint extends DefaultEndpoint
         return topic;
     }
 
-    public int getConsumerCount() {
-        return consumerCount;
+    public int getConcurrentConsumers() {
+        return concurrentConsumers;
     }
 
-    /**
-     * Sets the number of consumer listeners used for this endpoint.
-     */
-    public void setConsumerCount(int consumerCount) {
-        this.consumerCount = consumerCount;
+    public void setConcurrentConsumers(int concurrentConsumers) {
+        this.concurrentConsumers = concurrentConsumers;
+    }
+
+    public int getReplyToConcurrentConsumers() {
+        return replyToConcurrentConsumers;
+    }
+
+    public void setReplyToConcurrentConsumers(int replyToConcurrentConsumers) {
+        this.replyToConcurrentConsumers = replyToConcurrentConsumers;
     }
 
     public Boolean getExplicitQosEnabled() {
@@ -669,17 +651,6 @@ public class SjmsEndpoint extends DefaultEndpoint
         this.messageSelector = messageSelector;
     }
 
-    public TransactionCommitStrategy getTransactionCommitStrategy() {
-        return transactionCommitStrategy;
-    }
-
-    /**
-     * Sets the commit strategy.
-     */
-    public void setTransactionCommitStrategy(TransactionCommitStrategy transactionCommitStrategy) {
-        this.transactionCommitStrategy = transactionCommitStrategy;
-    }
-
     public boolean isTransacted() {
         return transacted;
     }
@@ -716,6 +687,14 @@ public class SjmsEndpoint extends DefaultEndpoint
         setExchangePattern(ExchangePattern.InOut);
     }
 
+    public ReplyToType getReplyToType() {
+        return replyToType;
+    }
+
+    public void setReplyToType(ReplyToType replyToType) {
+        this.replyToType = replyToType;
+    }
+
     public boolean isTestConnectionOnStartup() {
         return testConnectionOnStartup;
     }
@@ -941,4 +920,12 @@ public class SjmsEndpoint extends DefaultEndpoint
     public void setAsyncConsumer(boolean asyncConsumer) {
         this.asyncConsumer = asyncConsumer;
     }
+
+    public boolean isIncludeSentJMSMessageID() {
+        return includeSentJMSMessageID;
+    }
+
+    public void setIncludeSentJMSMessageID(boolean includeSentJMSMessageID) {
+        this.includeSentJMSMessageID = includeSentJMSMessageID;
+    }
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsHelper.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsHelper.java
index bff6ecc..013ce1b 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsHelper.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsHelper.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.sjms;
 
 import javax.jms.Connection;
 import javax.jms.JMSException;
+import javax.jms.Message;
 import javax.jms.MessageConsumer;
 import javax.jms.MessageProducer;
 import javax.jms.Session;
@@ -80,11 +81,32 @@ public final class SjmsHelper {
         }
     }
 
-    public static void rollbackIfNecessary(Session session) throws JMSException {
-        try {
-            session.rollback();
-        } catch (javax.jms.TransactionInProgressException | javax.jms.IllegalStateException ex) {
-            // ignore
+    public static void commitIfNeeded(Session session, Message message) throws Exception {
+        if (session.getTransacted()) {
+            SjmsHelper.commitIfNecessary(session);
+        } else if (message != null && session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) {
+            message.acknowledge();
         }
     }
+
+    public static void rollbackIfNeeded(Session session) throws JMSException {
+        if (session.getTransacted()) {
+            try {
+                session.rollback();
+            } catch (javax.jms.TransactionInProgressException | javax.jms.IllegalStateException ex) {
+                // ignore
+            }
+        } else if (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) {
+            try {
+                session.recover();
+            } catch (javax.jms.IllegalStateException ex) {
+                // ignore
+            }
+        }
+    }
+
+    public static boolean isTransactionOrClientAcknowledgeMode(Session session) throws JMSException {
+        return session.getTransacted() || session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE;
+    }
+
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsProducer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsProducer.java
index 6bc7d80..57ee7ed 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsProducer.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsProducer.java
@@ -16,160 +16,521 @@
  */
 package org.apache.camel.component.sjms;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import javax.jms.Connection;
-import javax.jms.DeliveryMode;
 import javax.jms.Destination;
 import javax.jms.JMSException;
+import javax.jms.Message;
 import javax.jms.Session;
 
 import org.apache.camel.AsyncCallback;
-import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.tx.SessionTransactionSynchronization;
+import org.apache.camel.ExtendedExchange;
+import org.apache.camel.FailedToCreateProducerException;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.RuntimeExchangeException;
+import org.apache.camel.component.sjms.jms.JmsMessageHelper;
+import org.apache.camel.component.sjms.jms.MessageCreator;
+import org.apache.camel.component.sjms.reply.QueueReplyManager;
+import org.apache.camel.component.sjms.reply.ReplyManager;
+import org.apache.camel.component.sjms.reply.TemporaryQueueReplyManager;
+import org.apache.camel.spi.UuidGenerator;
 import org.apache.camel.support.DefaultAsyncProducer;
+import org.apache.camel.support.SynchronizationAdapter;
+import org.apache.camel.support.service.ServiceHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-/**
- * Base SjmsProducer class.
- */
-public abstract class SjmsProducer extends DefaultAsyncProducer {
 
-    protected SjmsTemplate template;
+import static org.apache.camel.component.sjms.SjmsHelper.*;
+import static org.apache.camel.component.sjms.jms.JmsMessageHelper.*;
+
+public class SjmsProducer extends DefaultAsyncProducer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SjmsProducer.class);
+
+    private static final String GENERATED_CORRELATION_ID_PREFIX = "Camel-";
+    private final SjmsEndpoint endpoint;
+    private final AtomicBoolean started = new AtomicBoolean();
+    private SjmsTemplate inOnlyTemplate;
+    private SjmsTemplate inOutTemplate;
+    private UuidGenerator uuidGenerator;
+    private ReplyManager replyManager;
 
-    public SjmsProducer(Endpoint endpoint) {
+    public SjmsProducer(SjmsEndpoint endpoint) {
         super(endpoint);
+        this.endpoint = endpoint;
+    }
+
+    @Override
+    public SjmsEndpoint getEndpoint() {
+        return (SjmsEndpoint) super.getEndpoint();
     }
 
     @Override
     protected void doInit() throws Exception {
-        template = new SjmsTemplate(getEndpoint().getConnectionFactory(), isEndpointTransacted(), getAcknowledgeMode());
+        super.doInit();
+        if (uuidGenerator == null) {
+            // use the generator configured on the camel context
+            uuidGenerator = getEndpoint().getCamelContext().getUuidGenerator();
+        }
+    }
 
-        // configure qos if enabled
-        if (getEndpoint().isExplicitQosEnabled()) {
-            int dm = getEndpoint().isDeliveryPersistent() ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT;
-            if (getEndpoint().getDeliveryMode() != null) {
-                dm = getEndpoint().getDeliveryMode();
-            }
-            template.setQoSSettings(dm, getEndpoint().getPriority(), getEndpoint().getTimeToLive());
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        if (endpoint.isTestConnectionOnStartup()) {
+            testConnectionOnStartup();
         }
     }
 
     @Override
-    public SjmsEndpoint getEndpoint() {
-        return (SjmsEndpoint) super.getEndpoint();
+    protected void doStop() throws Exception {
+        super.doStop();
+
+        // must stop/un-init reply manager if it was in use
+        unInitReplyManager();
+    }
+
+    protected void initReplyManager() {
+        if (!started.get()) {
+            synchronized (this) {
+                if (started.get()) {
+                    return;
+                }
+
+                // must use the classloader from the application context when creating reply manager,
+                // as it should inherit the classloader from app context and not the current which may be
+                // a different classloader
+                ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+                ClassLoader ac = endpoint.getCamelContext().getApplicationContextClassLoader();
+                try {
+                    if (ac != null) {
+                        Thread.currentThread().setContextClassLoader(ac);
+                    }
+                    // validate that replyToType and replyTo is configured accordingly
+                    if (endpoint.getReplyToType() != null) {
+                        // setting temporary with a fixed replyTo is not supported
+                        if (endpoint.getReplyTo() != null && endpoint.getReplyToType().equals(ReplyToType.Temporary.name())) {
+                            throw new IllegalArgumentException(
+                                    "ReplyToType " + ReplyToType.Temporary
+                                                               + " is not supported when replyTo " + endpoint.getReplyTo()
+                                                               + " is also configured.");
+                        }
+                    }
+
+                    if (endpoint.getReplyTo() != null) {
+                        replyManager = createReplyManager(endpoint.getReplyTo());
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Using JmsReplyManager: {} to process replies from: {}", replyManager,
+                                    endpoint.getReplyTo());
+                        }
+                    } else {
+                        replyManager = createReplyManager();
+                        LOG.debug("Using JmsReplyManager: {} to process replies from temporary queue", replyManager);
+                    }
+                } catch (Exception e) {
+                    throw new FailedToCreateProducerException(endpoint, e);
+                } finally {
+                    Thread.currentThread().setContextClassLoader(oldClassLoader);
+                }
+                started.set(true);
+            }
+        }
+    }
+
+    protected void unInitReplyManager() {
+        try {
+            if (replyManager != null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Stopping JmsReplyManager: {} from processing replies from: {}", replyManager,
+                            endpoint.getReplyTo() != null ? endpoint.getReplyTo() : "temporary queue");
+                }
+                ServiceHelper.stopService(replyManager);
+            }
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        } finally {
+            started.set(false);
+        }
+    }
+
+    protected ReplyManager createReplyManager(String replyTo) throws Exception {
+        // use a regular queue
+        ReplyManager replyManager = new QueueReplyManager(getEndpoint().getCamelContext());
+        replyManager.setEndpoint(getEndpoint());
+
+        String name = "JmsReplyManagerTimeoutChecker[" + replyTo + "]";
+        ScheduledExecutorService replyManagerScheduledExecutorService
+                = getEndpoint().getCamelContext().getExecutorServiceManager().newSingleThreadScheduledExecutor(name, name);
+        replyManager.setScheduledExecutorService(replyManagerScheduledExecutorService);
+
+        name = "JmsReplyManagerOnTimeout[" + replyTo + "]";
+        // allow the timeout thread to timeout so during normal operation we do not have a idle thread
+        int max = getEndpoint().getComponent().getReplyToOnTimeoutMaxConcurrentConsumers();
+        if (max <= 0) {
+            throw new IllegalArgumentException("The option replyToOnTimeoutMaxConcurrentConsumers must be >= 1");
+        }
+        ExecutorService replyManagerExecutorService
+                = getEndpoint().getCamelContext().getExecutorServiceManager().newThreadPool(replyManager, name, 0, max);
+        replyManager.setOnTimeoutExecutorService(replyManagerExecutorService);
+
+        ServiceHelper.startService(replyManager);
+
+        return replyManager;
     }
 
-    protected Destination resolveDestinationName(Session session, String destinationName) throws JMSException {
-        return getEndpoint().getDestinationCreationStrategy().createDestination(session,
-                destinationName, getEndpoint().isTopic());
+    protected ReplyManager createReplyManager() throws Exception {
+        // use a temporary queue
+        ReplyManager replyManager = new TemporaryQueueReplyManager(getEndpoint().getCamelContext());
+        replyManager.setEndpoint(getEndpoint());
+
+        String name = "JmsReplyManagerTimeoutChecker[" + getEndpoint().getEndpointConfiguredDestinationName() + "]";
+        ScheduledExecutorService replyManagerScheduledExecutorService
+                = getEndpoint().getCamelContext().getExecutorServiceManager().newSingleThreadScheduledExecutor(name, name);
+        replyManager.setScheduledExecutorService(replyManagerScheduledExecutorService);
+
+        name = "JmsReplyManagerOnTimeout[" + getEndpoint().getEndpointConfiguredDestinationName() + "]";
+        // allow the timeout thread to timeout so during normal operation we do not have a idle thread
+        int max = getEndpoint().getComponent().getReplyToOnTimeoutMaxConcurrentConsumers();
+        if (max <= 0) {
+            throw new IllegalArgumentException("The option replyToOnTimeoutMaxConcurrentConsumers must be >= 1");
+        }
+        ExecutorService replyManagerExecutorService
+                = getEndpoint().getCamelContext().getExecutorServiceManager().newThreadPool(replyManager, name, 0, max);
+        replyManager.setOnTimeoutExecutorService(replyManagerExecutorService);
+
+        ServiceHelper.startService(replyManager);
+
+        return replyManager;
     }
 
-    protected abstract void sendMessage(Exchange exchange, Session sharedSession, String destinationName);
+    /**
+     * Pre tests the connection before starting the listening.
+     * <p/>
+     * In case of connection failure the exception is thrown which prevents Camel from starting.
+     *
+     * @throws FailedToCreateProducerException is thrown if testing the connection failed
+     */
+    protected void testConnectionOnStartup() throws FailedToCreateProducerException {
+        try {
+            SjmsTemplate template = getInOnlyTemplate();
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Testing JMS Connection on startup for destination: {}", getEndpoint().getDestinationName());
+            }
+
+            Connection conn = template.getConnectionFactory().createConnection();
+            SjmsHelper.closeConnection(conn);
+
+            LOG.debug("Successfully tested JMS Connection on startup for destination: {}",
+                    getEndpoint().getDestinationName());
+        } catch (Exception e) {
+            throw new FailedToCreateProducerException(getEndpoint(), e);
+        }
+    }
 
     @Override
-    public boolean process(final Exchange exchange, final AsyncCallback callback) {
-        String destinationName = exchange.getMessage().getHeader(SjmsConstants.JMS_DESTINATION_NAME, String.class);
-        if (destinationName != null) {
-            // remove the header so it wont be propagated
-            exchange.getMessage().removeHeader(SjmsConstants.JMS_DESTINATION_NAME);
+    public boolean process(Exchange exchange, AsyncCallback callback) {
+        // deny processing if we are not started
+        if (!isRunAllowed()) {
+            if (exchange.getException() == null) {
+                exchange.setException(new RejectedExecutionException());
+            }
+            // we cannot process so invoke callback
+            callback.done(true);
+            return true;
         }
 
-        return doProcess(exchange, callback, destinationName);
+        try {
+            if (!endpoint.isDisableReplyTo() && exchange.getPattern().isOutCapable()) {
+                // in out requires a bit more work than in only
+                return processInOut(exchange, callback);
+            } else {
+                // in only
+                return processInOnly(exchange, callback);
+            }
+        } catch (Throwable e) {
+            // must catch exception to ensure callback is invoked as expected
+            // to let Camel error handling deal with this
+            exchange.setException(e);
+            callback.done(true);
+            return true;
+        }
     }
 
-    protected boolean doProcess(Exchange exchange, AsyncCallback callback, String destinationName) {
+    protected boolean processInOut(final Exchange exchange, final AsyncCallback callback) {
+        final org.apache.camel.Message in = exchange.getIn();
+
+        String destinationName = in.getHeader(SjmsConstants.JMS_DESTINATION_NAME, String.class);
+        // remove the header so it wont be propagated
+        in.removeHeader(SjmsConstants.JMS_DESTINATION_NAME);
         if (destinationName == null) {
-            destinationName = getDestinationName();
+            destinationName = endpoint.getDestinationName();
+        }
+
+        initReplyManager();
+
+        // the request timeout can be overruled by a header otherwise the endpoint configured value is used
+        final long timeout
+                = exchange.getIn().getHeader(SjmsConstants.JMS_REQUEST_TIMEOUT, endpoint.getRequestTimeout(), long.class);
+
+        final String originalCorrelationId = in.getHeader("JMSCorrelationID", String.class);
+
+        boolean generateFreshCorrId = ObjectHelper.isEmpty(originalCorrelationId)
+                || originalCorrelationId.startsWith(GENERATED_CORRELATION_ID_PREFIX);
+        if (generateFreshCorrId) {
+            // we append the 'Camel-' prefix to know it was generated by us
+            in.setHeader("JMSCorrelationID", GENERATED_CORRELATION_ID_PREFIX + getUuidGenerator().generateUuid());
         }
+
+        MessageCreator messageCreator = new MessageCreator() {
+            public Message createMessage(Session session) throws JMSException {
+                Message answer = endpoint.getBinding().makeJmsMessage(exchange, in, session, null);
+
+                Destination replyTo;
+                String replyToOverride = endpoint.getReplyToOverride();
+                if (replyToOverride != null) {
+                    replyTo = resolveOrCreateDestination(replyToOverride, session);
+                } else {
+                    // get the reply to destination to be used from the reply manager
+                    replyTo = replyManager.getReplyTo();
+                }
+                if (replyTo == null) {
+                    throw new RuntimeExchangeException("Failed to resolve replyTo destination", exchange);
+                }
+                JmsMessageHelper.setJMSReplyTo(answer, replyTo);
+                replyManager.setReplyToSelectorHeader(in, answer);
+
+                String correlationId = determineCorrelationId(answer);
+                replyManager.registerReply(replyManager, exchange, callback, originalCorrelationId, correlationId, timeout);
+
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Using {}: {}, JMSReplyTo destination: {}, with request timeout: {} ms.",
+                            new Object[] { "JMSCorrelationID", correlationId, replyTo, timeout });
+                }
+
+                LOG.trace("Created javax.jms.Message: {}", answer);
+                return answer;
+            }
+        };
+
         try {
-            if (isEndpointTransacted()) {
-                Connection connection = null;
-                Session session = null;
-                boolean close = false;
-                if (isSharedJMSSession()) {
-                    session = exchange.getIn().getHeader(SjmsConstants.JMS_SESSION, Session.class);
+            doSend(true, destinationName, messageCreator);
+        } catch (Exception e) {
+            exchange.setException(e);
+            callback.done(true);
+            return true;
+        }
+
+        // continue routing asynchronously (reply will be processed async when its received)
+        return false;
+    }
+
+    protected boolean processInOnly(final Exchange exchange, final AsyncCallback callback) {
+        final org.apache.camel.Message in = exchange.getIn();
+
+        String destinationName = in.getHeader(SjmsConstants.JMS_DESTINATION_NAME, String.class);
+        if (destinationName != null) {
+            // remove the header so it wont be propagated
+            in.removeHeader(SjmsConstants.JMS_DESTINATION_NAME);
+        }
+        if (destinationName == null) {
+            destinationName = endpoint.getDestinationName();
+        }
+
+        final String to = destinationName;
+
+        MessageCreator messageCreator = new MessageCreator() {
+            public Message createMessage(Session session) throws JMSException {
+                Message answer = endpoint.getBinding().makeJmsMessage(exchange, in, session, null);
+
+                // when in InOnly mode the JMSReplyTo is a bit complicated
+                // we only want to set the JMSReplyTo on the answer if
+                // there is a JMSReplyTo from the header/endpoint and
+                // we have been told to preserveMessageQos
+
+                Object jmsReplyTo = JmsMessageHelper.getJMSReplyTo(answer);
+                if (endpoint.isDisableReplyTo()) {
+                    // honor disable reply to configuration
+                    LOG.trace("ReplyTo is disabled on endpoint: {}", endpoint);
+                    JmsMessageHelper.setJMSReplyTo(answer, null);
+                } else {
+                    // if the binding did not create the reply to then we have to try to create it here
+                    if (jmsReplyTo == null) {
+                        // prefer reply to from header over endpoint configured
+                        jmsReplyTo = exchange.getIn().getHeader("JMSReplyTo", String.class);
+                        if (jmsReplyTo == null) {
+                            jmsReplyTo = endpoint.getReplyTo();
+                        }
+                    }
                 }
-                if (session == null) {
-                    close = true;
-                    connection = template.createConnection();
-                    session = template.createSession(connection);
+
+                // we must honor these special flags to preserve QoS
+                // as we are not OUT capable and thus do not expect a reply, and therefore
+                // the consumer of this message should not return a reply so we remove it
+                // unless we use preserveMessageQos=true to tell that we still want to use JMSReplyTo
+                if (jmsReplyTo != null && !(endpoint.isPreserveMessageQos() || endpoint.isExplicitQosEnabled())) {
+                    // log at debug what we are doing, as higher level may cause noise in production logs
+                    // this behavior is also documented at the camel website
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug(
+                                "Disabling JMSReplyTo: {} for destination: {}. Use preserveMessageQos=true to force Camel to keep the JMSReplyTo on endpoint: {}",
+                                new Object[] { jmsReplyTo, to, endpoint });
+                    }
+                    jmsReplyTo = null;
                 }
-                exchange.getUnitOfWork().addSynchronization(
-                        new SessionTransactionSynchronization(connection, session, getCommitStrategy(), close));
-                sendMessage(exchange, session, destinationName);
-            } else {
-                sendMessage(exchange, null, destinationName);
+
+                // the reply to is a String, so we need to look up its Destination instance
+                // and if needed create the destination using the session if needed to
+                if (jmsReplyTo instanceof String) {
+                    String replyTo = (String) jmsReplyTo;
+                    // we need to null it as we use the String to resolve it as a Destination instance
+                    jmsReplyTo = resolveOrCreateDestination(replyTo, session);
+                }
+
+                // set the JMSReplyTo on the answer if we are to use it
+                Destination replyTo = null;
+                String replyToOverride = endpoint.getReplyToOverride();
+                if (replyToOverride != null) {
+                    replyTo = resolveOrCreateDestination(replyToOverride, session);
+                } else if (jmsReplyTo != null) {
+                    replyTo = (Destination) jmsReplyTo;
+                }
+                if (replyTo != null) {
+                    LOG.debug("Using JMSReplyTo destination: {}", replyTo);
+                    JmsMessageHelper.setJMSReplyTo(answer, replyTo);
+                } else {
+                    // do not use JMSReplyTo
+                    LOG.trace("Not using JMSReplyTo");
+                    JmsMessageHelper.setJMSReplyTo(answer, null);
+                }
+
+                // if transacted or client ack mode then add uow work to complete after exchange is done
+                if (isTransactionOrClientAcknowledgeMode(session)) {
+                    ExtendedExchange ecc = exchange.adapt(ExtendedExchange.class);
+                    TransactionOnCompletion toc = new TransactionOnCompletion(session, answer);
+                    if (!ecc.containsOnCompletion(toc)) {
+                        ecc.addOnCompletion(toc);
+                    }
+                }
+
+                LOG.trace("Created javax.jms.Message: {}", answer);
+                return answer;
             }
-        } catch (Throwable e) {
+        };
+
+        try {
+            doSend(false, destinationName, messageCreator);
+        } catch (Exception e) {
             exchange.setException(e);
+            callback.done(true);
+            return true;
         }
+
+        // after sending then set the OUT message id to the JMSMessageID so its identical
+        setMessageId(exchange);
+
+        // we are synchronous so return true
         callback.done(true);
         return true;
     }
 
-    /**
-     * Gets the acknowledgment mode for this instance of DestinationProducer.
-     */
-    public int getAcknowledgeMode() {
-        return getEndpoint().getAcknowledgementMode().intValue();
+    protected void setMessageId(Exchange exchange) {
+        if (exchange.hasOut()) {
+            SjmsMessage out = exchange.getOut(SjmsMessage.class);
+            try {
+                if (out != null && out.getJmsMessage() != null) {
+                    out.setMessageId(out.getJmsMessage().getJMSMessageID());
+                }
+            } catch (JMSException e) {
+                LOG.warn("Unable to retrieve JMSMessageID from outgoing JMS Message and set it into Camel's MessageId", e);
+            }
+        }
     }
 
-    /**
-     * Gets the synchronous value for this instance of DestinationProducer.
-     */
-    public boolean isSynchronous() {
-        return getEndpoint().isSynchronous();
+    public SjmsTemplate getInOnlyTemplate() {
+        if (inOnlyTemplate == null) {
+            inOnlyTemplate = endpoint.createInOnlyTemplate();
+        }
+        return inOnlyTemplate;
     }
 
-    /**
-     * Gets the replyTo for this instance of DestinationProducer.
-     */
-    public String getReplyTo() {
-        return getEndpoint().getReplyTo();
+    public void setInOnlyTemplate(SjmsTemplate inOnlyTemplate) {
+        this.inOnlyTemplate = inOnlyTemplate;
     }
 
-    /**
-     * Gets the destinationName for this instance of DestinationProducer.
-     */
-    public String getDestinationName() {
-        return getEndpoint().getDestinationName();
+    public SjmsTemplate getInOutTemplate() {
+        if (inOutTemplate == null) {
+            inOutTemplate = endpoint.createInOutTemplate();
+        }
+        return inOutTemplate;
     }
 
-    /**
-     * Test to verify if this endpoint is a JMS Topic or Queue.
-     */
-    public boolean isTopic() {
-        return getEndpoint().isTopic();
+    public void setInOutTemplate(SjmsTemplate inOutTemplate) {
+        this.inOutTemplate = inOutTemplate;
     }
 
-    /**
-     * Test to determine if this endpoint should use a JMS Transaction.
-     */
-    public boolean isEndpointTransacted() {
-        return getEndpoint().isTransacted();
+    public UuidGenerator getUuidGenerator() {
+        return uuidGenerator;
     }
 
-    /**
-     * Test to determine if this endpoint should share a JMS Session with other SJMS endpoints.
-     */
-    public boolean isSharedJMSSession() {
-        return getEndpoint().isSharedJMSSession();
+    public void setUuidGenerator(UuidGenerator uuidGenerator) {
+        this.uuidGenerator = uuidGenerator;
+    }
+
+    protected Destination resolveOrCreateDestination(String destinationName, Session session)
+            throws JMSException {
+
+        boolean isPubSub = isTopicPrefix(destinationName)
+                || (!isQueuePrefix(destinationName) && endpoint.isTopic());
+
+        // must normalize the destination name
+        String before = destinationName;
+        destinationName = normalizeDestinationName(destinationName);
+        LOG.trace("Normalized JMSReplyTo destination name {} -> {}", before, destinationName);
+
+        return endpoint.getDestinationCreationStrategy().createDestination(session, destinationName, isPubSub);
     }
 
     /**
-     * Gets consumerCount for this instance of SjmsProducer.
+     * Strategy to determine which correlation id to use among <tt>JMSMessageID</tt> and <tt>JMSCorrelationID</tt>.
+     *
+     * @param  message      the JMS message
+     * @throws JMSException can be thrown
      */
-    public int getConsumerCount() {
-        return getEndpoint().getConsumerCount();
+    protected String determineCorrelationId(Message message) throws JMSException {
+        String cid = getJMSCorrelationIDAsBytes(message);
+        if (ObjectHelper.isEmpty(cid)) {
+            cid = getJMSMessageID(message);
+        }
+        return cid;
     }
 
     /**
-     * Gets commitStrategy for this instance of SjmsProducer.
+     * Sends the message using the JmsTemplate.
+     *
+     * @param inOut           use inOut or inOnly template
+     * @param destinationName the destination
+     * @param messageCreator  the creator to create the {@link Message} to send
      */
-    protected TransactionCommitStrategy getCommitStrategy() {
-        if (isEndpointTransacted()) {
-            return getEndpoint().getTransactionCommitStrategy();
+    protected void doSend(
+            boolean inOut, String destinationName,
+            MessageCreator messageCreator)
+            throws Exception {
+
+        SjmsTemplate template = inOut ? getInOutTemplate() : getInOnlyTemplate();
+
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Using {} jms template", inOut ? "inOut" : "inOnly");
         }
-        return null;
+
+        template.send(destinationName, messageCreator, getEndpoint().isTopic());
     }
 
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsTemplate.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsTemplate.java
index 902ce6e..f725b16 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsTemplate.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsTemplate.java
@@ -18,17 +18,23 @@ package org.apache.camel.component.sjms;
 
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
 import javax.jms.Message;
 import javax.jms.MessageProducer;
 import javax.jms.Session;
 
+import org.apache.camel.component.sjms.jms.DestinationCreationStrategy;
+import org.apache.camel.component.sjms.jms.MessageCreator;
 import org.apache.camel.util.ObjectHelper;
 
+import static org.apache.camel.component.sjms.SjmsHelper.*;
+
 public class SjmsTemplate {
 
     private final ConnectionFactory connectionFactory;
     private final boolean transacted;
     private final int acknowledgeMode;
+    private DestinationCreationStrategy destinationCreationStrategy;
 
     private boolean explicitQosEnabled;
     private int deliveryMode = Message.DEFAULT_DELIVERY_MODE;
@@ -43,6 +49,14 @@ public class SjmsTemplate {
         this.acknowledgeMode = acknowledgeMode;
     }
 
+    public ConnectionFactory getConnectionFactory() {
+        return connectionFactory;
+    }
+
+    public void setDestinationCreationStrategy(DestinationCreationStrategy destinationCreationStrategy) {
+        this.destinationCreationStrategy = destinationCreationStrategy;
+    }
+
     public void setQoSSettings(int deliveryMode, int priority, long timeToLive) {
         if (deliveryMode != 0) {
             this.deliveryMode = deliveryMode;
@@ -70,8 +84,8 @@ public class SjmsTemplate {
             session = createSession(con);
             return sessionCallback.doInJms(session);
         } finally {
-            close(session);
-            close(con);
+            closeSession(session);
+            closeConnection(con);
         }
     }
 
@@ -83,6 +97,20 @@ public class SjmsTemplate {
         }
     }
 
+    public void send(String destinationName, MessageCreator messageCreator, boolean isTopic) throws Exception {
+        execute(session -> {
+            Destination dest = destinationCreationStrategy.createDestination(session, destinationName, isTopic);
+            Message message = messageCreator.createMessage(session);
+            MessageProducer producer = session.createProducer(dest);
+            try {
+                send(producer, message);
+            } finally {
+                closeProducer(producer);
+            }
+            return null;
+        });
+    }
+
     public void send(MessageProducer producer, Message message) throws Exception {
         if (explicitQosEnabled) {
             producer.send(message, deliveryMode, priority, timeToLive);
@@ -99,23 +127,4 @@ public class SjmsTemplate {
         return connection.createSession(transacted, acknowledgeMode);
     }
 
-    private static void close(Connection con) {
-        if (con != null) {
-            try {
-                con.close();
-            } catch (Throwable e) {
-                // ignore
-            }
-        }
-    }
-
-    private static void close(Session session) {
-        if (session != null) {
-            try {
-                session.close();
-            } catch (Throwable e) {
-                // ignore
-            }
-        }
-    }
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/TransactionOnCompletion.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/TransactionOnCompletion.java
new file mode 100644
index 0000000..3674cde
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/TransactionOnCompletion.java
@@ -0,0 +1,68 @@
+/*
+ * 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.component.sjms;
+
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.support.SynchronizationAdapter;
+
+
+import static org.apache.camel.component.sjms.SjmsHelper.*;
+
+/**
+ * Completion {@link org.apache.camel.spi.Synchronization} work when
+ * processing the message is complete to either commit or rollback the session.
+ */
+class TransactionOnCompletion extends SynchronizationAdapter implements Comparable<TransactionOnCompletion> {
+
+    // TODO: close session, connection
+
+    private final Session session;
+    private final Message message;
+
+    public TransactionOnCompletion(Session session, Message message) {
+        this.session = session;
+        this.message = message;
+    }
+
+    @Override
+    public void onDone(Exchange exchange) {
+        try {
+            if (exchange.isFailed() || exchange.isRollbackOnly()) {
+                rollbackIfNeeded(session);
+            } else {
+                commitIfNeeded(session, message);
+            }
+        } catch (Throwable e) {
+            // ignore
+        } finally {
+            closeSession(session);
+        }
+    }
+
+    @Override
+    public int compareTo(TransactionOnCompletion o) {
+        // same session and message
+        if (session == o.session && message == o.message) {
+            return 0;
+        } else {
+            return -1;
+        }
+    }
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/AbstractMessageHandler.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/AbstractMessageHandler.java
deleted file mode 100644
index 0eecf31..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/AbstractMessageHandler.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.component.sjms.consumer;
-
-import java.util.concurrent.ExecutorService;
-
-import javax.jms.Message;
-import javax.jms.MessageListener;
-import javax.jms.Session;
-
-import org.apache.camel.AsyncProcessor;
-import org.apache.camel.Exchange;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.sjms.SjmsConstants;
-import org.apache.camel.component.sjms.SjmsEndpoint;
-import org.apache.camel.spi.Synchronization;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.camel.RuntimeCamelException.wrapRuntimeCamelException;
-
-/**
- * Abstract MessageListener
- */
-@Deprecated
-public abstract class AbstractMessageHandler implements MessageListener {
-
-    protected final Logger log = LoggerFactory.getLogger(getClass());
-
-    private final ExecutorService executor;
-
-    private SjmsEndpoint endpoint;
-    private AsyncProcessor processor;
-    private Session session;
-    private boolean transacted;
-    private boolean sharedJMSSession;
-    private boolean synchronous = true;
-    private final Synchronization synchronization;
-    private boolean topic;
-
-    public AbstractMessageHandler(SjmsEndpoint endpoint, ExecutorService executor) {
-        this(endpoint, executor, null);
-    }
-
-    public AbstractMessageHandler(SjmsEndpoint endpoint, ExecutorService executor, Synchronization synchronization) {
-        this.synchronization = synchronization;
-        this.endpoint = endpoint;
-        this.executor = executor;
-    }
-
-    @Override
-    public void onMessage(Message message) {
-        RuntimeCamelException rce = null;
-        try {
-            final Exchange exchange = getEndpoint().createExchange(message, getSession());
-
-            log.debug("Processing ExchangeId: {}", exchange.getExchangeId());
-
-            if (isTransacted()) {
-                if (isSharedJMSSession()) {
-                    // Propagate a JMS Session as an initiator if sharedJMSSession is enabled
-                    exchange.getIn().setHeader(SjmsConstants.JMS_SESSION, getSession());
-                }
-            }
-            try {
-                if (isTransacted() || isSynchronous()) {
-                    log.debug("Handling synchronous message: {}", exchange.getIn().getBody());
-                    handleMessage(exchange);
-                    if (exchange.isFailed()) {
-                        synchronization.onFailure(exchange);
-                    } else {
-                        synchronization.onComplete(exchange);
-                    }
-                } else {
-                    log.debug("Handling asynchronous message: {}", exchange.getIn().getBody());
-                    executor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                handleMessage(exchange);
-                            } catch (Exception e) {
-                                exchange.setException(e);
-                            }
-                        }
-                    });
-                }
-            } catch (Exception e) {
-                if (exchange.getException() == null) {
-                    exchange.setException(e);
-                } else {
-                    throw e;
-                }
-            }
-        } catch (Exception e) {
-            rce = wrapRuntimeCamelException(e);
-        } finally {
-            if (rce != null) {
-                throw rce;
-            }
-        }
-    }
-
-    public abstract void handleMessage(Exchange exchange);
-
-    /**
-     * Method will be called to
-     */
-    public abstract void close();
-
-    public void setTransacted(boolean transacted) {
-        this.transacted = transacted;
-    }
-
-    public boolean isTransacted() {
-        return transacted;
-    }
-
-    public void setSharedJMSSession(boolean share) {
-        this.sharedJMSSession = share;
-    }
-
-    public boolean isSharedJMSSession() {
-        return sharedJMSSession;
-    }
-
-    public SjmsEndpoint getEndpoint() {
-        return endpoint;
-    }
-
-    public AsyncProcessor getProcessor() {
-        return processor;
-    }
-
-    public void setProcessor(AsyncProcessor processor) {
-        this.processor = processor;
-    }
-
-    public void setSession(Session session) {
-        this.session = session;
-    }
-
-    public Session getSession() {
-        return session;
-    }
-
-    public void setSynchronous(boolean async) {
-        this.synchronous = async;
-    }
-
-    public boolean isSynchronous() {
-        return synchronous;
-    }
-
-    public void setTopic(boolean topic) {
-        this.topic = topic;
-    }
-
-    public boolean isTopic() {
-        return topic;
-    }
-
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/InOnlyMessageHandler.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/InOnlyMessageHandler.java
deleted file mode 100644
index 0d9db8c..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/InOnlyMessageHandler.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.component.sjms.consumer;
-
-import java.util.concurrent.ExecutorService;
-
-import org.apache.camel.AsyncCallback;
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.SjmsEndpoint;
-import org.apache.camel.spi.Synchronization;
-
-/**
- * An InOnly {@link AbstractMessageHandler}
- */
-@Deprecated
-public class InOnlyMessageHandler extends AbstractMessageHandler {
-
-    public InOnlyMessageHandler(SjmsEndpoint endpoint, ExecutorService executor) {
-        super(endpoint, executor);
-    }
-
-    public InOnlyMessageHandler(SjmsEndpoint endpoint, ExecutorService executor, Synchronization synchronization) {
-        super(endpoint, executor, synchronization);
-    }
-
-    @Override
-    public void handleMessage(final Exchange exchange) {
-        if (log.isDebugEnabled()) {
-            log.debug("Handling InOnly Message: {}", exchange.getIn().getBody());
-        }
-        if (!exchange.isFailed()) {
-            NoOpAsyncCallback callback = new NoOpAsyncCallback();
-            if (isTransacted() || isSynchronous()) {
-                // must process synchronous if transacted or configured to do so
-                if (log.isDebugEnabled()) {
-                    log.debug("Synchronous processing: Message[{}], Destination[{}] ", exchange.getIn().getBody(),
-                            getEndpoint().getEndpointUri());
-                }
-                try {
-                    getProcessor().process(exchange);
-                } catch (Exception e) {
-                    exchange.setException(e);
-                } finally {
-                    callback.done(true);
-                }
-            } else {
-                // process asynchronous using the async routing engine
-                if (log.isDebugEnabled()) {
-                    log.debug("Asynchronous processing: Message[{}], Destination[{}] ", exchange.getIn().getBody(),
-                            getEndpoint().getEndpointUri());
-                }
-
-                getProcessor().process(exchange, callback);
-            }
-        }
-    }
-
-    @Override
-    public void close() {
-        // no-op
-    }
-
-    protected class NoOpAsyncCallback implements AsyncCallback {
-
-        public NoOpAsyncCallback() {
-        }
-
-        @Override
-        public void done(boolean sync) {
-            log.debug("NoOpAsyncCallback InOnly Exchange complete");
-        }
-    }
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/InOutMessageHandler.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/InOutMessageHandler.java
deleted file mode 100644
index d964be1..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/InOutMessageHandler.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.component.sjms.consumer;
-
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Topic;
-
-import org.apache.camel.AsyncCallback;
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.SjmsEndpoint;
-import org.apache.camel.component.sjms.jms.JmsConstants;
-import org.apache.camel.spi.Synchronization;
-
-/**
- * cache manager to store and purge unused cashed producers or we will have a memory leak
- */
-@Deprecated
-public class InOutMessageHandler extends AbstractMessageHandler {
-
-    private Map<String, MessageProducer> producerCache = new TreeMap<>();
-    private ReadWriteLock lock = new ReentrantReadWriteLock();
-
-    public InOutMessageHandler(SjmsEndpoint endpoint, ExecutorService executor) {
-        super(endpoint, executor);
-    }
-
-    public InOutMessageHandler(SjmsEndpoint endpoint, ExecutorService executor, Synchronization synchronization) {
-        super(endpoint, executor, synchronization);
-    }
-
-    @Override
-    public void handleMessage(final Exchange exchange) {
-        try {
-            MessageProducer messageProducer = null;
-            Object obj = exchange.getIn().getHeader(JmsConstants.JMS_REPLY_TO);
-            if (obj != null) {
-                Destination replyTo;
-                if (isDestination(obj)) {
-                    replyTo = (Destination) obj;
-                } else if (obj instanceof String) {
-                    replyTo = getEndpoint().getDestinationCreationStrategy().createDestination(getSession(), (String) obj,
-                            isTopic());
-                } else {
-                    throw new Exception(
-                            "The value of JMSReplyTo must be a valid Destination or String.  Value provided: " + obj);
-                }
-
-                String destinationName = getDestinationName(replyTo);
-                try {
-                    lock.readLock().lock();
-                    if (producerCache.containsKey(destinationName)) {
-                        messageProducer = producerCache.get(destinationName);
-                    }
-                } finally {
-                    lock.readLock().unlock();
-                }
-                if (messageProducer == null) {
-                    try {
-                        lock.writeLock().lock();
-                        messageProducer = getSession().createProducer(replyTo);
-                        producerCache.put(destinationName, messageProducer);
-                    } finally {
-                        lock.writeLock().unlock();
-                    }
-                }
-            }
-
-            MessageHandlerAsyncCallback callback = new MessageHandlerAsyncCallback(exchange, messageProducer);
-            if (exchange.isFailed()) {
-                return;
-            } else {
-                if (isTransacted() || isSynchronous()) {
-                    // must process synchronous if transacted or configured to do so
-                    log.debug("Synchronous processing: Message[{}], Destination[{}] ", exchange.getIn().getBody(),
-                            getEndpoint().getEndpointUri());
-                    try {
-                        getProcessor().process(exchange);
-                    } catch (Exception e) {
-                        exchange.setException(e);
-                    } finally {
-                        callback.done(true);
-                    }
-                } else {
-                    // process asynchronous using the async routing engine
-                    if (log.isDebugEnabled()) {
-                        log.debug("Asynchronous processing: Message[{}], Destination[{}] ", exchange.getIn().getBody(),
-                                getEndpoint().getEndpointUri());
-                    }
-                    getProcessor().process(exchange, callback);
-                }
-            }
-        } catch (Exception e) {
-            exchange.setException(e);
-        }
-
-        if (log.isDebugEnabled()) {
-            log.debug("SjmsMessageConsumer invoked for Exchange id:{}", exchange.getExchangeId());
-        }
-    }
-
-    @Override
-    public void close() {
-        for (final Map.Entry<String, MessageProducer> entry : producerCache.entrySet()) {
-            try {
-                entry.getValue().close();
-            } catch (JMSException e) {
-                log.debug("Cached MessageProducer with key: {} threw an unexpected exception. This exception is ignored.",
-                        entry.getKey(), e);
-            }
-        }
-        producerCache.clear();
-    }
-
-    private boolean isDestination(Object object) {
-        return object instanceof Destination;
-    }
-
-    private String getDestinationName(Destination destination) throws Exception {
-        String answer = null;
-        if (destination instanceof Queue) {
-            answer = ((Queue) destination).getQueueName();
-        } else if (destination instanceof Topic) {
-            answer = ((Topic) destination).getTopicName();
-        }
-
-        return answer;
-    }
-
-    protected class MessageHandlerAsyncCallback implements AsyncCallback {
-
-        private final Exchange exchange;
-        private final MessageProducer localProducer;
-
-        public MessageHandlerAsyncCallback(Exchange exchange, MessageProducer localProducer) {
-            this.exchange = exchange;
-            this.localProducer = localProducer;
-        }
-
-        @Override
-        public void done(boolean sync) {
-            try {
-                org.apache.camel.Message msg = exchange.getMessage();
-                Message response = getEndpoint().getBinding().makeJmsMessage(exchange, msg, getSession(), null);
-                response.setJMSCorrelationID(exchange.getIn().getHeader(JmsConstants.JMS_CORRELATION_ID, String.class));
-                localProducer.send(response);
-            } catch (Exception e) {
-                exchange.setException(e);
-            }
-        }
-    }
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/SimpleMessageListenerContainer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/SimpleMessageListenerContainer.java
index e5ee4b2..c2cb3cb 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/SimpleMessageListenerContainer.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/consumer/SimpleMessageListenerContainer.java
@@ -32,7 +32,7 @@ import javax.jms.Session;
 import org.apache.camel.CamelContext;
 import org.apache.camel.component.sjms.SessionMessageListener;
 import org.apache.camel.component.sjms.SjmsEndpoint;
-import org.apache.camel.component.sjms.SjmsHelper;
+import org.apache.camel.component.sjms.jms.DestinationCreationStrategy;
 import org.apache.camel.support.service.ServiceSupport;
 import org.apache.camel.util.backoff.BackOff;
 import org.apache.camel.util.backoff.BackOffTimer;
@@ -48,10 +48,11 @@ public class SimpleMessageListenerContainer extends ServiceSupport
 
     private final SjmsEndpoint endpoint;
     private SessionMessageListener messageListener;
-
-    // TODO: transaction
-    // TODO: Add concurrency later
+    private String clientId;
     private int concurrentConsumers = 1;
+    private ExceptionListener exceptionListener;
+    private String destinationName;
+    private DestinationCreationStrategy destinationCreationStrategy;
 
     private final Object connectionLock = new Object();
     private Connection connection;
@@ -59,7 +60,6 @@ public class SimpleMessageListenerContainer extends ServiceSupport
     private final Object consumerLock = new Object();
     private Set<MessageConsumer> consumers;
     private Set<Session> sessions;
-
     private BackOffTimer.Task recoverTask;
     private ScheduledExecutorService scheduler;
 
@@ -67,10 +67,50 @@ public class SimpleMessageListenerContainer extends ServiceSupport
         this.endpoint = endpoint;
     }
 
+    public SjmsEndpoint getEndpoint() {
+        return endpoint;
+    }
+
     public void setMessageListener(SessionMessageListener messageListener) {
         this.messageListener = messageListener;
     }
 
+    public void setExceptionListener(ExceptionListener exceptionListener) {
+        this.exceptionListener = exceptionListener;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getDestinationName() {
+        return destinationName;
+    }
+
+    public void setDestinationName(String destinationName) {
+        this.destinationName = destinationName;
+    }
+
+    public DestinationCreationStrategy getDestinationCreationStrategy() {
+        return destinationCreationStrategy;
+    }
+
+    public void setDestinationCreationStrategy(DestinationCreationStrategy destinationCreationStrategy) {
+        this.destinationCreationStrategy = destinationCreationStrategy;
+    }
+
+    public int getConcurrentConsumers() {
+        return concurrentConsumers;
+    }
+
+    public void setConcurrentConsumers(int concurrentConsumers) {
+        this.concurrentConsumers = concurrentConsumers;
+    }
+
     @Override
     public void afterPropertiesConfigured(CamelContext camelContext) {
         // noop
@@ -122,26 +162,17 @@ public class SimpleMessageListenerContainer extends ServiceSupport
             commitIfNeeded(session, message);
         }
 
-        protected void commitIfNeeded(Session session, Message message) throws Exception {
-            if (session.getTransacted()) {
-                SjmsHelper.commitIfNecessary(session);
-            } else if (message != null && session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) {
-                message.acknowledge();
-            }
-        }
-
-        protected void rollbackIfNeeded(Session session) throws JMSException {
-            if (session.getTransacted()) {
-                SjmsHelper.rollbackIfNecessary(session);
-            } else if (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) {
-                session.recover();
-            }
-        }
-
     }
 
     @Override
     public void onException(JMSException exception) {
+        if (exceptionListener != null) {
+            try {
+                exceptionListener.onException(exception);
+            } catch (Throwable e) {
+                // ignore
+            }
+        }
         if (endpoint.getExceptionListener() != null) {
             try {
                 endpoint.getExceptionListener().onException(exception);
@@ -211,12 +242,14 @@ public class SimpleMessageListenerContainer extends ServiceSupport
     protected void initConsumers() throws Exception {
         synchronized (this.consumerLock) {
             if (consumers == null) {
+                LOG.debug("Initializing {} concurrent consumers as JMS listener on destination: {}", concurrentConsumers,
+                        destinationName);
                 sessions = new HashSet<>(concurrentConsumers);
                 consumers = new HashSet<>(concurrentConsumers);
                 for (int i = 0; i < this.concurrentConsumers; i++) {
                     Session session
                             = connection.createSession(endpoint.isTransacted(), endpoint.getAcknowledgementMode().intValue());
-                    MessageConsumer consumer = endpoint.getJmsObjectFactory().createMessageConsumer(session, endpoint);
+                    MessageConsumer consumer = createMessageConsumer(session);
                     configureConsumer(consumer, session);
                     sessions.add(session);
                     consumers.add(consumer);
@@ -225,6 +258,10 @@ public class SimpleMessageListenerContainer extends ServiceSupport
         }
     }
 
+    protected MessageConsumer createMessageConsumer(Session session) throws Exception {
+        return endpoint.getJmsObjectFactory().createMessageConsumer(session, endpoint);
+    }
+
     protected void stopConsumers() throws Exception {
         synchronized (this.consumerLock) {
             if (consumers != null) {
@@ -248,8 +285,9 @@ public class SimpleMessageListenerContainer extends ServiceSupport
                 Connection con = null;
                 try {
                     con = endpoint.getConnectionFactory().createConnection();
-                    if (endpoint.getComponent().getConnectionClientId() != null) {
-                        con.setClientID(endpoint.getComponent().getConnectionClientId());
+                    String cid = clientId != null ? clientId : endpoint.getComponent().getClientId();
+                    if (cid != null) {
+                        con.setClientID(cid);
                     }
                     con.setExceptionListener(this);
                 } catch (JMSException e) {
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionFactoryResource.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionFactoryResource.java
deleted file mode 100644
index 043b708..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionFactoryResource.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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.component.sjms.jms;
-
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.ExceptionListener;
-
-import org.apache.camel.util.ObjectHelper;
-import org.apache.commons.pool.BasePoolableObjectFactory;
-import org.apache.commons.pool.impl.GenericObjectPool;
-
-/**
- * The default {@link ConnectionResource} implementation for the SJMSComponent.
- */
-@Deprecated
-public class ConnectionFactoryResource extends BasePoolableObjectFactory<Connection> implements ConnectionResource {
-
-    private static final long DEFAULT_WAIT_TIMEOUT = 5 * 1000;
-    private static final int DEFAULT_POOL_SIZE = 1;
-    private GenericObjectPool<Connection> connections;
-    private ConnectionFactory connectionFactory;
-    private String username;
-    private String password;
-    private String clientId;
-    private ExceptionListener exceptionListener;
-
-    /**
-     * Default Constructor
-     */
-    public ConnectionFactoryResource() {
-        this(DEFAULT_POOL_SIZE, null);
-    }
-
-    public ConnectionFactoryResource(int poolSize, ConnectionFactory connectionFactory) {
-        this(poolSize, connectionFactory, null, null);
-    }
-
-    public ConnectionFactoryResource(int poolSize, ConnectionFactory connectionFactory, String username, String password) {
-        this(poolSize, connectionFactory, username, password, null);
-    }
-
-    public ConnectionFactoryResource(int poolSize, ConnectionFactory connectionFactory, String username, String password,
-                                     String connectionId) {
-        this(poolSize, connectionFactory, username, password, connectionId, DEFAULT_WAIT_TIMEOUT);
-    }
-
-    public ConnectionFactoryResource(int poolSize, ConnectionFactory connectionFactory, String username, String password,
-                                     String connectionId, long maxWait) {
-        this(poolSize, connectionFactory, username, password, connectionId, DEFAULT_WAIT_TIMEOUT, true);
-    }
-
-    public ConnectionFactoryResource(int poolSize, ConnectionFactory connectionFactory, String username, String password,
-                                     String connectionId,
-                                     long maxWait, boolean testOnBorrow) {
-        this.connectionFactory = connectionFactory;
-        this.username = username;
-        this.password = password;
-        this.clientId = connectionId;
-        this.connections = new GenericObjectPool<>(this);
-        this.connections.setMaxWait(maxWait);
-        this.connections.setMaxActive(poolSize);
-        this.connections.setMaxIdle(poolSize);
-        this.connections.setMinIdle(poolSize);
-        this.connections.setLifo(false);
-        this.connections.setTestOnBorrow(testOnBorrow);
-    }
-
-    @Override
-    public boolean validateObject(Connection connection) {
-        try {
-            // ensure connection works so we need to start it
-            connection.start();
-            return true;
-        } catch (Throwable e) {
-            // ignore
-        }
-
-        return false;
-    }
-
-    @Override
-    public Connection borrowConnection() throws Exception {
-        return connections.borrowObject();
-    }
-
-    @Override
-    public void returnConnection(Connection connection) throws Exception {
-        connections.returnObject(connection);
-    }
-
-    @Override
-    public Connection makeObject() throws Exception {
-        Connection connection = null;
-        if (connectionFactory != null) {
-            if (getUsername() != null && getPassword() != null) {
-                connection = connectionFactory.createConnection(getUsername(), getPassword());
-            } else {
-                connection = connectionFactory.createConnection();
-            }
-        }
-        if (connection != null) {
-            if (ObjectHelper.isNotEmpty(getClientId())) {
-                connection.setClientID(getClientId());
-            }
-            // we want to listen for exceptions
-            if (exceptionListener != null) {
-                connection.setExceptionListener(exceptionListener);
-            }
-            connection.start();
-        }
-        return connection;
-    }
-
-    @Override
-    public void destroyObject(Connection connection) throws Exception {
-        if (connection != null) {
-            connection.stop();
-            connection.close();
-        }
-    }
-
-    public ConnectionFactory getConnectionFactory() {
-        return connectionFactory;
-    }
-
-    public void setConnectionFactory(ConnectionFactory connectionFactory) {
-        this.connectionFactory = connectionFactory;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
-    public ExceptionListener getExceptionListener() {
-        return exceptionListener;
-    }
-
-    public void setExceptionListener(ExceptionListener exceptionListener) {
-        this.exceptionListener = exceptionListener;
-    }
-
-    public int size() {
-        return connections.getNumActive() + connections.getNumIdle();
-    }
-
-    public void fillPool() throws Exception {
-        while (connections.getNumIdle() < connections.getMaxIdle()) {
-            connections.addObject();
-        }
-    }
-
-    public void drainPool() throws Exception {
-        connections.close();
-    }
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionResource.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionResource.java
deleted file mode 100644
index 9b63ef9..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionResource.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.component.sjms.jms;
-
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-
-/**
- * <p>
- * The ConnectionResource is the contract used to provide {@link Connection} pools to the SJMS component. A user should
- * use this to provide access to an alternative pooled connection resource such as a {@link Connection} pool that is
- * managed by a J2EE container.
- * </p>
- * <p>
- * It is recommended though that for standard {@link ConnectionFactory} providers you use the
- * {@link ConnectionFactoryResource) implementation that is provided with SJMS as it is optimized for this component.
- * </p>
- */
-@Deprecated
-public interface ConnectionResource {
-
-    /**
-     * Borrows a {@link Connection} from the connection pool. An exception should be thrown if no resource is available.
-     *
-     * @return           {@link Connection}
-     * @throws Exception when no resource is available
-     */
-    Connection borrowConnection() throws Exception;
-
-    /**
-     * Returns the {@link Connection} to the connection pool.
-     *
-     * @param connection the borrowed {@link Connection}
-     */
-    void returnConnection(Connection connection) throws Exception;
-
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/Jms11ObjectFactory.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/Jms11ObjectFactory.java
index 699db13..3bc7d69 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/Jms11ObjectFactory.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/Jms11ObjectFactory.java
@@ -43,6 +43,11 @@ public class Jms11ObjectFactory implements JmsObjectFactory {
     }
 
     @Override
+    public MessageConsumer createQueueMessageConsumer(Session session, Destination destination) throws Exception {
+        return createMessageConsumer(session, destination, null, false, null, false, false);
+    }
+
+    @Override
     public MessageConsumer createMessageConsumer(
             Session session,
             Destination destination,
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/JmsObjectFactory.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/JmsObjectFactory.java
index 056f676..014b478 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/JmsObjectFactory.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/JmsObjectFactory.java
@@ -26,6 +26,8 @@ import org.apache.camel.Endpoint;
 public interface JmsObjectFactory {
     MessageConsumer createMessageConsumer(Session session, Endpoint endpoint) throws Exception;
 
+    MessageConsumer createQueueMessageConsumer(Session session, Destination destination) throws Exception;
+
     MessageConsumer createMessageConsumer(
             Session session, Destination destination,
             String messageSelector, boolean topic, String subscriptionId, boolean durable,
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageListenerContainer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/MessageCreator.java
similarity index 68%
copy from components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageListenerContainer.java
copy to components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/MessageCreator.java
index e85772a..63cd955 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/MessageListenerContainer.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/MessageCreator.java
@@ -14,17 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.sjms;
+package org.apache.camel.component.sjms.jms;
 
-import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
 
-import org.apache.camel.AfterPropertiesConfigured;
-import org.apache.camel.Service;
+@FunctionalInterface
+public interface MessageCreator {
 
-public interface MessageListenerContainer extends Service, AfterPropertiesConfigured {
-
-    ConnectionFactory getConnectionFactory();
-
-    void setMessageListener(SessionMessageListener messageListener);
+    Message createMessage(Session session) throws JMSException;
 
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/producer/InOnlyProducer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/producer/InOnlyProducer.java
deleted file mode 100644
index b21ce9e..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/producer/InOnlyProducer.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.component.sjms.producer;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-
-import org.apache.camel.CamelExchangeException;
-import org.apache.camel.Endpoint;
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.SjmsProducer;
-import org.apache.camel.component.sjms.TransactionCommitStrategy;
-import org.apache.camel.component.sjms.jms.JmsMessageHelper;
-import org.apache.camel.component.sjms.tx.DefaultTransactionCommitStrategy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.camel.component.sjms.SjmsHelper.closeProducer;
-import static org.apache.camel.component.sjms.jms.JmsMessageHelper.isTopicPrefix;
-
-/**
- * A Camel Producer that provides the InOnly Exchange pattern.
- */
-public class InOnlyProducer extends SjmsProducer {
-
-    private static final Logger LOG = LoggerFactory.getLogger(InOnlyProducer.class);
-
-    public InOnlyProducer(final Endpoint endpoint) {
-        super(endpoint);
-    }
-
-    @Override
-    protected TransactionCommitStrategy getCommitStrategy() {
-        if (isEndpointTransacted()) {
-            return super.getCommitStrategy() == null ? new DefaultTransactionCommitStrategy() : super.getCommitStrategy();
-        }
-        return null;
-    }
-
-    @Override
-    protected void sendMessage(Exchange exchange, Session session, String destinationName) {
-        try {
-            template.execute(session, sc -> {
-                MessageProducer producer = null;
-                try {
-                    Message answer = getEndpoint().getBinding().makeJmsMessage(exchange, sc);
-
-                    // when in InOnly mode the JMSReplyTo is a bit complicated
-                    // we only want to set the JMSReplyTo on the answer if
-                    // there is a JMSReplyTo from the header/endpoint and
-                    // we have been told to preserveMessageQos
-
-                    Object jmsReplyTo = JmsMessageHelper.getJMSReplyTo(answer);
-                    if (getEndpoint().isDisableReplyTo()) {
-                        // honor disable reply to configuration
-                        LOG.trace("ReplyTo is disabled on endpoint: {}", getEndpoint());
-                        JmsMessageHelper.setJMSReplyTo(answer, null);
-                    } else {
-                        // if the binding did not create the reply to then we have to try to create it here
-                        if (jmsReplyTo == null) {
-                            // prefer reply to from header over endpoint configured
-                            jmsReplyTo = exchange.getIn().getHeader("JMSReplyTo", String.class);
-                            if (jmsReplyTo == null) {
-                                jmsReplyTo = getEndpoint().getReplyTo();
-                            }
-                        }
-                    }
-
-                    // we must honor these special flags to preserve QoS
-                    // as we are not OUT capable and thus do not expect a reply, and therefore
-                    // the consumer of this message should not return a reply so we remove it
-                    // unless we use preserveMessageQos=true to tell that we still want to use JMSReplyTo
-                    if (jmsReplyTo != null && !(getEndpoint().isPreserveMessageQos() || getEndpoint().isExplicitQosEnabled())) {
-                        // log at debug what we are doing, as higher level may cause noise in production logs
-                        // this behavior is also documented at the camel website
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug(
-                                    "Disabling JMSReplyTo: {} for destination: {}. Use preserveMessageQos=true to force Camel to keep the JMSReplyTo on endpoint: {}",
-                                    new Object[] { jmsReplyTo, destinationName, getEndpoint() });
-                        }
-                        jmsReplyTo = null;
-                    }
-
-                    // the reply to is a String, so we need to look up its Destination instance
-                    // and if needed create the destination using the session if needed to
-                    if (jmsReplyTo instanceof String) {
-                        String replyTo = (String) jmsReplyTo;
-                        // we need to null it as we use the String to resolve it as a Destination instance
-                        jmsReplyTo = resolveOrCreateDestination(replyTo, sc);
-                    }
-
-                    // set the JMSReplyTo on the answer if we are to use it
-                    Destination replyTo = null;
-                    String replyToOverride = getEndpoint().getReplyToOverride();
-                    if (replyToOverride != null) {
-                        replyTo = resolveOrCreateDestination(replyToOverride, sc);
-                    } else if (jmsReplyTo instanceof Destination) {
-                        replyTo = (Destination) jmsReplyTo;
-                    }
-                    if (replyTo != null) {
-                        LOG.debug("Using JMSReplyTo destination: {}", replyTo);
-                        JmsMessageHelper.setJMSReplyTo(answer, replyTo);
-                    } else {
-                        // do not use JMSReplyTo
-                        LOG.trace("Not using JMSReplyTo");
-                        JmsMessageHelper.setJMSReplyTo(answer, null);
-                    }
-
-                    producer = getEndpoint().getJmsObjectFactory().createMessageProducer(sc, getEndpoint(), destinationName);
-                    template.send(producer, answer);
-                } finally {
-                    closeProducer(producer);
-                }
-                return null;
-            });
-        } catch (Exception e) {
-            exchange.setException(new CamelExchangeException("Unable to complete sending the JMS message", exchange, e));
-        }
-    }
-
-    protected Destination resolveOrCreateDestination(String destinationName, Session session)
-            throws JMSException {
-        boolean isPubSub = isTopicPrefix(destinationName)
-                || (!JmsMessageHelper.isQueuePrefix(destinationName) && getEndpoint().isTopic());
-        return getEndpoint().getDestinationCreationStrategy().createDestination(session, destinationName, isPubSub);
-    }
-
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/producer/InOutProducer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/producer/InOutProducer.java
deleted file mode 100644
index 426ae90..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/producer/InOutProducer.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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.component.sjms.producer;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Exchanger;
-import java.util.concurrent.TimeUnit;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-
-import org.apache.camel.CamelException;
-import org.apache.camel.CamelExchangeException;
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.MessageConsumerResources;
-import org.apache.camel.component.sjms.SjmsConstants;
-import org.apache.camel.component.sjms.SjmsEndpoint;
-import org.apache.camel.component.sjms.SjmsMessage;
-import org.apache.camel.component.sjms.SjmsProducer;
-import org.apache.camel.component.sjms.jms.ConnectionResource;
-import org.apache.camel.component.sjms.jms.DestinationNameParser;
-import org.apache.camel.component.sjms.jms.JmsConstants;
-import org.apache.camel.component.sjms.jms.JmsMessageHelper;
-import org.apache.camel.spi.UuidGenerator;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.commons.pool.BasePoolableObjectFactory;
-import org.apache.commons.pool.impl.GenericObjectPool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.camel.component.sjms.SjmsHelper.closeProducer;
-
-/**
- * A Camel Producer that provides the InOut Exchange pattern.
- */
-public class InOutProducer extends SjmsProducer {
-
-    // TODO: reply manager
-
-    private static final Logger LOG = LoggerFactory.getLogger(InOutProducer.class);
-
-    private static final Map<String, Exchanger<Object>> EXCHANGERS = new ConcurrentHashMap<>();
-
-    private static final String GENERATED_CORRELATION_ID_PREFIX = "Camel-";
-    private UuidGenerator uuidGenerator;
-    private GenericObjectPool<MessageConsumerResources> consumers;
-
-    public InOutProducer(final SjmsEndpoint endpoint) {
-        super(endpoint);
-    }
-
-    public UuidGenerator getUuidGenerator() {
-        return uuidGenerator;
-    }
-
-    public void setUuidGenerator(UuidGenerator uuidGenerator) {
-        this.uuidGenerator = uuidGenerator;
-    }
-
-    @Deprecated
-    protected ConnectionResource getOrCreateConnectionResource() {
-        ConnectionResource answer = getEndpoint().getConnectionResource();
-        if (answer == null) {
-            answer = getEndpoint().createConnectionResource(this);
-        }
-        return answer;
-    }
-
-    /**
-     * A pool of {@link MessageConsumerResources} objects that are the reply consumers.
-     */
-    @Deprecated
-    protected class MessageConsumerResourcesFactory extends BasePoolableObjectFactory<MessageConsumerResources> {
-
-        @Override
-        public MessageConsumerResources makeObject() throws Exception {
-            MessageConsumerResources answer;
-            ConnectionResource connectionResource = getOrCreateConnectionResource();
-            Connection conn = connectionResource.borrowConnection();
-            try {
-                Session session;
-                if (isEndpointTransacted()) {
-                    session = conn.createSession(true, Session.SESSION_TRANSACTED);
-                } else {
-                    session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-                }
-
-                Destination replyToDestination;
-                boolean isReplyToTopic;
-                if (ObjectHelper.isEmpty(getReplyTo())) {
-                    isReplyToTopic = isTopic();
-                    replyToDestination = getEndpoint().getDestinationCreationStrategy().createTemporaryDestination(session,
-                            isReplyToTopic);
-                } else {
-                    isReplyToTopic = DestinationNameParser.isReplyToTopic(getReplyTo(), isTopic());
-                    replyToDestination = getEndpoint().getDestinationCreationStrategy().createDestination(session,
-                            getReplyTo(), isReplyToTopic);
-                }
-                MessageConsumer messageConsumer = getEndpoint().getJmsObjectFactory().createMessageConsumer(session,
-                        replyToDestination, null, isReplyToTopic, null, true, false, false);
-                messageConsumer.setMessageListener(new MessageListener() {
-                    @Override
-                    public void onMessage(final Message message) {
-                        LOG.debug("Message Received in the Consumer Pool");
-                        LOG.debug("  Message : {}", message);
-                        try {
-                            String correlationID = message.getJMSCorrelationID();
-                            Exchanger<Object> exchanger = EXCHANGERS.get(correlationID);
-                            if (exchanger != null) {
-                                exchanger.exchange(message, getEndpoint().getRequestTimeout(), TimeUnit.MILLISECONDS);
-                            } else {
-                                // we could not correlate the received reply message to a matching request and therefore
-                                // we cannot continue routing the unknown message
-                                // log a warn and then ignore the message
-                                LOG.warn(
-                                        "Reply received for unknown correlationID [{}] on reply destination [{}]. Current correlation map size: {}. The message will be ignored: {}",
-                                        correlationID, replyToDestination, EXCHANGERS.size(), message);
-                            }
-                        } catch (Exception e) {
-                            LOG.warn("Unable to match correlated exchange message: {}. This exception is ignored.", message, e);
-                        }
-                    }
-                });
-                answer = new MessageConsumerResources(session, messageConsumer, replyToDestination);
-            } catch (Exception e) {
-                LOG.error("Unable to create the MessageConsumerResource: {}", e.getMessage());
-                throw new CamelException(e);
-            } finally {
-                connectionResource.returnConnection(conn);
-            }
-            return answer;
-        }
-
-        @Override
-        public boolean validateObject(MessageConsumerResources obj) {
-            try {
-                obj.getSession().getAcknowledgeMode();
-                return true;
-            } catch (JMSException ex) {
-                LOG.debug("Cannot validate session. This exception is ignored.", ex);
-            }
-            return false;
-        }
-
-        @Override
-        public void destroyObject(MessageConsumerResources model) throws Exception {
-            if (model.getMessageConsumer() != null) {
-                model.getMessageConsumer().close();
-            }
-
-            if (model.getSession() != null) {
-                if (model.getSession().getTransacted()) {
-                    try {
-                        model.getSession().rollback();
-                    } catch (Exception e) {
-                        // Do nothing. Just make sure we are cleaned up
-                    }
-                }
-                model.getSession().close();
-            }
-        }
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        if (isEndpointTransacted()) {
-            throw new IllegalArgumentException(
-                    "InOut exchange pattern is incompatible with transacted=true as it cause a deadlock. Please use transacted=false or InOnly exchange pattern.");
-        }
-
-        if (ObjectHelper.isEmpty(getReplyTo())) {
-            LOG.debug("No reply to destination is defined. Using temporary destinations.");
-        } else {
-            LOG.debug("Using {} as the reply to destination.", getReplyTo());
-        }
-        if (uuidGenerator == null) {
-            // use the generator configured on the camel context
-            uuidGenerator = getEndpoint().getCamelContext().getUuidGenerator();
-        }
-        if (consumers == null) {
-            consumers = new GenericObjectPool<>(new MessageConsumerResourcesFactory());
-            consumers.setMaxActive(getConsumerCount());
-            consumers.setMaxIdle(getConsumerCount());
-            consumers.setTestOnBorrow(getEndpoint().getComponent().isConnectionTestOnBorrow());
-            while (consumers.getNumIdle() < consumers.getMaxIdle()) {
-                consumers.addObject();
-            }
-        }
-        super.doStart();
-    }
-
-    @Override
-    protected void doStop() throws Exception {
-        super.doStop();
-        if (consumers != null) {
-            try {
-                consumers.close();
-            } catch (Exception e) {
-                // ignore
-            }
-            consumers = null;
-        }
-    }
-
-    @Override
-    protected void sendMessage(Exchange exchange, Session session, String destinationName) {
-        try {
-            template.execute(session, sc -> {
-                MessageProducer producer = null;
-                try {
-                    Message request = getEndpoint().getBinding().makeJmsMessage(exchange, sc);
-
-                    String correlationId = exchange.getIn().getHeader(JmsConstants.JMS_CORRELATION_ID, String.class);
-                    if (correlationId == null) {
-                        // we append the 'Camel-' prefix to know it was generated by us
-                        correlationId = GENERATED_CORRELATION_ID_PREFIX + getUuidGenerator().generateUuid();
-                    }
-
-                    // the request timeout can be overruled by a header otherwise the endpoint configured value is used
-                    final long timeout
-                            = exchange.getIn().getHeader(SjmsConstants.JMS_REQUEST_TIMEOUT, getEndpoint().getRequestTimeout(),
-                                    long.class);
-
-                    Object responseObject = null;
-                    Exchanger<Object> messageExchanger = new Exchanger<>();
-                    JmsMessageHelper.setCorrelationId(request, correlationId);
-                    EXCHANGERS.put(correlationId, messageExchanger);
-
-                    MessageConsumerResources consumer = consumers.borrowObject();
-                    JmsMessageHelper.setJMSReplyTo(request, consumer.getReplyToDestination());
-                    consumers.returnObject(consumer);
-
-                    producer = getEndpoint().getJmsObjectFactory().createMessageProducer(sc, getEndpoint(), destinationName);
-                    template.send(producer, request);
-
-                    try {
-                        responseObject = messageExchanger.exchange(null, timeout, TimeUnit.MILLISECONDS);
-                        EXCHANGERS.remove(correlationId);
-                    } catch (Throwable e) {
-                        exchange.setException(e);
-                    }
-
-                    if (exchange.getException() == null) {
-                        if (responseObject instanceof Throwable) {
-                            exchange.setException((Throwable) responseObject);
-                        } else if (responseObject instanceof Message) {
-                            Message message = (Message) responseObject;
-
-                            SjmsMessage response
-                                    = new SjmsMessage(exchange, message, consumer.getSession(), getEndpoint().getBinding());
-                            // the JmsBinding is designed to be "pull-based": it will populate the Camel message on demand
-                            // therefore, we link Exchange and OUT message before continuing, so that the JmsBinding has full access
-                            // to everything it may need, and can populate headers, properties, etc. accordingly (solves CAMEL-6218).
-                            exchange.setOut(response);
-                        } else {
-                            exchange.setException(new CamelException("Unknown response type: " + responseObject));
-                        }
-                    }
-
-                } finally {
-                    closeProducer(producer);
-                }
-                return null;
-            });
-        } catch (Exception e) {
-            exchange.setException(new CamelExchangeException("Unable to complete sending the JMS message", exchange, e));
-        }
-    }
-
-}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/CorrelationTimeoutMap.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/CorrelationTimeoutMap.java
new file mode 100644
index 0000000..584c2c3
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/CorrelationTimeoutMap.java
@@ -0,0 +1,70 @@
+/*
+ * 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.component.sjms.reply;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.function.BiConsumer;
+
+import org.apache.camel.support.DefaultTimeoutMap;
+
+import static org.apache.camel.TimeoutMap.Listener.Type.*;
+
+/**
+ * A {@link org.apache.camel.TimeoutMap} which is used to track reply messages which has been timed out, and thus should
+ * trigger the waiting {@link org.apache.camel.Exchange} to timeout as well. Zero (or negative) timeout means infinite
+ * but is actually encoded as {@link Integer#MAX_VALUE} which is 24 days.
+ */
+class CorrelationTimeoutMap extends DefaultTimeoutMap<String, ReplyHandler> {
+
+    private final BiConsumer<ReplyHandler, String> evictionTask;
+
+    CorrelationTimeoutMap(ScheduledExecutorService executor, long requestMapPollTimeMillis, ExecutorService executorService) {
+        super(executor, requestMapPollTimeMillis);
+        // Support synchronous or asynchronous handling of evictions
+        evictionTask = executorService == null
+                ? ReplyHandler::onTimeout
+                : (handler, key) -> executorService.submit(() -> handler.onTimeout(key));
+        addListener(this::listener);
+    }
+
+    private static long encode(long timeoutMillis) {
+        return timeoutMillis > 0 ? timeoutMillis : Integer.MAX_VALUE; // TODO why not Long.MAX_VALUE!
+    }
+
+    private void listener(Listener.Type type, String key, ReplyHandler handler) {
+        if (type == Put) {
+            log.trace("Added correlationID: {}", key);
+        } else if (type == Remove) {
+            log.trace("Removed correlationID: {}", key);
+        } else if (type == Evict) {
+            evictionTask.accept(handler, key);
+            log.trace("Evicted correlationID: {}", key);
+        }
+    }
+
+    @Override
+    public ReplyHandler put(String key, ReplyHandler value, long timeoutMillis) {
+        return super.put(key, value, encode(timeoutMillis));
+    }
+
+    @Override
+    public ReplyHandler putIfAbsent(String key, ReplyHandler value, long timeoutMillis) {
+        return super.putIfAbsent(key, value, encode(timeoutMillis));
+    }
+
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ExclusiveQueueMessageListenerContainer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ExclusiveQueueMessageListenerContainer.java
new file mode 100644
index 0000000..1c416fc
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ExclusiveQueueMessageListenerContainer.java
@@ -0,0 +1,48 @@
+/*
+ * 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.component.sjms.reply;
+
+import javax.jms.Destination;
+import javax.jms.MessageConsumer;
+import javax.jms.Session;
+
+import org.apache.camel.component.sjms.MessageListenerContainer;
+import org.apache.camel.component.sjms.SjmsEndpoint;
+import org.apache.camel.component.sjms.consumer.SimpleMessageListenerContainer;
+
+/**
+ * This {@link MessageListenerContainer} is used for reply queues which are exclusive.
+ * <p/>
+ * Mind that exclusive reply queues is per producer, so if you run in a clustered environment then each producer should
+ * use an unique reply queue destination name. If not then other nodes may steal reply messages which was intended for
+ * another. For clustered environments it may be safer to use shared queues as each node will only consume reply
+ * messages which are intended for itself.
+ */
+public class ExclusiveQueueMessageListenerContainer extends SimpleMessageListenerContainer {
+
+    // no need to override any methods currently
+
+    public ExclusiveQueueMessageListenerContainer(SjmsEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    protected MessageConsumer createMessageConsumer(Session session) throws Exception {
+        Destination destination = getDestinationCreationStrategy().createDestination(session, getDestinationName(), false);
+        return getEndpoint().getJmsObjectFactory().createQueueMessageConsumer(session, destination);
+    }
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/MessageSelectorCreator.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/MessageSelectorCreator.java
new file mode 100644
index 0000000..669476a
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/MessageSelectorCreator.java
@@ -0,0 +1,86 @@
+/*
+ * 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.component.sjms.reply;
+
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.apache.camel.TimeoutMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.camel.TimeoutMap.Listener.Type.*;
+
+/**
+ * A creator which can build the JMS message selector query string to use with a shared reply-to queue, so we can select
+ * the correct messages we expect as replies.
+ */
+public class MessageSelectorCreator {
+    protected static final Logger LOG = LoggerFactory.getLogger(MessageSelectorCreator.class);
+    protected final TimeoutMap<String, ?> timeoutMap;
+    protected final ConcurrentSkipListSet<String> correlationIds;
+    protected volatile boolean dirty = true;
+    protected StringBuilder expression;
+
+    public MessageSelectorCreator(CorrelationTimeoutMap timeoutMap) {
+        this.timeoutMap = timeoutMap;
+        this.timeoutMap.addListener((type, cid, value) -> timeoutEvent(type, cid));
+        // create local set of correlation ids, as its easier to keep track
+        // using the listener so we can flag the dirty flag upon changes
+        // must support concurrent access
+        this.correlationIds = new ConcurrentSkipListSet<>();
+    }
+
+    public synchronized String get() {
+        if (!dirty) {
+            return expression.toString();
+        }
+
+        expression = new StringBuilder("JMSCorrelationID='");
+
+        if (correlationIds.size() == 0) {
+            // no id's so use a dummy to select nothing
+            expression.append("CamelDummyJmsMessageSelector'");
+        } else {
+            boolean first = true;
+            for (String value : correlationIds) {
+                if (!first) {
+                    expression.append(" OR JMSCorrelationID='");
+                }
+                expression.append(value).append("'");
+                if (first) {
+                    first = false;
+                }
+            }
+        }
+
+        String answer = expression.toString();
+
+        dirty = false;
+        return answer;
+    }
+
+    // Changes to live correlation-ids invalidate existing message selector
+    private void timeoutEvent(TimeoutMap.Listener.Type type, String cid) {
+        if (type == Put) {
+            correlationIds.add(cid);
+        } else if (type == Remove || type == Evict) {
+            correlationIds.remove(cid);
+        }
+        dirty = true;
+    }
+
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/QueueReplyHandler.java
similarity index 61%
copy from components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java
copy to components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/QueueReplyHandler.java
index a6fbfac..b0c5eee 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/QueueReplyHandler.java
@@ -14,23 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.sjms.tx;
+package org.apache.camel.component.sjms.reply;
 
+import org.apache.camel.AsyncCallback;
 import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.TransactionCommitStrategy;
 
 /**
- * The default commit strategy for all transaction.
+ * {@link ReplyHandler} to handle processing replies when using regular queues.
  */
-public class DefaultTransactionCommitStrategy implements TransactionCommitStrategy {
+public class QueueReplyHandler extends TemporaryQueueReplyHandler {
 
-    @Override
-    public boolean commit(Exchange exchange) throws Exception {
-        return true;
+    public QueueReplyHandler(ReplyManager replyManager, Exchange exchange, AsyncCallback callback,
+                             String originalCorrelationId, String correlationId, long timeout) {
+        super(replyManager, exchange, callback, originalCorrelationId, correlationId, timeout);
     }
 
-    @Override
-    public boolean rollback(Exchange exchange) throws Exception {
-        return true;
-    }
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/QueueReplyManager.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/QueueReplyManager.java
new file mode 100644
index 0000000..30ee6ee
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/QueueReplyManager.java
@@ -0,0 +1,142 @@
+/*
+ * 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.component.sjms.reply;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.sjms.MessageListenerContainer;
+import org.apache.camel.component.sjms.ReplyToType;
+import org.apache.camel.component.sjms.consumer.SimpleMessageListenerContainer;
+import org.apache.camel.component.sjms.jms.DestinationCreationStrategy;
+
+/**
+ * A {@link ReplyManager} when using regular queues.
+ */
+public class QueueReplyManager extends ReplyManagerSupport {
+
+    public QueueReplyManager(CamelContext camelContext) {
+        super(camelContext);
+    }
+
+    @Override
+    protected ReplyHandler createReplyHandler(
+            ReplyManager replyManager, Exchange exchange, AsyncCallback callback,
+            String originalCorrelationId, String correlationId, long requestTimeout) {
+        return new QueueReplyHandler(
+                replyManager, exchange, callback,
+                originalCorrelationId, correlationId, requestTimeout);
+    }
+
+    @Override
+    public void setReplyToSelectorHeader(org.apache.camel.Message camelMessage, Message jmsMessage) throws JMSException {
+        // noop
+    }
+
+    @Override
+    public void updateCorrelationId(String correlationId, String newCorrelationId, long requestTimeout) {
+        log.trace("Updated provisional correlationId [{}] to expected correlationId [{}]", correlationId, newCorrelationId);
+
+        ReplyHandler handler = correlation.remove(correlationId);
+        if (handler == null) {
+            // should not happen that we can't find the handler
+            return;
+        }
+
+        correlation.put(newCorrelationId, handler, requestTimeout);
+    }
+
+    @Override
+    protected void handleReplyMessage(String correlationID, Message message, Session session) {
+        ReplyHandler handler = correlation.get(correlationID);
+
+        if (handler != null) {
+            correlation.remove(correlationID);
+            handler.onReply(correlationID, message, session);
+        } else {
+            // we could not correlate the received reply message to a matching request and therefore
+            // we cannot continue routing the unknown message
+            // log a warn and then ignore the message
+            log.warn(
+                    "Reply received for unknown correlationID [{}] on reply destination [{}]. Current correlation map size: {}. The message will be ignored: {}",
+                    correlationID, replyTo, correlation.size(), message);
+        }
+    }
+
+    private final class DestinationResolverDelegate implements DestinationCreationStrategy {
+        private final DestinationCreationStrategy delegate;
+        private Destination destination;
+
+        DestinationResolverDelegate(DestinationCreationStrategy delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public Destination createDestination(Session session, String destinationName, boolean topic) throws JMSException {
+            synchronized (QueueReplyManager.this) {
+                // resolve the reply to destination
+                if (destination == null) {
+                    destination = delegate.createDestination(session, destinationName, topic);
+                    setReplyTo(destination);
+                }
+            }
+            return destination;
+        }
+
+        @Override
+        public Destination createTemporaryDestination(Session session, boolean topic) throws JMSException {
+            return null;
+        }
+    }
+
+    @Override
+    protected MessageListenerContainer createListenerContainer() throws Exception {
+        SimpleMessageListenerContainer answer;
+
+        ReplyToType type = endpoint.getReplyToType();
+        if (type == null) {
+            // use exclusive by default for reply queues
+            type = ReplyToType.Exclusive;
+        }
+
+        if (ReplyToType.Exclusive == type) {
+            answer = new ExclusiveQueueMessageListenerContainer(endpoint);
+            log.debug("Using exclusive queue: {} as reply listener: {}", endpoint.getReplyTo(), answer);
+        } else {
+            throw new IllegalArgumentException("ReplyToType " + type + " is not supported for reply queues");
+        }
+        answer.setMessageListener(this);
+
+        answer.setConcurrentConsumers(endpoint.getReplyToConcurrentConsumers());
+        answer.setDestinationCreationStrategy(new DestinationResolverDelegate(endpoint.getDestinationCreationStrategy()));
+        answer.setDestinationName(endpoint.getReplyTo());
+
+        String clientId = endpoint.getComponent().getClientId();
+        if (clientId != null) {
+            clientId += ".CamelReplyManager";
+            answer.setClientId(clientId);
+        }
+
+        return answer;
+    }
+
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyHandler.java
similarity index 57%
rename from components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java
rename to components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyHandler.java
index a6fbfac..73dc833 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/DefaultTransactionCommitStrategy.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyHandler.java
@@ -14,23 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.sjms.tx;
+package org.apache.camel.component.sjms.reply;
 
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.TransactionCommitStrategy;
+import javax.jms.Message;
+import javax.jms.Session;
 
 /**
- * The default commit strategy for all transaction.
+ * Handles a reply.
  */
-public class DefaultTransactionCommitStrategy implements TransactionCommitStrategy {
+public interface ReplyHandler {
 
-    @Override
-    public boolean commit(Exchange exchange) throws Exception {
-        return true;
-    }
+    /**
+     * The reply message was received
+     *
+     * @param correlationId the correlation id
+     * @param reply         the JMS reply message
+     * @param session       the JMS session
+     */
+    void onReply(String correlationId, Message reply, Session session);
 
-    @Override
-    public boolean rollback(Exchange exchange) throws Exception {
-        return true;
-    }
+    /**
+     * The reply message was not received and a timeout triggered
+     *
+     * @param correlationId the correlation id
+     */
+    void onTimeout(String correlationId);
 }
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyHolder.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyHolder.java
new file mode 100644
index 0000000..4f3b3c7
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyHolder.java
@@ -0,0 +1,124 @@
+/*
+ * 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.component.sjms.reply;
+
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+
+/**
+ * Holder which contains the {@link Exchange} and {@link AsyncCallback} to be used when the reply arrives, so we can set
+ * the reply on the {@link Exchange} and continue routing using the callback.
+ */
+public class ReplyHolder {
+
+    private final Exchange exchange;
+    private final AsyncCallback callback;
+    private final Message message;
+    private final Session session;
+    private final String originalCorrelationId;
+    private final String correlationId;
+    private long timeout;
+
+    /**
+     * Constructor to use when a reply message was received
+     */
+    public ReplyHolder(Exchange exchange, AsyncCallback callback, String originalCorrelationId,
+                       String correlationId, Message message, Session session) {
+        this.exchange = exchange;
+        this.callback = callback;
+        this.originalCorrelationId = originalCorrelationId;
+        this.correlationId = correlationId;
+        this.message = message;
+        this.session = session;
+    }
+
+    /**
+     * Constructor to use when a timeout occurred
+     */
+    public ReplyHolder(Exchange exchange, AsyncCallback callback, String originalCorrelationId,
+                       String correlationId, long timeout) {
+        this(exchange, callback, originalCorrelationId, correlationId, null, null);
+        this.timeout = timeout;
+    }
+
+    public Exchange getExchange() {
+        return exchange;
+    }
+
+    public AsyncCallback getCallback() {
+        return callback;
+    }
+
+    /**
+     * Gets the original correlation id, if one was set when sending the message.
+     * <p/>
+     * Some JMS brokers will mess with the correlation id and send back a different/empty correlation id. So we need to
+     * remember it so we can restore the correlation id.
+     */
+    public String getOriginalCorrelationId() {
+        return originalCorrelationId;
+    }
+
+    /**
+     * Gets the correlation id
+     *
+     * @see #getOriginalCorrelationId()
+     */
+    public String getCorrelationId() {
+        return correlationId;
+    }
+
+    /**
+     * Gets the received message
+     *
+     * @return the received message, or <tt>null</tt> if timeout occurred and no message has been received
+     * @see    #isTimeout()
+     */
+    public Message getMessage() {
+        return message;
+    }
+
+    /**
+     * Gets the JMS session from the received message
+     *
+     * @return the JMS session, or <tt>null</tt> if timeout occurred and no message has been received
+     * @see    #isTimeout()
+     */
+    public Session getSession() {
+        return session;
+    }
+
+    /**
+     * Whether timeout triggered or not.
+     * <p/>
+     * A timeout is triggered if <tt>requestTimeout</tt> option has been configured, and a reply message has <b>not</b>
+     * been received within that time frame.
+     */
+    public boolean isTimeout() {
+        return message == null;
+    }
+
+    /**
+     * The timeout value
+     */
+    public long getRequestTimeout() {
+        return timeout;
+    }
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyManager.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyManager.java
new file mode 100644
index 0000000..60fdc8e
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyManager.java
@@ -0,0 +1,112 @@
+/*
+ * 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.component.sjms.reply;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.sjms.SessionMessageListener;
+import org.apache.camel.component.sjms.SjmsEndpoint;
+
+/**
+ * The {@link ReplyManager} is responsible for handling
+ * <a href="http://camel.apache.org/request-reply.html">request-reply</a> over JMS.
+ */
+public interface ReplyManager extends SessionMessageListener {
+
+    /**
+     * Sets the belonging {@link org.apache.camel.component.sjms.SjmsEndpoint}.
+     */
+    void setEndpoint(SjmsEndpoint endpoint);
+
+    /**
+     * Sets the reply to queue the manager should listen for replies.
+     * <p/>
+     * The queue is either a temporary or a persistent queue.
+     */
+    void setReplyTo(Destination replyTo);
+
+    /**
+     * Sets the scheduled thread pool to use when checking for timeouts (no reply received within a given time period)
+     */
+    void setScheduledExecutorService(ScheduledExecutorService executorService);
+
+    /**
+     * Sets the thread pool to use for continue routing {@link Exchange} when a timeout was triggered when doing
+     * request/reply over JMS.
+     */
+    void setOnTimeoutExecutorService(ExecutorService executorService);
+
+    /**
+     * Sets the JMS message property used for message correlation. If set message correlation will be performed on the
+     * value of this JMS property, JMSCorrelationID will be ignored.
+     */
+    @Deprecated
+    void setCorrelationProperty(String correlationProperty);
+
+    /**
+     * Gets the reply to queue being used
+     */
+    Destination getReplyTo();
+
+    /**
+     * To be used when a reply queue is used with a custom JMS selector is being used.
+     */
+    @Deprecated
+    void setReplyToSelectorHeader(org.apache.camel.Message camelMessage, Message jmsMessage) throws JMSException;
+
+    /**
+     * Register a reply
+     *
+     * @param  replyManager          the reply manager being used
+     * @param  exchange              the exchange
+     * @param  callback              the callback
+     * @param  originalCorrelationId an optional original correlation id
+     * @param  correlationId         the correlation id to expect being used
+     * @param  requestTimeout        the timeout
+     * @return                       the correlation id used
+     */
+    String registerReply(
+            ReplyManager replyManager, Exchange exchange, AsyncCallback callback,
+            String originalCorrelationId, String correlationId, long requestTimeout);
+
+    /**
+     * Updates the correlation id to the new correlation id.
+     * <p/>
+     * This is only used when <tt>useMessageIDasCorrelationID</tt> option is used, which means a provisional correlation
+     * id is first used, then after the message has been sent, the real correlation id is known. This allows us then to
+     * update the internal mapping to expect the real correlation id.
+     *
+     * @param correlationId    the provisional correlation id
+     * @param newCorrelationId the real correlation id
+     * @param requestTimeout   the timeout
+     */
+    void updateCorrelationId(String correlationId, String newCorrelationId, long requestTimeout);
+
+    /**
+     * Process the reply
+     *
+     * @param holder containing needed data to process the reply and continue routing
+     */
+    void processReply(ReplyHolder holder);
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyManagerSupport.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyManagerSupport.java
new file mode 100644
index 0000000..22a195f
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/ReplyManagerSupport.java
@@ -0,0 +1,264 @@
+/*
+ * 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.component.sjms.reply;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangeTimedOutException;
+import org.apache.camel.component.sjms.MessageListenerContainer;
+import org.apache.camel.component.sjms.SjmsEndpoint;
+import org.apache.camel.component.sjms.SjmsMessage;
+import org.apache.camel.component.sjms.jms.JmsMessageHelper;
+import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.support.service.ServiceHelper;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for {@link ReplyManager} implementations.
+ */
+public abstract class ReplyManagerSupport extends ServiceSupport implements ReplyManager {
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+    protected final CamelContext camelContext;
+    protected ScheduledExecutorService scheduledExecutorService;
+    protected ExecutorService executorService;
+    protected SjmsEndpoint endpoint;
+    protected Destination replyTo;
+    protected MessageListenerContainer listenerContainer;
+    protected final CountDownLatch replyToLatch = new CountDownLatch(1);
+    protected final long replyToTimeout = 10000;
+    protected CorrelationTimeoutMap correlation;
+    protected String correlationProperty;
+
+    public ReplyManagerSupport(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public void setScheduledExecutorService(ScheduledExecutorService executorService) {
+        this.scheduledExecutorService = executorService;
+    }
+
+    @Override
+    public void setOnTimeoutExecutorService(ExecutorService executorService) {
+        this.executorService = executorService;
+    }
+
+    @Override
+    public void setEndpoint(SjmsEndpoint endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    @Override
+    public void setReplyTo(Destination replyTo) {
+        log.trace("ReplyTo destination: {}", replyTo);
+        this.replyTo = replyTo;
+        // trigger latch as the reply to has been resolved and set
+        replyToLatch.countDown();
+    }
+
+    @Override
+    public void setCorrelationProperty(final String correlationProperty) {
+        this.correlationProperty = correlationProperty;
+    }
+
+    @Override
+    public Destination getReplyTo() {
+        if (replyTo != null) {
+            return replyTo;
+        }
+        try {
+            // the reply to destination has to be resolved using a DestinationResolver using
+            // the MessageListenerContainer which occurs asynchronously so we have to wait
+            // for that to happen before we can retrieve the reply to destination to be used
+            log.trace("Waiting for replyTo to be set");
+            boolean done = replyToLatch.await(replyToTimeout, TimeUnit.MILLISECONDS);
+            if (!done) {
+                log.warn("ReplyTo destination was not set and timeout occurred");
+            } else {
+                log.trace("Waiting for replyTo to be set done");
+            }
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        return replyTo;
+    }
+
+    @Override
+    public String registerReply(
+            ReplyManager replyManager, Exchange exchange, AsyncCallback callback,
+            String originalCorrelationId, String correlationId, long requestTimeout) {
+        // add to correlation map
+        QueueReplyHandler handler = new QueueReplyHandler(
+                replyManager, exchange, callback,
+                originalCorrelationId, correlationId, requestTimeout);
+        // Just make sure we don't override the old value of the correlationId
+        ReplyHandler result = correlation.putIfAbsent(correlationId, handler, requestTimeout);
+        if (result != null) {
+            String logMessage = String.format("The correlationId [%s] is not unique.", correlationId);
+            throw new IllegalArgumentException(logMessage);
+        }
+        return correlationId;
+    }
+
+    protected abstract ReplyHandler createReplyHandler(
+            ReplyManager replyManager, Exchange exchange, AsyncCallback callback,
+            String originalCorrelationId, String correlationId, long requestTimeout);
+
+    @Override
+    public void onMessage(Message message, Session session) throws JMSException {
+        String correlationID = null;
+
+        try {
+            if (correlationProperty == null) {
+                correlationID = message.getJMSCorrelationID();
+            } else {
+                correlationID = message.getStringProperty(correlationProperty);
+            }
+        } catch (JMSException e) {
+            // ignore
+        }
+
+        if (correlationID == null) {
+            log.warn("Ignoring message with no correlationID: {}", message);
+            return;
+        }
+
+        log.debug("Received reply message with correlationID [{}] -> {}", correlationID, message);
+
+        // handle the reply message
+        handleReplyMessage(correlationID, message, session);
+    }
+
+    @Override
+    public void processReply(ReplyHolder holder) {
+        if (holder != null && isRunAllowed()) {
+            try {
+                Exchange exchange = holder.getExchange();
+
+                boolean timeout = holder.isTimeout();
+                if (timeout) {
+                    // timeout occurred do a WARN log so its easier to spot in the logs
+                    if (log.isWarnEnabled()) {
+                        log.warn(
+                                "Timeout occurred after {} millis waiting for reply message with correlationID [{}] on destination {}."
+                                 + " Setting ExchangeTimedOutException on {} and continue routing.",
+                                holder.getRequestTimeout(), holder.getCorrelationId(), replyTo,
+                                ExchangeHelper.logIds(exchange));
+                    }
+
+                    // no response, so lets set a timed out exception
+                    String msg = "reply message with correlationID: " + holder.getCorrelationId()
+                                 + " not received on destination: " + replyTo;
+                    exchange.setException(new ExchangeTimedOutException(exchange, holder.getRequestTimeout(), msg));
+                } else {
+                    Message message = holder.getMessage();
+                    Session session = holder.getSession();
+                    SjmsMessage response = new SjmsMessage(exchange, message, session, endpoint.getBinding());
+                    // the JmsBinding is designed to be "pull-based": it will populate the Camel message on demand
+                    // therefore, we link Exchange and OUT message before continuing, so that the JmsBinding has full access 
+                    // to everything it may need, and can populate headers, properties, etc. accordingly (solves CAMEL-6218).
+                    exchange.setOut(response);
+                    Object body = response.getBody();
+
+                    if (endpoint.isTransferException() && body instanceof Exception) {
+                        log.debug("Reply was an Exception. Setting the Exception on the Exchange: {}", body);
+                        // we got an exception back and endpoint was configured to transfer exception
+                        // therefore set response as exception
+                        exchange.setException((Exception) body);
+                    } else {
+                        log.debug("Reply received. OUT message body set to reply payload: {}", body);
+                    }
+
+                    // restore correlation id in case the remote server messed with it
+                    if (holder.getOriginalCorrelationId() != null) {
+                        JmsMessageHelper.setCorrelationId(message, holder.getOriginalCorrelationId());
+                        exchange.getOut().setHeader("JMSCorrelationID", holder.getOriginalCorrelationId());
+                    }
+                }
+            } finally {
+                // notify callback
+                AsyncCallback callback = holder.getCallback();
+                callback.done(false);
+            }
+        }
+    }
+
+    protected abstract void handleReplyMessage(String correlationID, Message message, Session session);
+
+    protected abstract MessageListenerContainer createListenerContainer() throws Exception;
+
+    @Override
+    protected void doStart() throws Exception {
+        ObjectHelper.notNull(executorService, "executorService", this);
+        ObjectHelper.notNull(scheduledExecutorService, "scheduledExecutorService", this);
+        ObjectHelper.notNull(endpoint, "endpoint", this);
+
+        // timeout map to use for purging messages which have timed out, while waiting for an expected reply
+        // when doing request/reply over JMS
+        log.trace("Using timeout checker interval with {} millis", endpoint.getComponent().getRequestTimeoutCheckerInterval());
+        correlation = new CorrelationTimeoutMap(
+                scheduledExecutorService, endpoint.getComponent().getRequestTimeoutCheckerInterval(), executorService);
+        ServiceHelper.startService(correlation);
+
+        // create JMS listener and start it
+        listenerContainer = createListenerContainer();
+        listenerContainer.afterPropertiesConfigured(endpoint.getCamelContext());
+        log.debug("Starting reply listener container on endpoint: {}", endpoint);
+
+        ServiceHelper.startService(listenerContainer);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        ServiceHelper.stopService(correlation);
+
+        if (listenerContainer != null) {
+            log.debug("Stopping reply listener container on endpoint: {}", endpoint);
+            try {
+                ServiceHelper.stopAndShutdownService(listenerContainer);
+            } finally {
+                listenerContainer = null;
+            }
+        }
+
+        // must also stop executor service
+        if (scheduledExecutorService != null) {
+            camelContext.getExecutorServiceManager().shutdownGraceful(scheduledExecutorService);
+            scheduledExecutorService = null;
+        }
+        if (executorService != null) {
+            camelContext.getExecutorServiceManager().shutdownGraceful(executorService);
+            executorService = null;
+        }
+    }
+
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueMessageListenerContainer.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueMessageListenerContainer.java
new file mode 100644
index 0000000..3e1c933
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueMessageListenerContainer.java
@@ -0,0 +1,43 @@
+/*
+ * 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.component.sjms.reply;
+
+import javax.jms.Destination;
+import javax.jms.MessageConsumer;
+import javax.jms.Session;
+
+import org.apache.camel.component.sjms.MessageListenerContainer;
+import org.apache.camel.component.sjms.SjmsEndpoint;
+import org.apache.camel.component.sjms.consumer.SimpleMessageListenerContainer;
+
+/**
+ * This {@link MessageListenerContainer} is used for reply queues which are using temporary queue.
+ */
+public class TemporaryQueueMessageListenerContainer extends SimpleMessageListenerContainer {
+
+    // no need to override any methods currently
+
+    public TemporaryQueueMessageListenerContainer(SjmsEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    protected MessageConsumer createMessageConsumer(Session session) throws Exception {
+        Destination destination = getDestinationCreationStrategy().createTemporaryDestination(session, false);
+        return getEndpoint().getJmsObjectFactory().createQueueMessageConsumer(session, destination);
+    }
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueReplyHandler.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueReplyHandler.java
new file mode 100644
index 0000000..1fe0c70
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueReplyHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.component.sjms.reply;
+
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+
+/**
+ * {@link ReplyHandler} to handle processing replies when using temporary queues.
+ */
+public class TemporaryQueueReplyHandler implements ReplyHandler {
+
+    // task queue to add the holder so we can process the reply
+    protected final ReplyManager replyManager;
+    protected final Exchange exchange;
+    protected final AsyncCallback callback;
+    // remember the original correlation id, in case the server returns back a reply with a messed up correlation id
+    protected final String originalCorrelationId;
+    protected final String correlationId;
+    protected final long timeout;
+
+    public TemporaryQueueReplyHandler(ReplyManager replyManager, Exchange exchange, AsyncCallback callback,
+                                      String originalCorrelationId, String correlationId, long timeout) {
+        this.replyManager = replyManager;
+        this.exchange = exchange;
+        this.originalCorrelationId = originalCorrelationId;
+        this.correlationId = correlationId;
+        this.callback = callback;
+        this.timeout = timeout;
+    }
+
+    @Override
+    public void onReply(String correlationId, Message reply, Session session) {
+        // create holder object with the reply
+        ReplyHolder holder = new ReplyHolder(exchange, callback, originalCorrelationId, correlationId, reply, session);
+        // process the reply
+        replyManager.processReply(holder);
+    }
+
+    @Override
+    public void onTimeout(String correlationId) {
+        // create holder object without the reply which means a timeout occurred
+        ReplyHolder holder = new ReplyHolder(exchange, callback, originalCorrelationId, correlationId, timeout);
+        // process timeout
+        replyManager.processReply(holder);
+    }
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueReplyManager.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueReplyManager.java
new file mode 100644
index 0000000..6210d53
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/TemporaryQueueReplyManager.java
@@ -0,0 +1,169 @@
+/*
+ * 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.component.sjms.reply;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+import javax.jms.TemporaryQueue;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.sjms.MessageListenerContainer;
+import org.apache.camel.component.sjms.jms.DestinationCreationStrategy;
+
+/**
+ * A {@link ReplyManager} when using temporary queues.
+ */
+public class TemporaryQueueReplyManager extends ReplyManagerSupport {
+
+    final TemporaryReplyQueueDestinationResolver destResolver = new TemporaryReplyQueueDestinationResolver();
+
+    public TemporaryQueueReplyManager(CamelContext camelContext) {
+        super(camelContext);
+    }
+
+    @Override
+    public Destination getReplyTo() {
+        try {
+            destResolver.destinationReady();
+        } catch (InterruptedException e) {
+            log.warn("Interrupted while waiting for JMSReplyTo destination refresh", e);
+        }
+        return super.getReplyTo();
+    }
+
+    @Override
+    protected ReplyHandler createReplyHandler(
+            ReplyManager replyManager, Exchange exchange, AsyncCallback callback,
+            String originalCorrelationId, String correlationId, long requestTimeout) {
+        return new TemporaryQueueReplyHandler(this, exchange, callback, originalCorrelationId, correlationId, requestTimeout);
+    }
+
+    @Override
+    public void updateCorrelationId(String correlationId, String newCorrelationId, long requestTimeout) {
+        log.trace("Updated provisional correlationId [{}] to expected correlationId [{}]", correlationId, newCorrelationId);
+
+        ReplyHandler handler = correlation.remove(correlationId);
+        if (handler != null) {
+            correlation.put(newCorrelationId, handler, requestTimeout);
+        }
+    }
+
+    @Override
+    protected void handleReplyMessage(String correlationID, Message message, Session session) {
+        ReplyHandler handler = correlation.get(correlationID);
+        if (handler != null) {
+            correlation.remove(correlationID);
+            handler.onReply(correlationID, message, session);
+        } else {
+            // we could not correlate the received reply message to a matching request and therefore
+            // we cannot continue routing the unknown message
+            // log a warn and then ignore the message
+            log.warn("Reply received for unknown correlationID [{}]. The message will be ignored: {}", correlationID, message);
+        }
+    }
+
+    @Override
+    public void setReplyToSelectorHeader(org.apache.camel.Message camelMessage, Message jmsMessage) throws JMSException {
+        // noop
+    }
+
+    @Override
+    protected MessageListenerContainer createListenerContainer() throws Exception {
+        TemporaryQueueMessageListenerContainer answer
+                = new TemporaryQueueMessageListenerContainer(endpoint);
+        answer.setMessageListener(this);
+
+        String clientId = endpoint.getComponent().getClientId();
+        if (clientId != null) {
+            clientId += ".CamelReplyManager";
+            answer.setClientId(clientId);
+        }
+        answer.setConcurrentConsumers(endpoint.getReplyToConcurrentConsumers());
+        answer.setExceptionListener(new TemporaryReplyQueueExceptionListener(destResolver));
+        answer.setDestinationCreationStrategy(destResolver);
+        answer.setDestinationName("temporary");
+        return answer;
+    }
+
+    private final class TemporaryReplyQueueExceptionListener implements ExceptionListener {
+        private final TemporaryReplyQueueDestinationResolver destResolver;
+
+        private TemporaryReplyQueueExceptionListener(TemporaryReplyQueueDestinationResolver destResolver) {
+            this.destResolver = destResolver;
+        }
+
+        @Override
+        public void onException(JMSException exception) {
+            // capture exceptions, and schedule a refresh of the ReplyTo destination
+            log.warn("Exception inside the DMLC for Temporary ReplyTo Queue for destination {}, refreshing ReplyTo destination",
+                    endpoint.getDestinationName(), exception);
+            destResolver.scheduleRefresh();
+        }
+
+    }
+
+    private final class TemporaryReplyQueueDestinationResolver implements DestinationCreationStrategy {
+        private TemporaryQueue queue;
+        private final AtomicBoolean refreshWanted = new AtomicBoolean();
+
+        @Override
+        public Destination createDestination(Session session, String name, boolean topic) throws JMSException {
+            return null;
+        }
+
+        @Override
+        public Destination createTemporaryDestination(Session session, boolean topic) throws JMSException {
+            synchronized (refreshWanted) {
+                if (queue == null || refreshWanted.get()) {
+                    refreshWanted.set(false);
+                    queue = session.createTemporaryQueue();
+                    setReplyTo(queue);
+                    if (log.isDebugEnabled()) {
+                        log.debug("Refreshed Temporary ReplyTo Queue. New queue: {}", queue.getQueueName());
+                    }
+                    refreshWanted.notifyAll();
+                }
+            }
+            return queue;
+        }
+
+        public void scheduleRefresh() {
+            refreshWanted.set(true);
+        }
+
+        public void destinationReady() throws InterruptedException {
+            if (refreshWanted.get()) {
+                synchronized (refreshWanted) {
+                    //check if requestWanted is still true
+                    if (refreshWanted.get()) {
+                        log.debug("Waiting for new Temporary ReplyTo queue to be assigned before we can continue");
+                        refreshWanted.wait();
+                    }
+                }
+            }
+        }
+
+    }
+
+}
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/package.html b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/package.html
new file mode 100644
index 0000000..56d2984
--- /dev/null
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/reply/package.html
@@ -0,0 +1,27 @@
+<!--
+
+    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.
+
+-->
+<html>
+<head>
+</head>
+<body>
+
+Logic implementing support for request/reply over JMS
+
+</body>
+</html>
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/SessionTransactionSynchronization.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/SessionTransactionSynchronization.java
deleted file mode 100644
index ae8e3e4..0000000
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/SessionTransactionSynchronization.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.component.sjms.tx;
-
-import javax.jms.Connection;
-import javax.jms.Session;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sjms.TransactionCommitStrategy;
-import org.apache.camel.support.SynchronizationAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * SessionTransactionSynchronization is called at the completion of each {@link org.apache.camel.Exchange}.
- * <p/>
- * The commit or rollback on the {@link Session} must be performed from the same thread that consumed the message.
- */
-public class SessionTransactionSynchronization extends SynchronizationAdapter {
-    private static final Logger LOG = LoggerFactory.getLogger(SessionTransactionSynchronization.class);
-
-    private final Connection connection;
-    private final Session session;
-    private final TransactionCommitStrategy commitStrategy;
-    private final boolean close;
-
-    public SessionTransactionSynchronization(Connection connection, Session session, TransactionCommitStrategy commitStrategy,
-                                             boolean close) {
-        this.connection = connection;
-        this.session = session;
-        this.close = close;
-        if (commitStrategy == null) {
-            this.commitStrategy = new DefaultTransactionCommitStrategy();
-        } else {
-            this.commitStrategy = commitStrategy;
-        }
-    }
-
-    @Override
-    public void onFailure(Exchange exchange) {
-        try {
-            if (commitStrategy.rollback(exchange)) {
-                LOG.debug("Processing failure of ExchangeId: {}", exchange.getExchangeId());
-                if (session != null && session.getTransacted()) {
-                    session.rollback();
-                }
-            }
-        } catch (Exception e) {
-            LOG.warn("Failed to rollback the JMS session: {}", e.getMessage());
-        }
-
-        if (close) {
-            close(session);
-            close(connection);
-        }
-    }
-
-    @Override
-    public void onComplete(Exchange exchange) {
-        try {
-            if (commitStrategy.commit(exchange)) {
-                LOG.debug("Processing completion of ExchangeId: {}", exchange.getExchangeId());
-                if (session != null && session.getTransacted()) {
-                    session.commit();
-                }
-            }
-        } catch (Exception e) {
-            LOG.warn("Failed to commit the JMS session: {}", e.getMessage());
-            exchange.setException(e);
-        }
-
-        if (close) {
-            close(session);
-            close(connection);
-        }
-    }
-
-    @Override
-    public boolean allowHandover() {
-        // must not handover as we should be synchronous
-        return false;
-    }
-
-    private static void close(Connection con) {
-        if (con != null) {
-            try {
-                con.close();
-            } catch (Throwable e) {
-                // ignore
-            }
-        }
-    }
-
-    private static void close(Session session) {
-        if (session != null) {
-            try {
-                session.close();
-            } catch (Throwable e) {
-                // ignore
-            }
-        }
-    }
-
-}
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectInOutProducerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectInOutProducerTest.java
index f3ccfb4..295b19b 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectInOutProducerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectInOutProducerTest.java
@@ -23,7 +23,6 @@ import javax.jms.MessageListener;
 import javax.jms.MessageProducer;
 import javax.jms.TextMessage;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.sjms.support.JmsTestSupport;
@@ -82,13 +81,6 @@ public class ReconnectInOutProducerTest extends JmsTestSupport {
         };
     }
 
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext camelContext = super.createCamelContext();
-        camelContext.getComponent("sjms", SjmsComponent.class).setConnectionTestOnBorrow(true);
-        return camelContext;
-    }
-
     protected class MyMessageListener implements MessageListener {
         private String requestText;
         private String responseText;
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectProducerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectProducerTest.java
index 04b6ce5..6010e68 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectProducerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/ReconnectProducerTest.java
@@ -20,7 +20,6 @@ import javax.jms.Message;
 import javax.jms.MessageConsumer;
 import javax.jms.TextMessage;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.component.sjms.support.JmsTestSupport;
@@ -87,7 +86,7 @@ public class ReconnectProducerTest extends JmsTestSupport {
         return new RouteBuilder() {
             public void configure() {
                 from("direct:start")
-                        .to("sjms:queue:" + TEST_DESTINATION_NAME + "?consumerCount=10");
+                        .to("sjms:queue:" + TEST_DESTINATION_NAME + "?concurrentConsumers=10");
 
                 from("direct:finish")
                         .to("log:test.log.1?showBody=true", "mock:result");
@@ -95,10 +94,4 @@ public class ReconnectProducerTest extends JmsTestSupport {
         };
     }
 
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext camelContext = super.createCamelContext();
-        camelContext.getComponent("sjms", SjmsComponent.class).setConnectionTestOnBorrow(true);
-        return camelContext;
-    }
 }
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/SjmsDestinationCreationStrategyTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/SjmsDestinationCreationStrategyTest.java
deleted file mode 100644
index 460497c..0000000
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/SjmsDestinationCreationStrategyTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.component.sjms;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Session;
-
-import org.apache.activemq.ActiveMQConnectionFactory;
-import org.apache.camel.CamelContext;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.sjms.jms.DefaultDestinationCreationStrategy;
-import org.apache.camel.component.sjms.support.JmsTestSupport;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class SjmsDestinationCreationStrategyTest extends JmsTestSupport {
-
-    private boolean createDestinationCalled;
-    private boolean createTemporaryDestination;
-
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext camelContext = new DefaultCamelContext();
-        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUri);
-        setupFactoryExternal(connectionFactory);
-        SjmsComponent component = new SjmsComponent();
-        component.setConnectionFactory(connectionFactory);
-        component.setDestinationCreationStrategy(new TestDestinationCreationStrategyTest());
-        camelContext.addComponent("sjms", component);
-        return camelContext;
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("sjms:queue:inout?exchangePattern=InOut")
-                        .process(exchange -> exchange.getMessage().setBody("response"));
-            }
-        };
-    }
-
-    @Test
-    public void testSjmsComponentUsesCustomDestinationCreationStrategy() throws Exception {
-        assertFalse(createDestinationCalled);
-        template.sendBody("sjms:queue:inonly", "hello world");
-        assertTrue(createDestinationCalled);
-
-        assertFalse(createTemporaryDestination);
-        String response = (String) template.sendBody("sjms:queue:inout?exchangePattern=InOut",
-                ExchangePattern.InOut, "hello world 2");
-        assertTrue(createTemporaryDestination);
-        assertEquals("response", response);
-    }
-
-    class TestDestinationCreationStrategyTest extends DefaultDestinationCreationStrategy {
-        @Override
-        public Destination createDestination(Session session, String name, boolean topic) throws JMSException {
-            if (name.equals("inonly")) {
-                createDestinationCalled = true;
-            }
-            return super.createDestination(session, name, topic);
-        }
-
-        @Override
-        public Destination createTemporaryDestination(Session session, boolean topic) throws JMSException {
-            createTemporaryDestination = true;
-            return super.createTemporaryDestination(session, topic);
-        }
-    }
-}
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/SjmsEndpointConnectionSettingsTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/SjmsEndpointConnectionSettingsTest.java
index a888b50..2f4aa3d 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/SjmsEndpointConnectionSettingsTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/SjmsEndpointConnectionSettingsTest.java
@@ -19,8 +19,6 @@ package org.apache.camel.component.sjms;
 import org.apache.activemq.ActiveMQConnectionFactory;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
-import org.apache.camel.component.sjms.jms.ConnectionFactoryResource;
-import org.apache.camel.component.sjms.jms.ConnectionResource;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.support.SimpleRegistry;
 import org.apache.camel.test.junit5.CamelTestSupport;
@@ -33,7 +31,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 public class SjmsEndpointConnectionSettingsTest extends CamelTestSupport {
     private final ActiveMQConnectionFactory connectionFactory
             = new ActiveMQConnectionFactory("vm://broker?broker.persistent=false&broker.useJmx=false");
-    private final ConnectionResource connectionResource = new ConnectionFactoryResource(2, connectionFactory);
 
     @Test
     public void testConnectionFactory() {
@@ -44,20 +41,10 @@ public class SjmsEndpointConnectionSettingsTest extends CamelTestSupport {
         assertEquals(connectionFactory, qe.getConnectionFactory());
     }
 
-    @Test
-    public void testConnectionResource() {
-        Endpoint endpoint = context.getEndpoint("sjms:queue:test?connectionResource=#connresource");
-        assertNotNull(endpoint);
-        assertTrue(endpoint instanceof SjmsEndpoint);
-        SjmsEndpoint qe = (SjmsEndpoint) endpoint;
-        assertEquals(connectionResource, qe.getConnectionResource());
-    }
-
     @Override
     protected CamelContext createCamelContext() throws Exception {
         SimpleRegistry registry = new SimpleRegistry();
         registry.bind("activemq", connectionFactory);
-        registry.bind("connresource", connectionResource);
         return new DefaultCamelContext(registry);
     }
 }
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOnlyConsumerAsyncTrueTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOnlyConsumerAsyncTrueTest.java
deleted file mode 100644
index 7d9259f..0000000
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOnlyConsumerAsyncTrueTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.component.sjms.consumer;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.sjms.support.JmsTestSupport;
-import org.junit.jupiter.api.Test;
-
-/**
- *
- */
-public class InOnlyConsumerAsyncTrueTest extends JmsTestSupport {
-
-    private static final String MOCK_RESULT = "mock:result";
-
-    @Test
-    public void testInOnlyConsumerAsyncTrue() throws Exception {
-        getMockEndpoint(MOCK_RESULT).expectedBodiesReceived("Hello World", "Hello Camel");
-
-        template.sendBody("sjms:queue:in.only.consumer.async", "Hello Camel");
-        template.sendBody("sjms:queue:in.only.consumer.async", "Hello World");
-        //        Thread.sleep(4000);
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("sjms:queue:in.only.consumer.async?asyncConsumer=true").to("log:before")
-                        .process(new Processor() {
-                            public void process(Exchange exchange) throws Exception {
-                                if (exchange.getIn().getBody(String.class).equals("Hello Camel")) {
-                                    Thread.sleep(2000);
-                                }
-                            }
-                        }).to("log:after").to(MOCK_RESULT);
-            }
-        };
-    }
-}
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOnlyTopicDurableConsumerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOnlyTopicDurableConsumerTest.java
index 1332f7e..788d264 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOnlyTopicDurableConsumerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOnlyTopicDurableConsumerTest.java
@@ -47,7 +47,7 @@ public class InOnlyTopicDurableConsumerTest extends JmsTestSupport {
     protected CamelContext createCamelContext() throws Exception {
         CamelContext context = super.createCamelContext();
         SjmsComponent sjms = context.getComponent("sjms", SjmsComponent.class);
-        sjms.setConnectionClientId(CONNECTION_ID);
+        sjms.setClientId(CONNECTION_ID);
         return context;
     }
 
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConcurrentConsumerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConcurrentConsumerTest.java
index 3822484..b45f712 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConcurrentConsumerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConcurrentConsumerTest.java
@@ -77,10 +77,10 @@ public class InOutConcurrentConsumerTest extends JmsTestSupport {
         return new RouteBuilder() {
             public void configure() throws Exception {
                 from("direct:start")
-                        .to("sjms:a?consumerCount=5&exchangePattern=InOut&replyTo=myResponse")
+                        .to("sjms:a?replyToConcurrentConsumers=5&replyTo=myResponse")
                         .to("mock:result");
 
-                from("sjms:a?consumerCount=5&exchangePattern=InOut&replyTo=myResponse")
+                from("sjms:a?concurrentConsumers=5")
                         .process(exchange -> {
                             String body = exchange.getIn().getBody(String.class);
                             // sleep a little to simulate heavy work and force concurrency processing
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerQueueAsyncTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerQueueAsyncTest.java
index 0b89f96..15bccea 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerQueueAsyncTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerQueueAsyncTest.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.sjms.consumer;
 
 import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.sjms.support.JmsTestSupport;
@@ -25,12 +26,12 @@ import org.junit.jupiter.api.Test;
 public class InOutConsumerQueueAsyncTest extends JmsTestSupport {
 
     @Test
-    public void testAynchronous() throws Exception {
+    public void testAsync() throws Exception {
         getMockEndpoint("mock:result").expectedBodiesReceived("Hello World", "Hello Camel");
 
         template.sendBody("sjms:start", "Hello Camel");
         template.sendBody("sjms:start", "Hello World");
-        Thread.sleep(4000);
+
         assertMockEndpointsSatisfied();
     }
 
@@ -39,10 +40,14 @@ public class InOutConsumerQueueAsyncTest extends JmsTestSupport {
         return new RouteBuilder() {
             public void configure() throws Exception {
                 from("sjms:queue:start?asyncConsumer=true")
-                        .to("sjms:queue:in.out.queue?replyTo=in.out.queue.response")
+                        .log("Requesting ${body} with thread ${threadName}")
+                        .to(ExchangePattern.InOut,
+                                "sjms:queue:in.out.queue?replyToConcurrentConsumers=2&replyTo=in.out.queue.response")
+                        .log("Result ${body} with thread ${threadName}")
                         .to("mock:result");
 
-                from("sjms:queue:in.out.queue?asyncConsumer=true").to("log:before")
+                from("sjms:queue:in.out.queue?concurrentConsumers=2").to("log:before")
+                        .log("Replying ${body} with thread ${threadName}")
                         .process(new Processor() {
                             public void process(Exchange exchange) throws Exception {
                                 String body = (String) exchange.getIn().getBody();
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerTempQueueAsyncTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerTempQueueAsyncTest.java
index a6c8478..0e94068 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerTempQueueAsyncTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutConsumerTempQueueAsyncTest.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.sjms.consumer;
 
 import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.sjms.support.JmsTestSupport;
@@ -25,12 +26,12 @@ import org.junit.jupiter.api.Test;
 public class InOutConsumerTempQueueAsyncTest extends JmsTestSupport {
 
     @Test
-    public void testAynchronous() throws Exception {
+    public void testAsync() throws Exception {
         getMockEndpoint("mock:result").expectedBodiesReceived("Hello World", "Hello Camel");
 
-        template.requestBody("sjms:start", "Hello Camel");
-        template.requestBody("sjms:start", "Hello World");
-        Thread.sleep(5000);
+        template.sendBody("sjms:start", "Hello Camel");
+        template.sendBody("sjms:start", "Hello World");
+
         assertMockEndpointsSatisfied();
     }
 
@@ -39,10 +40,13 @@ public class InOutConsumerTempQueueAsyncTest extends JmsTestSupport {
         return new RouteBuilder() {
             public void configure() throws Exception {
                 from("sjms:queue:start?asyncConsumer=true")
-                        .to("sjms:queue:in.out.temp.queue")
+                        .log("Requesting ${body} with thread ${threadName}")
+                        .to(ExchangePattern.InOut, "sjms:queue:in.out.temp.queue?replyToConcurrentConsumers=2")
+                        .log("Result ${body} with thread ${threadName}")
                         .to("mock:result");
 
-                from("sjms:queue:in.out.temp.queue?asyncConsumer=true").to("log:before")
+                from("sjms:queue:in.out.temp.queue?concurrentConsumers=2").to("log:before")
+                        .log("Replying ${body} with thread ${threadName}")
                         .process(new Processor() {
                             public void process(Exchange exchange) throws Exception {
                                 String body = (String) exchange.getIn().getBody();
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutSynchronousConsumerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutSynchronousConsumerTest.java
index a913e08..3a565da 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutSynchronousConsumerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/consumer/InOutSynchronousConsumerTest.java
@@ -28,7 +28,7 @@ public class InOutSynchronousConsumerTest extends JmsTestSupport {
 
     private static String beforeThreadName;
     private static String afterThreadName;
-    private String url = "sjms:queue:in?replyTo=response.queue";
+    private String url = "sjms:queue:in?replyTo=response.queue&synchronous=true";
 
     @Test
     public void testSynchronous() throws Exception {
@@ -50,7 +50,7 @@ public class InOutSynchronousConsumerTest extends JmsTestSupport {
                         .to("log:after")
                         .to("mock:result");
 
-                from("sjms:queue:in?exchangePattern=InOut").process(exchange -> exchange.getMessage().setBody("Bye World"));
+                from("sjms:queue:in").process(exchange -> exchange.getMessage().setBody("Bye World"));
             }
         };
     }
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/it/ConnectionResourceIT.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/it/ConnectionResourceIT.java
deleted file mode 100644
index c65accb..0000000
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/it/ConnectionResourceIT.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.component.sjms.it;
-
-import java.util.concurrent.TimeUnit;
-
-import javax.jms.Connection;
-import javax.jms.Session;
-
-import org.apache.activemq.pool.PooledConnectionFactory;
-import org.apache.camel.CamelContext;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.sjms.SjmsComponent;
-import org.apache.camel.component.sjms.jms.ConnectionResource;
-import org.apache.camel.component.sjms.support.JmsTestSupport;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.apache.camel.util.StopWatch;
-import org.junit.jupiter.api.Test;
-
-import static org.apache.camel.test.junit5.TestSupport.body;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-/**
- * Integration test that verifies we can replace the internal ConnectionFactoryResource with another provider.
- */
-public class ConnectionResourceIT extends JmsTestSupport {
-
-    /**
-     * Test method for {@link org.apache.commons.pool.ObjectPool#returnObject(java.lang.Object)} .
-     * 
-     * @throws Exception
-     */
-    @Test
-    public void testCreateConnections() throws Exception {
-        ConnectionResource pool = new AMQConnectionResource("tcp://localhost:33333", 1);
-        assertNotNull(pool);
-        Connection connection = pool.borrowConnection();
-        assertNotNull(connection);
-        assertNotNull(connection.createSession(false, Session.AUTO_ACKNOWLEDGE));
-        pool.returnConnection(connection);
-        Connection connection2 = pool.borrowConnection();
-        assertNotNull(connection2);
-    }
-
-    @Test
-    public void testConnectionResourceRouter() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedMessageCount(100);
-        mock.expectsNoDuplicates(body());
-
-        StopWatch watch = new StopWatch();
-
-        for (int i = 0; i < 100; i++) {
-            template.sendBody("seda:start", "" + i);
-        }
-
-        // just in case we run on slow boxes
-        assertMockEndpointsSatisfied(20, TimeUnit.SECONDS);
-
-        log.info("Took " + watch.taken() + " ms. to process 100 messages request/reply over JMS");
-    }
-
-    /*
-     * @see org.apache.camel.test.junit5.CamelTestSupport#createCamelContext()
-     * @return
-     * @throws Exception
-     */
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext camelContext = new DefaultCamelContext();
-        AMQConnectionResource pool = new AMQConnectionResource("tcp://localhost:33333", 1);
-        SjmsComponent component = new SjmsComponent();
-        component.setConnectionResource(pool);
-        camelContext.addComponent("sjms", component);
-        return camelContext;
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-
-                from("seda:start")
-                        .to("sjms:queue:in.foo?replyTo=out.bar&exchangePattern=InOut")
-                        .to("mock:result");
-
-                from("sjms:queue:in.foo?exchangePattern=InOut&consumerCount=20")
-                        .log("Using ${threadName} to process ${body}")
-                        .transform(body().prepend("Bye "));
-            }
-        };
-    }
-
-    public class AMQConnectionResource implements ConnectionResource {
-        private PooledConnectionFactory pcf;
-
-        public AMQConnectionResource(String connectString, int maxConnections) {
-            pcf = new PooledConnectionFactory(connectString);
-            pcf.setMaxConnections(maxConnections);
-            pcf.start();
-        }
-
-        public void stop() {
-            pcf.stop();
-        }
-
-        @Override
-        public Connection borrowConnection() throws Exception {
-            Connection answer = pcf.createConnection();
-            answer.start();
-            return answer;
-        }
-
-        @Override
-        public void returnConnection(Connection connection) throws Exception {
-            // Do nothing in this case since the PooledConnectionFactory takes
-            // care of this for us
-            log.info("Connection returned");
-        }
-    }
-}
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/jms/ConnectionFactoryResourceTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/jms/ConnectionFactoryResourceTest.java
deleted file mode 100644
index b303027..0000000
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/jms/ConnectionFactoryResourceTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.component.sjms.jms;
-
-import java.util.NoSuchElementException;
-
-import org.apache.activemq.ActiveMQConnection;
-import org.apache.activemq.ActiveMQConnectionFactory;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class ConnectionFactoryResourceTest {
-    private ActiveMQConnectionFactory connectionFactory;
-
-    @BeforeEach
-    public void setup() {
-        connectionFactory = new ActiveMQConnectionFactory("vm://broker?broker.persistent=false&broker.useJmx=false");
-    }
-
-    @AfterEach
-    public void teardown() {
-        connectionFactory = null;
-    }
-
-    @Test
-    public void testCreateObject() throws Exception {
-        ConnectionFactoryResource pool = new ConnectionFactoryResource(1, connectionFactory);
-        pool.fillPool();
-        assertNotNull(pool);
-        ActiveMQConnection connection = (ActiveMQConnection) pool.makeObject();
-        assertNotNull(connection);
-        assertTrue(connection.isStarted());
-        pool.drainPool();
-    }
-
-    @Test
-    public void testDestroyObject() throws Exception {
-        ConnectionFactoryResource pool = new ConnectionFactoryResource(1, connectionFactory);
-        pool.fillPool();
-        assertNotNull(pool);
-        ActiveMQConnection connection = (ActiveMQConnection) pool.makeObject();
-        assertNotNull(connection);
-        assertTrue(connection.isStarted());
-        pool.drainPool();
-        assertEquals(0, pool.size());
-    }
-
-    @Test
-    public void testBorrowObject() throws Exception {
-        ConnectionFactoryResource pool = new ConnectionFactoryResource(1, connectionFactory);
-        pool.fillPool();
-        assertNotNull(pool);
-        ActiveMQConnection connection = (ActiveMQConnection) pool.borrowConnection();
-        assertNotNull(connection);
-        assertTrue(connection.isStarted());
-        assertThrows(NoSuchElementException.class,
-                pool::borrowConnection);
-    }
-
-    @Test
-    public void testReturnObject() throws Exception {
-        ConnectionFactoryResource pool = new ConnectionFactoryResource(1, connectionFactory);
-        pool.fillPool();
-        assertNotNull(pool);
-        ActiveMQConnection connection = (ActiveMQConnection) pool.borrowConnection();
-        assertNotNull(connection);
-        assertTrue(connection.isStarted());
-        pool.returnConnection(connection);
-        ActiveMQConnection connection2 = (ActiveMQConnection) pool.borrowConnection();
-        assertNotNull(connection2);
-        pool.drainPool();
-    }
-
-    @Test
-    public void testRoundRobbin() throws Exception {
-        ConnectionFactoryResource pool = new ConnectionFactoryResource(2, connectionFactory);
-        pool.fillPool();
-        assertNotNull(pool);
-        ActiveMQConnection connection = (ActiveMQConnection) pool.borrowConnection();
-        assertNotNull(connection);
-        assertTrue(connection.isStarted());
-        pool.returnConnection(connection);
-        ActiveMQConnection connection2 = (ActiveMQConnection) pool.borrowConnection();
-        assertNotNull(connection2);
-        assertNotEquals(connection, connection2);
-        pool.drainPool();
-    }
-}
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerAsyncLoadTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerAsyncLoadTest.java
index 4a618d0..c5cfddc 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerAsyncLoadTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerAsyncLoadTest.java
@@ -119,7 +119,7 @@ public class InOutQueueProducerAsyncLoadTest extends JmsTestSupport {
                         .to("log:" + TEST_DESTINATION_NAME + ".in.log?showBody=true")
                         .to(ExchangePattern.InOut, "sjms:queue:" + TEST_DESTINATION_NAME + ".request" + "?replyTo="
                                                    + TEST_DESTINATION_NAME
-                                                   + ".response&consumerCount=10")
+                                                   + ".response&concurrentConsumers=10")
                         .threads(20)
                         .to("log:" + TEST_DESTINATION_NAME + ".out.log?showBody=true");
             }
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerSyncLoadTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerSyncLoadTest.java
index d575040..79dbe00 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerSyncLoadTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/InOutQueueProducerSyncLoadTest.java
@@ -117,7 +117,7 @@ public class InOutQueueProducerSyncLoadTest extends JmsTestSupport {
                         .to("log:" + TEST_DESTINATION_NAME + ".in.log?showBody=true")
                         .to(ExchangePattern.InOut, "sjms:queue:" + TEST_DESTINATION_NAME + ".request" + "?replyTo="
                                                    + TEST_DESTINATION_NAME
-                                                   + ".response&consumerCount=20")
+                                                   + ".response&concurrentConsumers=20")
                         .to("log:" + TEST_DESTINATION_NAME + ".out.log?showBody=true");
             }
         };
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/QueueProducerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/QueueProducerTest.java
index 5507f03..a2cf7c4 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/QueueProducerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/producer/QueueProducerTest.java
@@ -66,12 +66,6 @@ public class QueueProducerTest extends JmsTestSupport {
 
     }
 
-    /**
-     * @see              org.apache.camel.test.junit5.CamelTestSupport#createRouteBuilder()
-     *
-     * @return
-     * @throws Exception
-     */
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConcurrentConsumersTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConcurrentConsumersTest.java
index 7a484d6..062e7c4 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConcurrentConsumersTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConcurrentConsumersTest.java
@@ -33,13 +33,13 @@ public class TransactedConcurrentConsumersTest extends TransactedConsumerSupport
     public void testRoute() throws Exception {
         final String destinationName = "sjms:queue:one.consumer.one.route.test";
         int routeCount = 1;
-        int consumerCount = 2;
+        int concurrentConsumers = 2;
         int messageCount = 20;
         int maxAttemptsCount = 10;
         int totalRedeliverdFalse = 20;
         int totalRedeliveredTrue = 1;
         runTest(destinationName, routeCount, messageCount, totalRedeliverdFalse, totalRedeliveredTrue,
-                consumerCount, maxAttemptsCount);
+                concurrentConsumers, maxAttemptsCount);
     }
 
     @Override
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumerSupport.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumerSupport.java
index 38d8217..68dbf45 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumerSupport.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumerSupport.java
@@ -38,7 +38,7 @@ public abstract class TransactedConsumerSupport extends CamelTestSupport {
 
     protected void runTest(
             String destinationName, int routeCount, int messageCount, int totalRedeliverdFalse, int totalRedeliveredTrue,
-            int consumerCount, int maxAttemptsCount)
+            int concurrentConsumers, int maxAttemptsCount)
             throws Exception {
         // The CountDownLatch is used to make our final assertions await
         // unit all the messages have been processed. It is also
@@ -48,7 +48,7 @@ public abstract class TransactedConsumerSupport extends CamelTestSupport {
 
         for (int i = 1; i <= routeCount; i++) {
             // We add a route here so we can pass our latch into it.
-            addRoute(destinationName, i, consumerCount, maxAttemptsCount, latch);
+            addRoute(destinationName, i, concurrentConsumers, maxAttemptsCount, latch);
             // Create mock endpoints for the before and after
             getMockEndpoint("mock:test.before." + i).expectedMessageCount(totalRedeliverdFalse);
             getMockEndpoint("mock:test.after." + i).expectedMessageCount(totalRedeliveredTrue);
@@ -89,7 +89,7 @@ public abstract class TransactedConsumerSupport extends CamelTestSupport {
     }
 
     protected void addRoute(
-            final String destinationName, final int routeNumber, final int consumerCount,
+            final String destinationName, final int routeNumber, final int concurrentConsumers,
             final int maxAttemptsCount, final CountDownLatch latch)
             throws Exception {
         context.addRoutes(new RouteBuilder() {
@@ -103,8 +103,8 @@ public abstract class TransactedConsumerSupport extends CamelTestSupport {
                 }
 
                 // Our test consumer route
-                from(destinationName + "?transacted=true&consumerCount="
-                     + consumerCount)
+                from(destinationName + "?transacted=true&concurrentConsumers="
+                     + concurrentConsumers)
                              .id("consumer.route." + routeNumber)
                              // first consume all the messages that are not redelivered
                              .choice().when(header("JMSRedelivered").isEqualTo("false"))
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumersMultipleRouteTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumersMultipleRouteTest.java
index d8c1587..2075c40 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumersMultipleRouteTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedConsumersMultipleRouteTest.java
@@ -33,13 +33,13 @@ public class TransactedConsumersMultipleRouteTest extends TransactedConsumerSupp
     public void testRoute() throws Exception {
         final String destinationName = "sjms:queue:one.consumer.one.route.test";
         int routeCount = 2;
-        int consumerCount = 1;
+        int concurrentConsumers = 1;
         int messageCount = 20;
         int maxAttemptsCount = 10;
         int totalRedeliverdFalse = 10;
         int totalRedeliveredTrue = 1;
         runTest(destinationName, routeCount, messageCount, totalRedeliverdFalse, totalRedeliveredTrue,
-                consumerCount, maxAttemptsCount);
+                concurrentConsumers, maxAttemptsCount);
     }
 
     @Override
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedQueueConsumerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedQueueConsumerTest.java
index 27ab277..d9bc941 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedQueueConsumerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedQueueConsumerTest.java
@@ -30,13 +30,13 @@ public class TransactedQueueConsumerTest extends TransactedConsumerSupport {
     public void testRoute() throws Exception {
         final String destinationName = "sjms:queue:one.consumer.one.route.tx.test";
         int routeCount = 1;
-        int consumerCount = 1;
+        int concurrentConsumers = 1;
         int messageCount = 20;
         int maxAttemptsCount = 10;
         int totalRedeliverdFalse = 20;
         int totalRedeliveredTrue = 1;
         runTest(destinationName, routeCount, messageCount, totalRedeliverdFalse, totalRedeliveredTrue,
-                consumerCount, maxAttemptsCount);
+                concurrentConsumers, maxAttemptsCount);
     }
 
     @Override
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicConsumerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicConsumerTest.java
index 4afe922..1de48c0 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicConsumerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicConsumerTest.java
@@ -30,14 +30,13 @@ public class TransactedTopicConsumerTest extends TransactedConsumerSupport {
     public void testRoute() throws Exception {
         final String destinationName = "sjms:topic:one.consumer.one.route.tx.test";
         int routeCount = 2;
-        int consumerCount = 1;
-        int batchCount = 1;
+        int concurrentConsumers = 1;
         int messageCount = 20;
         int maxAttemptsCount = 10;
         int totalRedeliverdFalse = 20;
         int totalRedeliveredTrue = 1;
         runTest(destinationName, routeCount, messageCount, totalRedeliverdFalse, totalRedeliveredTrue,
-                consumerCount, maxAttemptsCount);
+                concurrentConsumers, maxAttemptsCount);
     }
 
     @Override
diff --git a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicProducerTest.java b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicProducerTest.java
index 1b98985..dea5a9e 100644
--- a/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicProducerTest.java
+++ b/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/tx/TransactedTopicProducerTest.java
@@ -60,7 +60,7 @@ public class TransactedTopicProducerTest extends JmsTestSupport {
     protected CamelContext createCamelContext() throws Exception {
         CamelContext context = super.createCamelContext();
         SjmsComponent sjms = context.getComponent("sjms", SjmsComponent.class);
-        sjms.setConnectionClientId(CONNECTION_ID);
+        sjms.setClientId(CONNECTION_ID);
         return context;
     }
 
diff --git a/components/camel-sjms2/src/generated/java/org/apache/camel/component/sjms2/Sjms2EndpointUriFactory.java b/components/camel-sjms2/src/generated/java/org/apache/camel/component/sjms2/Sjms2EndpointUriFactory.java
index 0f1fa10..9ac71dc 100644
--- a/components/camel-sjms2/src/generated/java/org/apache/camel/component/sjms2/Sjms2EndpointUriFactory.java
+++ b/components/camel-sjms2/src/generated/java/org/apache/camel/component/sjms2/Sjms2EndpointUriFactory.java
@@ -20,52 +20,60 @@ public class Sjms2EndpointUriFactory extends org.apache.camel.support.component.
     private static final Set<String> PROPERTY_NAMES;
     private static final Set<String> SECRET_PROPERTY_NAMES;
     static {
-        Set<String> props = new HashSet<>(45);
-        props.add("shared");
-        props.add("reconnectBackOff");
-        props.add("connectionCount");
+        Set<String> props = new HashSet<>(53);
+        props.add("includeSentJMSMessageID");
+        props.add("asyncConsumer");
         props.add("mapJmsMessage");
         props.add("synchronous");
-        props.add("connectionResource");
         props.add("includeAllJMSXProperties");
-        props.add("explicitQosEnabled");
-        props.add("transacted");
         props.add("errorHandlerLogStackTrace");
-        props.add("durable");
+        props.add("eagerLoadingOfProperties");
         props.add("timeToLive");
         props.add("bridgeErrorHandler");
-        props.add("jmsKeyFormatStrategy");
         props.add("deliveryMode");
-        props.add("headerFilterStrategy");
+        props.add("transferException");
         props.add("exceptionListener");
-        props.add("destinationName");
-        props.add("messageCreatedStrategy");
-        props.add("asyncStopListener");
         props.add("destinationType");
         props.add("asyncStartListener");
-        props.add("requestTimeout");
-        props.add("allowNullBody");
-        props.add("replyToDeliveryPersistent");
-        props.add("disableReplyTo");
-        props.add("reconnectOnError");
-        props.add("consumerCount");
+        props.add("eagerPoisonBody");
+        props.add("replyToConcurrentConsumers");
         props.add("destinationCreationStrategy");
-        props.add("exchangePattern");
+        props.add("disableTimeToLive");
         props.add("messageSelector");
         props.add("deliveryPersistent");
-        props.add("preserveMessageQos");
         props.add("priority");
+        props.add("concurrentConsumers");
         props.add("acknowledgementMode");
         props.add("lazyStartProducer");
-        props.add("transactionCommitStrategy");
-        props.add("connectionFactory");
         props.add("replyTo");
         props.add("replyToOverride");
         props.add("errorHandlerLoggingLevel");
-        props.add("sharedJMSSession");
         props.add("durableSubscriptionId");
         props.add("subscriptionId");
         props.add("exceptionHandler");
+        props.add("shared");
+        props.add("connectionCount");
+        props.add("explicitQosEnabled");
+        props.add("transacted");
+        props.add("autoStartup");
+        props.add("durable");
+        props.add("jmsKeyFormatStrategy");
+        props.add("headerFilterStrategy");
+        props.add("destinationName");
+        props.add("messageCreatedStrategy");
+        props.add("asyncStopListener");
+        props.add("requestTimeout");
+        props.add("allowNullBody");
+        props.add("replyToDeliveryPersistent");
+        props.add("disableReplyTo");
+        props.add("recoveryInterval");
+        props.add("exchangePattern");
+        props.add("preserveMessageQos");
+        props.add("replyToType");
+        props.add("testConnectionOnStartup");
+        props.add("connectionFactory");
+        props.add("replyToSameDestinationAllowed");
+        props.add("sharedJMSSession");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
         SECRET_PROPERTY_NAMES = Collections.emptySet();
     }
diff --git a/components/camel-sjms2/src/generated/resources/org/apache/camel/component/sjms2/sjms2.json b/components/camel-sjms2/src/generated/resources/org/apache/camel/component/sjms2/sjms2.json
index 8117c35..4fe444a 100644
--- a/components/camel-sjms2/src/generated/resources/org/apache/camel/component/sjms2/sjms2.json
+++ b/components/camel-sjms2/src/generated/resources/org/apache/camel/component/sjms2/sjms2.json
@@ -25,21 +25,17 @@
     "connectionCount": { "kind": "property", "displayName": "Connection Count", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1", "description": "The maximum number of connections available to endpoints started under this component" },
     "connectionFactory": { "kind": "property", "displayName": "Connection Factory", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "javax.jms.ConnectionFactory", "deprecated": false, "autowired": true, "secret": false, "description": "A ConnectionFactory is required to enable the SjmsComponent. It can be set directly or set set as part of a ConnectionResource." },
     "bridgeErrorHandler": { "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a me [...]
-    "reconnectBackOff": { "kind": "property", "displayName": "Reconnect Back Off", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5000, "description": "Backoff in millis on consumer pool reconnection attempts" },
-    "reconnectOnError": { "kind": "property", "displayName": "Reconnect On Error", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Try to apply reconnection logic on consumer pool" },
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during star [...]
     "autowiredEnabled": { "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which t [...]
-    "connectionClientId": { "kind": "property", "displayName": "Connection Client Id", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionMaxWait": { "kind": "property", "displayName": "Connection Max Wait", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5000, "description": "The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionResource": { "kind": "property", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details." },
-    "connectionTestOnBorrow": { "kind": "property", "displayName": "Connection Test On Borrow", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used." },
     "destinationCreationStrategy": { "kind": "property", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "jmsKeyFormatStrategy": { "kind": "property", "displayName": "Jms Key Format Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The defau [...]
     "messageCreatedStrategy": { "kind": "property", "displayName": "Message Created Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.MessageCreatedStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message." },
+    "recoveryInterval": { "kind": "property", "displayName": "Recovery Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds." },
+    "replyToOnTimeoutMaxConcurrentConsumers": { "kind": "property", "displayName": "Reply To On Timeout Max Concurrent Consumers", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request\/reply over JMS." },
+    "requestTimeoutCheckerInterval": { "kind": "property", "displayName": "Request Timeout Checker Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Configures how often Camel should check for timed out Exchanges when doing request\/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeou [...]
     "headerFilterStrategy": { "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." },
-    "connectionPassword": { "kind": "property", "displayName": "Connection Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "connectionUsername": { "kind": "property", "displayName": "Connection Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource." },
-    "transactionCommitStrategy": { "kind": "property", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch." }
+    "password": { "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." },
+    "username": { "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Username to use with the ConnectionFactory. You can also configure username\/password directly on the ConnectionFactory." }
   },
   "properties": {
     "destinationType": { "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" },
@@ -47,34 +43,40 @@
     "acknowledgementMode": { "kind": "parameter", "displayName": "Acknowledgement Mode", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.SessionAcknowledgementType", "enum": [ "SESSION_TRANSACTED", "CLIENT_ACKNOWLEDGE", "AUTO_ACKNOWLEDGE", "DUPS_OK_ACKNOWLEDGE" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "AUTO_ACKNOWLEDGE", "description": "The JMS acknowledgement name, which is one of:  [...]
     "disableReplyTo": { "kind": "parameter", "displayName": "Disable Reply To", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether Camel ignores the JMSReplyTo header in messages. If true, Camel does not send a reply back to the destination specified in the JMSReplyTo header. You can use this option if you want Camel to consume from  [...]
     "replyTo": { "kind": "parameter", "displayName": "Reply To", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Provides an explicit ReplyTo destination (overrides any incoming value of Message.getJMSReplyTo() in consumer)." },
+    "testConnectionOnStartup": { "kind": "parameter", "displayName": "Test Connection On Startup", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to test the connection on startup. This ensures that when Camel starts that all the JMS consumers have a valid connection to the JMS broker. If a connection cannot be granted then Camel [...]
+    "asyncConsumer": { "kind": "parameter", "displayName": "Async Consumer", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asy [...]
+    "autoStartup": { "kind": "parameter", "displayName": "Auto Startup", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether the consumer container should auto-startup." },
     "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a m [...]
-    "consumerCount": { "kind": "parameter", "displayName": "Consumer Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the number of consumer listeners used for this endpoint." },
+    "concurrentConsumers": { "kind": "parameter", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when consuming from JMS (not for request\/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads. When doing r [...]
     "durable": { "kind": "parameter", "displayName": "Durable", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets topic consumer to durable." },
     "durableSubscriptionId": { "kind": "parameter", "displayName": "Durable Subscription Id", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the durable subscription Id required for durable topics." },
-    "reconnectBackOff": { "kind": "parameter", "displayName": "Reconnect Back Off", "group": "consumer", "label": "consumer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Backoff in millis on consumer pool reconnection attempts" },
-    "reconnectOnError": { "kind": "parameter", "displayName": "Reconnect On Error", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Try to apply reconnection logic on consumer pool" },
     "replyToDeliveryPersistent": { "kind": "parameter", "displayName": "Reply To Delivery Persistent", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to use persistent delivery by default for replies." },
     "shared": { "kind": "parameter", "displayName": "Shared", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets the consumer to shared." },
     "subscriptionId": { "kind": "parameter", "displayName": "Subscription Id", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the subscription Id, required for durable or shared topics." },
-    "synchronous": { "kind": "parameter", "displayName": "Synchronous", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported)." },
+    "eagerLoadingOfProperties": { "kind": "parameter", "displayName": "Eager Loading Of Properties", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes c [...]
+    "eagerPoisonBody": { "kind": "parameter", "displayName": "Eager Poison Body", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Poison JMS message due to ${exception.message}", "description": "If eagerLoadingOfProperties is enabled and the JMS message payload (JMS body or JMS properties) is poison (cannot be read\/mapped), then se [...]
     "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...]
     "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
     "messageSelector": { "kind": "parameter", "displayName": "Message Selector", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the JMS Message selector syntax." },
+    "replyToSameDestinationAllowed": { "kind": "parameter", "displayName": "Reply To Same Destination Allowed", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a JMS consumer is allowed to send a reply message to the same destination that the consumer is using to consume from. This prevents an endless loop by c [...]
     "deliveryMode": { "kind": "parameter", "displayName": "Delivery Mode", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "enum": [ "1", "2" ], "deprecated": false, "autowired": false, "secret": false, "description": "Specifies the delivery mode to be used. Possible values are those defined by javax.jms.DeliveryMode. NON_PERSISTENT = 1 and PERSISTENT = 2." },
     "deliveryPersistent": { "kind": "parameter", "displayName": "Delivery Persistent", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether persistent delivery is used by default." },
     "explicitQosEnabled": { "kind": "parameter", "displayName": "Explicit Qos Enabled", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Set if the deliveryMode, priority or timeToLive qualities of service should be used when sending messages. This option is based on Spring's JmsTemplate. The deliveryMode, priority and timeToLi [...]
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during sta [...]
     "preserveMessageQos": { "kind": "parameter", "displayName": "Preserve Message Qos", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDelive [...]
     "priority": { "kind": "parameter", "displayName": "Priority", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "enum": [ "1", "2", "3", "4", "5", "6", "7", "8", "9" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": 4, "description": "Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in orde [...]
+    "replyToConcurrentConsumers": { "kind": "parameter", "displayName": "Reply To Concurrent Consumers", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Specifies the default number of concurrent consumers when doing request\/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up\/down of threads." },
     "replyToOverride": { "kind": "parameter", "displayName": "Reply To Override", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination." },
+    "replyToType": { "kind": "parameter", "displayName": "Reply To Type", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.ReplyToType", "enum": [ "Temporary", "Exclusive" ], "deprecated": false, "autowired": false, "secret": false, "description": "Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request\/reply over JMS. Possible values are: Temporary, Shared, or Exclusi [...]
     "requestTimeout": { "kind": "parameter", "displayName": "Request Timeout", "group": "producer", "label": "producer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeou [...]
     "timeToLive": { "kind": "parameter", "displayName": "Time To Live", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": -1, "description": "When sending messages, specifies the time-to-live of the message (in milliseconds)." },
     "allowNullBody": { "kind": "parameter", "displayName": "Allow Null Body", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown." },
+    "disableTimeToLive": { "kind": "parameter", "displayName": "Disable Time To Live", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Use this option to force disabling time to live. For example when you do request\/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message  [...]
+    "includeSentJMSMessageID": { "kind": "parameter", "displayName": "Include Sent JMSMessage ID", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was  [...]
     "asyncStartListener": { "kind": "parameter", "displayName": "Async Start Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and\/o [...]
     "asyncStopListener": { "kind": "parameter", "displayName": "Async Stop Listener", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to stop the consumer message listener asynchronously, when stopping a route." },
     "connectionCount": { "kind": "parameter", "displayName": "Connection Count", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": true, "autowired": false, "secret": false, "description": "The maximum number of connections available to this endpoint" },
     "connectionFactory": { "kind": "parameter", "displayName": "Connection Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ConnectionFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any" },
-    "connectionResource": { "kind": "parameter", "displayName": "Connection Resource", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.ConnectionResource", "deprecated": false, "autowired": false, "secret": false, "description": "Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any" },
     "destinationCreationStrategy": { "kind": "parameter", "displayName": "Destination Creation Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.DestinationCreationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom DestinationCreationStrategy." },
     "exceptionListener": { "kind": "parameter", "displayName": "Exception Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.jms.ExceptionListener", "deprecated": false, "autowired": false, "secret": false, "description": "Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions." },
     "headerFilterStrategy": { "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter header to and from Camel message." },
@@ -82,10 +84,12 @@
     "jmsKeyFormatStrategy": { "kind": "parameter", "displayName": "Jms Key Format Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides two implementations out of the box: default and pass [...]
     "mapJmsMessage": { "kind": "parameter", "displayName": "Map Jms Message", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether Camel should auto map the received JMS message to a suited payload type, such as javax.jms.TextMessage to a String etc. See section about how mapping works below for more details." },
     "messageCreatedStrategy": { "kind": "parameter", "displayName": "Message Created Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.jms.MessageCreatedStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message." },
+    "recoveryInterval": { "kind": "parameter", "displayName": "Recovery Interval", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "5000", "description": "Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds." },
+    "synchronous": { "kind": "parameter", "displayName": "Synchronous", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported)." },
+    "transferException": { "kind": "parameter", "displayName": "Transfer Exception", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If enabled and you are using Request Reply messaging (InOut) and an Exchange failed on the consumer side, then the caused Exception will be send back in response as a javax.jms.ObjectMessage. If the client i [...]
     "errorHandlerLoggingLevel": { "kind": "parameter", "displayName": "Error Handler Logging Level", "group": "logging", "label": "consumer,logging", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "WARN", "description": "Allows to configure the default errorHandler logging level for logging uncaught exceptions." },
     "errorHandlerLogStackTrace": { "kind": "parameter", "displayName": "Error Handler Log Stack Trace", "group": "logging", "label": "consumer,logging", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Allows to control whether stacktraces should be logged or not, by the default errorHandler." },
     "transacted": { "kind": "parameter", "displayName": "Transacted", "group": "transaction", "label": "transaction", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to use transacted mode" },
-    "transactionCommitStrategy": { "kind": "parameter", "displayName": "Transaction Commit Strategy", "group": "transaction", "label": "transaction", "required": false, "type": "object", "javaType": "org.apache.camel.component.sjms.TransactionCommitStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the commit strategy." },
     "sharedJMSSession": { "kind": "parameter", "displayName": "Shared JMSSession", "group": "transaction (advanced)", "label": "transaction,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS provi [...]
   }
 }
diff --git a/components/camel-sjms2/src/main/docs/sjms2-component.adoc b/components/camel-sjms2/src/main/docs/sjms2-component.adoc
index 133a721..a638296 100644
--- a/components/camel-sjms2/src/main/docs/sjms2-component.adoc
+++ b/components/camel-sjms2/src/main/docs/sjms2-component.adoc
@@ -12,33 +12,22 @@ include::{cq-version}@camel-quarkus:ROOT:partial$reference/components/sjms2.adoc
 
 *{component-header}*
 
-The Simple JMS 2.0 Component, or SJMS2, is a JMS client for use with Camel
-that uses well known best practices when it comes to JMS client creation
-and configuration. SJMS2 contains a brand new JMS 2.0 client API written
-explicitly for Camel eliminating third party messaging implementations
-keeping it light and resilient. The following features is included:
-
-* Standard Queue and Topic Support (Durable & Non-Durable)
-* InOnly & InOut MEP Support
-* Asynchronous Producer and Consumer Processing
-* Internal JMS Transaction Support
-
-Additional key features include:
-
-* Plugable Connection Resource Management
-* Session, Consumer, & Producer Pooling & Caching Management
-* Batch Consumers and Producers
-* Transacted Batch Consumers & Producers
-* Support for Customizable Transaction Commit Strategies (Local JMS
-Transactions only)
+The Simple JMS Component is a JMS component that only uses JMS APIs
+and no 3rd-party framework such as Spring JMS.
 
-[NOTE]
-====
-*Why the S in SJMS*
+The component was reworked from Camel 3.8 onwards
+to be similar to the existing Camel JMS component that is based on Spring JMS.
 
-S stands for Simple and Standard and Springless. Also camel-jms was
-already taken.
-====
+The reason is to offer many of the same features and functionality from the JMS component,
+but for users that requires lightweight without having to include the Spring Framework.
+
+There are some advanced features in the Spring JMS component that has been omitted, such as
+shared queues for request/reply. Spring JMS offers fine grained tunings for concurrency settings,
+which can be tweaked for dynamic scaling up and down depending on load. This is a special feature in Spring JMS
+that would require substantial code to implement in SJMS2.
+
+The SJMS2 component does not support for Spring or JTA Transaction, however support for internal local transactions
+is supported using JMS or Transaction or Client Acknowledge Mode. See more further below.
 
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
@@ -55,7 +44,7 @@ for this component:
 
 == URI format
 
-[source]
+[source,text]
 ----
 sjms2:[queue:|topic:]destinationName[?options]
 ----
@@ -64,14 +53,14 @@ Where `destinationName` is a JMS queue or topic name. By default, the
 `destinationName` is interpreted as a queue name. For example, to
 connect to the queue, `FOO.BAR` use:
 
-[source]
+[source,text]
 ----
 sjms2:FOO.BAR
 ----
 
 You can include the optional `queue:` prefix, if you prefer:
 
-[source]
+[source,text]
 ----
 sjms2:queue:FOO.BAR
 ----
@@ -79,7 +68,7 @@ sjms2:queue:FOO.BAR
 To connect to a topic, you _must_ include the `topic:` prefix. For
 example, to connect to the topic, `Stocks.Prices`, use:
 
-[source]
+[source,text]
 ----
 sjms2:topic:Stocks.Prices
 ----
@@ -89,11 +78,8 @@ You append query options to the URI using the following format,
 
 == Component Options and Configurations
 
-
-
-
 // component options: START
-The Simple JMS2 component supports 18 options, which are listed below.
+The Simple JMS2 component supports 14 options, which are listed below.
 
 
 
@@ -103,31 +89,21 @@ The Simple JMS2 component supports 18 options, which are listed below.
 | *connectionCount* (common) | The maximum number of connections available to endpoints started under this component | 1 | Integer
 | *connectionFactory* (common) | *Autowired* A ConnectionFactory is required to enable the SjmsComponent. It can be set directly or set set as part of a ConnectionResource. |  | ConnectionFactory
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
-| *reconnectBackOff* (consumer) | Backoff in millis on consumer pool reconnection attempts | 5000 | long
-| *reconnectOnError* (consumer) | Try to apply reconnection logic on consumer pool | true | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. | true | boolean
-| *connectionClientId* (advanced) | The client ID to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionMaxWait* (advanced) | The max wait time in millis to block and wait on free connection when the pool is exhausted when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. | 5000 | long
-| *connectionResource* (advanced) | A ConnectionResource is an interface that allows for customization and container control of the ConnectionFactory. See Plugable Connection Resource Management for further details. |  | ConnectionResource
-| *connectionTestOnBorrow* (advanced) | When using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource then should each javax.jms.Connection be tested before being used. | true | boolean
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *jmsKeyFormatStrategy* (advanced) | Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides one implementation out of the box: default. The default strategy will safely marshal dots and hyphens (. and -). Can be used for JMS brokers which do not care whether JMS header keys contain illegal characters. You can provide your own implementation of the org.apache.camel.component.jms.JmsKeyFormatStrategy and refer to it using  [...]
 | *messageCreatedStrategy* (advanced) | To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message. |  | MessageCreatedStrategy
+| *recoveryInterval* (advanced) | Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds. | 5000 | long
+| *replyToOnTimeoutMaxConcurrent{zwsp}Consumers* (advanced) | Specifies the maximum number of concurrent consumers for continue routing when timeout occurred when using request/reply over JMS. | 1 | int
+| *requestTimeoutCheckerInterval* (advanced) | Configures how often Camel should check for timed out Exchanges when doing request/reply over JMS. By default Camel checks once per second. But if you must react faster when a timeout occurs, then you can lower this interval, to check more frequently. The timeout is determined by the option requestTimeout. | 1000 | long
 | *headerFilterStrategy* (filter) | To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
-| *connectionPassword* (security) | The password to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *connectionUsername* (security) | The username to use when creating javax.jms.Connection when using the default org.apache.camel.component.sjms.jms.ConnectionFactoryResource. |  | String
-| *transactionCommitStrategy* (transaction) | To configure which kind of commit strategy to use. Camel provides two implementations out of the box, default and batch. |  | TransactionCommitStrategy
+| *password* (security) | Password to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
+| *username* (security) | Username to use with the ConnectionFactory. You can also configure username/password directly on the ConnectionFactory. |  | String
 |===
 // component options: END
 
 
-
-
-
-
-
-
 // endpoint options: START
 The Simple JMS2 endpoint is configured using URI syntax:
 
@@ -148,7 +124,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (43 parameters):
+=== Query Parameters (51 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -157,34 +133,40 @@ with the following path and query parameters:
 | *acknowledgementMode* (common) | The JMS acknowledgement name, which is one of: SESSION_TRANSACTED, CLIENT_ACKNOWLEDGE, AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE. There are 4 enums and the value can be one of: SESSION_TRANSACTED, CLIENT_ACKNOWLEDGE, AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE | AUTO_ACKNOWLEDGE | SessionAcknowledgementType
 | *disableReplyTo* (common) | Specifies whether Camel ignores the JMSReplyTo header in messages. If true, Camel does not send a reply back to the destination specified in the JMSReplyTo header. You can use this option if you want Camel to consume from a route and you do not want Camel to automatically send back a reply message because another component in your code handles the reply message. You can also use this option if you want to use Camel as a proxy between different message broker [...]
 | *replyTo* (common) | Provides an explicit ReplyTo destination (overrides any incoming value of Message.getJMSReplyTo() in consumer). |  | String
+| *testConnectionOnStartup* (common) | Specifies whether to test the connection on startup. This ensures that when Camel starts that all the JMS consumers have a valid connection to the JMS broker. If a connection cannot be granted then Camel throws an exception on startup. This ensures that Camel is not started with failed connections. The JMS producers is tested as well. | false | boolean
+| *asyncConsumer* (consumer) | Whether the JmsConsumer processes the Exchange asynchronously. If enabled then the JmsConsumer may pickup the next message from the JMS queue, while the previous message is being processed asynchronously (by the Asynchronous Routing Engine). This means that messages may be processed not 100% strictly in order. If disabled (as default) then the Exchange is fully processed before the JmsConsumer will pickup the next message from the JMS queue. Note if transac [...]
+| *autoStartup* (consumer) | Specifies whether the consumer container should auto-startup. | true | boolean
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
-| *consumerCount* (consumer) | Sets the number of consumer listeners used for this endpoint. | 1 | int
+| *concurrentConsumers* (consumer) | Specifies the default number of concurrent consumers when consuming from JMS (not for request/reply over JMS). See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. When doing request/reply over JMS then the option replyToConcurrentConsumers is used to control number of concurrent consumers on the reply message listener. | 1 | int
 | *durable* (consumer) | Sets topic consumer to durable. | false | boolean
 | *durableSubscriptionId* (consumer) | Sets the durable subscription Id required for durable topics. |  | String
-| *reconnectBackOff* (consumer) | Backoff in millis on consumer pool reconnection attempts | 5000 | long
-| *reconnectOnError* (consumer) | Try to apply reconnection logic on consumer pool | true | boolean
 | *replyToDeliveryPersistent* (consumer) | Specifies whether to use persistent delivery by default for replies. | true | boolean
 | *shared* (consumer) | Sets the consumer to shared. | false | boolean
 | *subscriptionId* (consumer) | Sets the subscription Id, required for durable or shared topics. |  | String
-| *synchronous* (consumer) | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). | true | boolean
+| *eagerLoadingOfProperties* (consumer) | Enables eager loading of JMS properties and payload as soon as a message is loaded which generally is inefficient as the JMS properties may not be required but sometimes can catch early any issues with the underlying JMS provider and the use of JMS properties. See also the option eagerPoisonBody. | false | boolean
+| *eagerPoisonBody* (consumer) | If eagerLoadingOfProperties is enabled and the JMS message payload (JMS body or JMS properties) is poison (cannot be read/mapped), then set this text as the message body instead so the message can be processed (the cause of the poison are already stored as exception on the Exchange). This can be turned off by setting eagerPoisonBody=false. See also the option eagerLoadingOfProperties. | Poison JMS message due to ${exception.message} | String
 | *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
 | *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. There are 3 enums and the value can be one of: InOnly, InOut, InOptionalOut |  | ExchangePattern
 | *messageSelector* (consumer) | Sets the JMS Message selector syntax. |  | String
+| *replyToSameDestinationAllowed* (consumer) | Whether a JMS consumer is allowed to send a reply message to the same destination that the consumer is using to consume from. This prevents an endless loop by consuming and sending back the same message to itself. | false | boolean
 | *deliveryMode* (producer) | Specifies the delivery mode to be used. Possible values are those defined by javax.jms.DeliveryMode. NON_PERSISTENT = 1 and PERSISTENT = 2. There are 2 enums and the value can be one of: 1, 2 |  | Integer
 | *deliveryPersistent* (producer) | Specifies whether persistent delivery is used by default. | true | boolean
 | *explicitQosEnabled* (producer) | Set if the deliveryMode, priority or timeToLive qualities of service should be used when sending messages. This option is based on Spring's JmsTemplate. The deliveryMode, priority and timeToLive options are applied to the current endpoint. This contrasts with the preserveMessageQos option, which operates at message granularity, reading QoS properties exclusively from the Camel In message headers. | false | Boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *preserveMessageQos* (producer) | Set to true, if you want to send message using the QoS settings specified on the message, instead of the QoS settings on the JMS endpoint. The following three headers are considered JMSPriority, JMSDeliveryMode, and JMSExpiration. You can provide all or only some of them. If not provided, Camel will fall back to use the values from the endpoint instead. So, when using this option, the headers override the values from the endpoint. The explicitQosEnable [...]
 | *priority* (producer) | Values greater than 1 specify the message priority when sending (where 1 is the lowest priority and 9 is the highest). The explicitQosEnabled option must also be enabled in order for this option to have any effect. There are 9 enums and the value can be one of: 1, 2, 3, 4, 5, 6, 7, 8, 9 | 4 | int
+| *replyToConcurrentConsumers* (producer) | Specifies the default number of concurrent consumers when doing request/reply over JMS. See also the maxMessagesPerTask option to control dynamic scaling up/down of threads. | 1 | int
 | *replyToOverride* (producer) | Provides an explicit ReplyTo destination in the JMS message, which overrides the setting of replyTo. It is useful if you want to forward the message to a remote Queue and receive the reply message from the ReplyTo destination. |  | String
+| *replyToType* (producer) | Allows for explicitly specifying which kind of strategy to use for replyTo queues when doing request/reply over JMS. Possible values are: Temporary, Shared, or Exclusive. By default Camel will use temporary queues. However if replyTo has been configured, then Shared is used by default. This option allows you to use exclusive queues instead of shared ones. See Camel JMS documentation for more details, and especially the notes about the implications if running  [...]
 | *requestTimeout* (producer) | The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds). The default is 20 seconds. You can include the header CamelJmsRequestTimeout to override this endpoint configured timeout value, and thus have per message individual timeout values. See also the requestTimeoutCheckerInterval option. | 20000 | long
 | *timeToLive* (producer) | When sending messages, specifies the time-to-live of the message (in milliseconds). | -1 | long
 | *allowNullBody* (producer) | Whether to allow sending messages with no body. If this option is false and the message body is null, then an JMSException is thrown. | true | boolean
+| *disableTimeToLive* (producer) | Use this option to force disabling time to live. For example when you do request/reply over JMS, then Camel will by default use the requestTimeout value as time to live on the message being sent. The problem is that the sender and receiver systems have to have their clocks synchronized, so they are in sync. This is not always so easy to archive. So you can use disableTimeToLive=true to not set a time to live value on the sent message. Then the message w [...]
+| *includeSentJMSMessageID* (producer) | Only applicable when sending to JMS destination using InOnly (eg fire and forget). Enabling this option will enrich the Camel Exchange with the actual JMSMessageID that was used by the JMS client when the message was sent to the JMS destination. | false | boolean
 | *asyncStartListener* (advanced) | Whether to startup the consumer message listener asynchronously, when starting a route. For example if a JmsConsumer cannot get a connection to a remote JMS broker, then it may block while retrying and/or failover. This will cause Camel to block while starting routes. By setting this option to true, you will let routes startup, while the JmsConsumer connects to the JMS broker using a dedicated thread in asynchronous mode. If this option is used, then b [...]
 | *asyncStopListener* (advanced) | Whether to stop the consumer message listener asynchronously, when stopping a route. | false | boolean
 | *connectionCount* (advanced) | *Deprecated* The maximum number of connections available to this endpoint |  | Integer
 | *connectionFactory* (advanced) | Initializes the connectionFactory for the endpoint, which takes precedence over the component's connectionFactory, if any |  | ConnectionFactory
-| *connectionResource* (advanced) | Initializes the connectionResource for the endpoint, which takes precedence over the component's connectionResource, if any |  | ConnectionResource
 | *destinationCreationStrategy* (advanced) | To use a custom DestinationCreationStrategy. |  | DestinationCreationStrategy
 | *exceptionListener* (advanced) | Specifies the JMS Exception Listener that is to be notified of any underlying JMS exceptions. |  | ExceptionListener
 | *headerFilterStrategy* (advanced) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
@@ -192,325 +174,112 @@ with the following path and query parameters:
 | *jmsKeyFormatStrategy* (advanced) | Pluggable strategy for encoding and decoding JMS keys so they can be compliant with the JMS specification. Camel provides two implementations out of the box: default and passthrough. The default strategy will safely marshal dots and hyphens (. and -). The passthrough strategy leaves the key as is. Can be used for JMS brokers which do not care whether JMS header keys contain illegal characters. You can provide your own implementation of the org.apache [...]
 | *mapJmsMessage* (advanced) | Specifies whether Camel should auto map the received JMS message to a suited payload type, such as javax.jms.TextMessage to a String etc. See section about how mapping works below for more details. | true | boolean
 | *messageCreatedStrategy* (advanced) | To use the given MessageCreatedStrategy which are invoked when Camel creates new instances of javax.jms.Message objects when Camel is sending a JMS message. |  | MessageCreatedStrategy
+| *recoveryInterval* (advanced) | Specifies the interval between recovery attempts, i.e. when a connection is being refreshed, in milliseconds. The default is 5000 ms, that is, 5 seconds. | 5000 | long
+| *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+| *transferException* (advanced) | If enabled and you are using Request Reply messaging (InOut) and an Exchange failed on the consumer side, then the caused Exception will be send back in response as a javax.jms.ObjectMessage. If the client is Camel, the returned Exception is rethrown. This allows you to use Camel JMS as a bridge in your routing - for example, using persistent queues to enable robust routing. Notice that if you also have transferExchange enabled, this option takes preced [...]
 | *errorHandlerLoggingLevel* (logging) | Allows to configure the default errorHandler logging level for logging uncaught exceptions. There are 6 enums and the value can be one of: TRACE, DEBUG, INFO, WARN, ERROR, OFF | WARN | LoggingLevel
 | *errorHandlerLogStackTrace* (logging) | Allows to control whether stacktraces should be logged or not, by the default errorHandler. | true | boolean
 | *transacted* (transaction) | Specifies whether to use transacted mode | false | boolean
-| *transactionCommitStrategy* (transaction) | Sets the commit strategy. |  | TransactionCommitStrategy
 | *sharedJMSSession* (transaction) | Specifies whether to share JMS session with other SJMS endpoints. Turn this off if your route is accessing to multiple JMS providers. If you need transaction against multiple JMS providers, use jms component to leverage XA transaction. | true | boolean
 |===
 // endpoint options: END
 
 
+Below is an example of how to configure the `SjmsComponent` with its
+required `ConnectionFactory` provider.
 
 
+== Reuse endpoint and send to different destinations computed at runtime
 
+If you need to send messages to a lot of different JMS destinations, it
+makes sense to reuse a SJMS endpoint and specify the real destination in
+a message header. This allows Camel to reuse the same endpoint, but send
+to different destinations. This greatly reduces the number of endpoints
+created and economizes on memory and thread resources.
 
-Below is an example of how to configure the `Sjms2Component` with its
-required `ConnectionFactory` provider. It will create a single connection
-by default and store it using the component's internal pooling APIs to
-ensure that it is able to service Session creation requests in a thread
-safe manner.
-
-[source,java]
-----
-Sjms2Component component = new Sjms2Component();
-component.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-getContext().addComponent("sjms2", component);
-----
-
-For a SJMS2 component that is required to support a durable subscription,
-you can override the default `ConnectionFactoryResource` instance and set
-the `clientId` property.
-
-[source,java]
-----
-ConnectionFactoryResource connectionResource = new ConnectionFactoryResource();
-connectionResource.setConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61616"));
-connectionResource.setClientId("myclient-id");
-
-Sjms2Component component = new Sjms2Component();
-component.setConnectionResource(connectionResource);
-component.setMaxConnections(1);
-----
+TIP: Using xref:{eip-vc}:eips:toD-eip.adoc[toD] is easier than specifying the dynamic destination with a header
 
-== Producer Usage
+You can specify the destination in the following headers:
 
-=== InOnly Producer - (Default)
+[width="100%",cols="10%,10%,80%",options="header",]
+|=====================================================================
+|Header |Type |Description
+|`CamelJmsDestinationName` |`String` |The destination name.
+|=====================================================================
 
-The _InOnly_ producer is the default behavior of the SJMS2 Producer
-Endpoint.
+For example, the following route shows how you can compute a destination
+at run time and use it to override the destination appearing in the JMS
+URL:
 
 [source,java]
-----
-from("direct:start")
-    .to("sjms2:queue:bar");
-----
-
-=== InOut Producer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI. By default it will use a dedicated TemporaryQueue for each
-consumer.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms2:queue:bar?exchangePattern=InOut");
-----
-
-You can specify a `replyTo` though which can provide a better
-monitor point.
-
-[source,java]
-----
-from("direct:start")
-    .to("sjms2:queue:bar?replyTo=my.reply.to.queue");
-----
+--------------------------------
+from("file://inbox")
+  .to("bean:computeDestination")
+  .to("sjms2:queue:dummy");
+--------------------------------
 
-== Consumer Usage
+The queue name, `dummy`, is just a placeholder. It must be provided as
+part of the JMS endpoint URL, but it will be ignored in this example.
 
-=== Durable Shared Subscription
-
-To create a durable subscription that can be shared between one or more consumers.
-Use a JMS 2.0 compliant connection factory and specify a common subscriptionId. Then set the subscription properties durable and shared to true.
-
-[source,java]
-----
-from("sjms2:topic:foo?consumerCount=3&subscriptionId=bar&durable=true&shared=true")
-    .to("mock:result");
-
-from("sjms2:topic:foo?consumerCount=2&subscriptionId=bar&durable=true&shared=true")
-    .to("mock:result");
-----
-
-=== InOnly Consumer - (Default)
-
-The _InOnly_ xonsumer is the default Exchange behavior of the SJMS2
-Consumer Endpoint.
+In the `computeDestination` bean, specify the real destination by
+setting the `CamelJmsDestinationName` header as follows:
 
 [source,java]
-----
-from("sjms2:queue:bar")
-    .to("mock:result");
-----
-
-=== InOut Consumer
-
-To enable _InOut_ behavior append the `exchangePattern` attribute to the
-URI.
-
-[source,java]
-----
-from("sjms2:queue:in.out.test?exchangePattern=InOut")
-    .transform(constant("Bye Camel"));
-----
-
-== Advanced Usage Notes
-
-=== Plugable Connection Resource Management [[SJMS2-connectionresource]]
-
-SJMS2 provides JMS
-http://docs.oracle.com/javaee/5/api/javax/jms/Connection.html[`Connection`]
-resource management through built-in connection pooling. This eliminates
-the need to depend on third party API pooling logic. However there may
-be times that you are required to use an external Connection resource
-manager such as those provided by J2EE or OSGi containers. For this SJMS2
-provides an interface that can be used to override the internal SJMS2
-Connection pooling capabilities. This is accomplished through the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionResource.java[`ConnectionResource`]
-interface.
-
-The
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/jms/ConnectionResource.java[`ConnectionResource`]
-provides methods for borrowing and returning Connections as needed is
-the contract used to provide
-http://docs.oracle.com/javaee/5/api/javax/jms/Connection.html[`Connection`]
-pools to the SJMS2 component. A user should use when it is necessary to
-integrate SJMS2 with an external connection pooling manager.
-
-It is recommended though that for standard
-http://docs.oracle.com/javaee/5/api/javax/jms/ConnectionFactory.html[`ConnectionFactory`]
-providers you use the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/it/ConnectionResourceIT.java[`ConnectionFactoryResource`]
-implementation that is provided with SJMS2 as-is or extend as it is
-optimized for this component.
-
-Below is an example of using the plugable ConnectionResource with the
-ActiveMQ `PooledConnectionFactory`:
-
-[source,java]
-----
-public class AMQConnectionResource implements ConnectionResource {
-    private PooledConnectionFactory pcf;
-
-    public AMQConnectionResource(String connectString, int maxConnections) {
-        super();
-        pcf = new PooledConnectionFactory(connectString);
-        pcf.setMaxConnections(maxConnections);
-        pcf.start();
-    }
-
-    public void stop() {
-        pcf.stop();
-    }
-
-    @Override
-    public Connection borrowConnection() throws Exception {
-        Connection answer = pcf.createConnection();
-        answer.start();
-        return answer;
-    }
-
-    @Override
-    public Connection borrowConnection(long timeout) throws Exception {
-        // SNIPPED...
-    }
-
-    @Override
-    public void returnConnection(Connection connection) throws Exception {
-        // Do nothing since there isn't a way to return a Connection
-        // to the instance of PooledConnectionFactory
-        log.info("Connection returned");
-    }
+-------------------------------------------------------------------------
+public void setJmsHeader(Exchange exchange) {
+   String id = ....
+   exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id");
 }
-----
-
-Then pass in the `ConnectionResource` to the `Sjms2Component`:
-
-[source,java]
-----
-CamelContext camelContext = new DefaultCamelContext();
-AMQConnectionResource pool = new AMQConnectionResource("tcp://localhost:33333", 1);
-Sjms2Component component = new Sjms2Component();
-component.setConnectionResource(pool);
-camelContext.addComponent("sjms2", component);
-----
-
-To see the full example of its usage please refer to the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/test/java/org/apache/camel/component/sjms/it/ConnectionResourceIT.java[`ConnectionResourceIT`].
-
-=== Session, Consumer, & Producer Pooling & Caching Management
-
-Coming soon ...
-
-=== Batch Message Support
+-------------------------------------------------------------------------
 
-The Sjms2Producer supports publishing a collection of messages by
-creating an Exchange that encapsulates a `List`. This Sjms2Producer will
-take then iterate through the contents of the List and publish each
-message individually.
+Then Camel will read this header and use it as the destination instead
+of the one configured on the endpoint. So, in this example Camel sends
+the message to `sjms2:queue:order:2`, assuming the `id` value was 2.
 
-If when producing a batch of messages there is the need to set headers
-that are unique to each message you can use the SJMS2
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/BatchMessage.java[`BatchMessage`]
-class. When the Sjms2Producer encounters a `BatchMessage` list it will
-iterate each `BatchMessage` and publish the included payload and headers.
+Keep in mind that the JMS producer removes both `CamelJmsDestinationName`
+headers from the exchange and do not propagate  them to the created JMS
+message in order to avoid the accidental loops
+in the routes (in scenarios when the message will be forwarded to the
+another JMS endpoint).
 
-Below is an example of using the BatchMessage class. First we create a
-list of `BatchMessage`:
+== Using toD
 
-[source,java]
-----
-List<BatchMessage<String>> messages = new ArrayList<BatchMessage<String>>();
-for (int i = 1; i <= messageCount; i++) {
-    String body = "Hello World " + i;
-    BatchMessage<String> message = new BatchMessage<String>(body, null);
-    messages.add(message);
-}
-----
+If you need to send messages to a lot of different JMS destinations, it
+makes sense to reuse a SJMS2 endpoint and specify the dynamic destinations
+with simple language using xref:{eip-vc}:eips:toD-eip.adoc[toD].
 
-Then publish the list:
+For example suppose you need to send messages to queues with order types,
+then using toD could for example be done as follows:
 
 [source,java]
-----
-template.sendBody("sjms2:queue:batch.queue", messages);
-----
+--------------------------------
+from("direct:order")
+  .toD("sjms2:order-${header.orderType}");
+--------------------------------
 
-=== Customizable Transaction Commit Strategies (Local JMS Transactions only)
-
-SJMS2 provides a developer the means to create a custom and plugable
-transaction strategy through the use of the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/TransactionCommitStrategy.java[`TransactionCommitStrategy`]
-interface. This allows a user to define a unique set of circumstances
-that the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/SessionTransactionSynchronization.java[`SessionTransactionSynchronization`]
-will use to determine when to commit the Session. An example of its use
-is the
-https://svn.apache.org/repos/asf/camel/trunk/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/tx/BatchTransactionCommitStrategy.java[`BatchTransactionCommitStrategy`]
-which is detailed further in the next section.
-
-=== Transacted Batch Consumers & Producers
-
-The SJMS2 component has been designed to support the batching of local JMS
-transactions on both the Producer and Consumer endpoints. How they are
-handled on each is very different though.
-
-The SJMS2 consumer endpoint is a straightforward implementation that will
-process X messages before committing them with the associated Session.
-To enable batched transaction on the consumer first enable transactions
-by setting the `transacted` parameter to true and then adding the
-`transactionBatchCount` and setting it to any value that is greater than
-0. For example the following configuration will commit the Session every
-10 messages:
-
-[source]
-----
-sjms2:queue:transacted.batch.consumer?transacted=true&transactionBatchCount=10
-----
-
-If an exception occurs during the processing of a batch on the consumer
-endpoint, the Session rollback is invoked causing the messages to be
-redelivered to the next available consumer. The counter is also reset to
-0 for the `BatchTransactionCommitStrategy` for the associated Session as
-well. It is the responsibility of the user to ensure they put hooks in
-their processors of batch messages to watch for messages with the
-JMSRedelivered header set to true. This is the indicator that messages
-were rolled back at some point and that a verification of a successful
-processing should occur.
-
-A transacted batch consumer also carries with it an instance of an
-internal timer that waits a default amount of time (5000ms) between
-messages before committing the open transactions on the Session. The
-default value of 5000ms (minimum of 1000ms) should be adequate for most
-use-cases but if further tuning is necessary simply set the
-`transactionBatchTimeout` parameter.
-
-[source]
-----
-sjms2:queue:transacted.batch.consumer?transacted=true&transactionBatchCount=10&transactionBatchTimeout=2000
-----
+== Additional Notes
 
-The minimal value that will be accepted is 1000ms as the amount of
-context switching may cause unnecessary performance impacts without
-gaining benefit.
+=== Local transactions
 
-The producer endpoint is handled much differently though. With the
-producer after each message is delivered to its destination the Exchange
-is closed and there is no longer a reference to that message. To make a
-available all the messages available for redelivery you simply enable
-transactions on a Producer Endpoint that is publishing BatchMessages.
-The transaction will commit at the conclusion of the exchange which
-includes all messages in the batch list. Nothing additional need be
-configured. For example:
+When using `transacted=true` then JMS Transacted Acknowledge Mode are in use.
+The SJMS2 component supports this from both the consumer and producers. If a consumer
+is transacted, then the active JMS Session will commit or rollback at the end of processing the message.
 
-[source,java]
-----
-List<BatchMessage<String>> messages = new ArrayList<BatchMessage<String>>();
-for (int i = 1; i <= messageCount; i++) {
-    String body = "Hello World " + i;
-    BatchMessage<String> message = new BatchMessage<String>(body, null);
-    messages.add(message);
-}
-----
+SJMS2 producers that are `transacted=true` will also defer until the end of processing the message
+before the the active JMS Session will commit or rollback.
 
-Now publish the List with transactions enabled:
+You can combine consumer and producer, such as:
 
 [source,java]
 ----
-template.sendBody("sjms2:queue:batch.queue?transacted=true", messages);
+from("sjms2:cheese?transacted=true")
+  .to("bean:foo")
+  .to("sjms2:foo?transacted=true")
+  .to("bean:bar");
 ----
 
-== Additional Notes
+Here the consumer and producer are both transacted, which means that only at the end of processing the message,
+then both the consumer and the producer will commit (or rollback in case of an exception during routing).
 
 === Message Header Format
 
@@ -530,12 +299,8 @@ messages:
 ** is replaced by _DOT_ and the reverse replacement when Camel consumes
 the message.
 ** is replaced by _HYPHEN_ and the reverse replacement when Camel
-consumes the message. +
-See also the option `jmsKeyFormatStrategy`, which allows use of your own
-custom strategy for formatting keys.
-
-For the `exchange.in.header`, the following rules apply for the header
-values:
+consumes the message.See also the option `jmsKeyFormatStrategy`,
+which allows use of your own custom strategy for formatting keys.
 
 === Message Content
 
@@ -550,40 +315,19 @@ dropped.
 === Clustering
 
 When using _InOut_ with SJMS2 in a clustered environment you must either
-use TemporaryQueue destinations or use a unique named reply to
+use TemporaryQueue destinations or use a unique reply to
 destination per InOut producer endpoint. Message correlation is handled
-by the endpoint, not with message selectors at the broker. The InOut
-Producer Endpoint uses Java Concurrency Exchangers cached by the Message
-`JMSCorrelationID`. This provides a nice performance increase while
-reducing the overhead on the broker since all the messages are consumed
-from the destination in the order they are produced by the interested
-consumer.
+by the producer, not with message selectors at the broker.
+
+[NOTE]
+====
+You should only use queues as reply-to destination types, topics is not recommended or fully supported.
+====
 
 Currently the only correlation strategy is to use the `JMSCorrelationId`.
 The _InOut_ Consumer uses this strategy as well ensuring that all
 responses messages to the included `JMSReplyTo` destination also have the
 `JMSCorrelationId` copied from the request as well.
 
-== Transaction Support [[SJMS2-transactions]]
-
-SJMS2 currently only supports the use of internal JMS Transactions. There
-is no support for the Camel Transaction Processor or the Java
-Transaction API (JTA).
-
-=== Does Springless Mean I Can't Use Spring?
-
-Not at all. Below is an example of the SJMS2 component using the XML DSL:
-
-[source,xml]
-----
-<route>
-    <from uri="direct:invoke.named.reply.to.queue" />
-    <to uri="sjms2:queue:named.reply.to.queue?replyTo=my.response.queue" />
-</route>
-----
-
-Springless refers to moving away from the dependency on the Spring JMS
-API. A new JMS client API is being developed from the ground up to power
-SJMS2.
 
 include::camel-spring-boot::page$sjms2-starter.adoc[]
diff --git a/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/jms/Jms2ObjectFactory.java b/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/jms/Jms2ObjectFactory.java
index 1a11567..725dab0 100644
--- a/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/jms/Jms2ObjectFactory.java
+++ b/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/jms/Jms2ObjectFactory.java
@@ -25,6 +25,7 @@ import javax.jms.Session;
 import javax.jms.Topic;
 
 import org.apache.camel.Endpoint;
+import org.apache.camel.component.sjms.SjmsEndpoint;
 import org.apache.camel.component.sjms.jms.JmsObjectFactory;
 import org.apache.camel.component.sjms2.Sjms2Endpoint;
 import org.apache.camel.util.ObjectHelper;
@@ -50,6 +51,11 @@ public class Jms2ObjectFactory implements JmsObjectFactory {
     }
 
     @Override
+    public MessageConsumer createQueueMessageConsumer(Session session, Destination destination) throws Exception {
+        return createMessageConsumer(session, destination, null, false, null, false, false);
+    }
+
+    @Override
     public MessageConsumer createMessageConsumer(
             Session session, Destination destination,
             String messageSelector, boolean topic, String subscriptionId, boolean durable,
@@ -192,6 +198,18 @@ public class Jms2ObjectFactory implements JmsObjectFactory {
     }
 
     @Override
+    public MessageProducer createMessageProducer(Session session, Endpoint endpoint, Destination destination) throws Exception {
+        SjmsEndpoint sjmsEndpoint = (SjmsEndpoint) endpoint;
+
+        boolean persistent = sjmsEndpoint.isDeliveryPersistent();
+        if (sjmsEndpoint.getDeliveryMode() != null) {
+            persistent = DeliveryMode.PERSISTENT == sjmsEndpoint.getDeliveryMode();
+        }
+
+        return createMessageProducer(session, destination, persistent, sjmsEndpoint.getTimeToLive());
+    }
+
+    @Override
     public MessageProducer createMessageProducer(
             Session session, Destination destination,
             boolean persistent, long ttl)
diff --git a/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/Sjms2EndpointConnectionSettingsTest.java b/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/Sjms2EndpointConnectionSettingsTest.java
deleted file mode 100644
index c5cfa04..0000000
--- a/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/Sjms2EndpointConnectionSettingsTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.component.sjms2;
-
-import java.util.Random;
-
-import org.apache.activemq.ActiveMQConnectionFactory;
-import org.apache.camel.CamelContext;
-import org.apache.camel.Endpoint;
-import org.apache.camel.component.sjms.jms.ConnectionFactoryResource;
-import org.apache.camel.component.sjms.jms.ConnectionResource;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.apache.camel.support.SimpleRegistry;
-import org.apache.camel.test.junit5.CamelTestSupport;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class Sjms2EndpointConnectionSettingsTest extends CamelTestSupport {
-    private final ActiveMQConnectionFactory connectionFactory
-            = new ActiveMQConnectionFactory("vm://broker?broker.persistent=false&broker.useJmx=false");
-    private final ConnectionResource connectionResource = new ConnectionFactoryResource(2, connectionFactory);
-
-    @Test
-    public void testConnectionFactory() {
-        Endpoint endpoint = context.getEndpoint("sjms2:queue:test?connectionFactory=#activemq");
-        assertNotNull(endpoint);
-        assertTrue(endpoint instanceof Sjms2Endpoint);
-        Sjms2Endpoint qe = (Sjms2Endpoint) endpoint;
-        assertEquals(connectionFactory, qe.getConnectionFactory());
-    }
-
-    @Test
-    public void testConnectionResource() {
-        Endpoint endpoint = context.getEndpoint("sjms2:queue:test?connectionResource=#connresource");
-        assertNotNull(endpoint);
-        assertTrue(endpoint instanceof Sjms2Endpoint);
-        Sjms2Endpoint qe = (Sjms2Endpoint) endpoint;
-        assertEquals(connectionResource, qe.getConnectionResource());
-    }
-
-    @Test
-    public void testConnectionCount() {
-        Random random = new Random();
-        int poolSize = random.nextInt(100);
-        Endpoint endpoint = context.getEndpoint("sjms2:queue:test?connectionCount=" + poolSize);
-        assertNotNull(endpoint);
-        assertTrue(endpoint instanceof Sjms2Endpoint);
-        Sjms2Endpoint qe = (Sjms2Endpoint) endpoint;
-        assertEquals(poolSize, qe.getConnectionCount());
-    }
-
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        SimpleRegistry registry = new SimpleRegistry();
-        registry.bind("activemq", connectionFactory);
-        registry.bind("connresource", connectionResource);
-        return new DefaultCamelContext(registry);
-    }
-}
diff --git a/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicDurableConsumerTest.java b/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicDurableConsumerTest.java
index 86ef372..73a41cd 100644
--- a/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicDurableConsumerTest.java
+++ b/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicDurableConsumerTest.java
@@ -16,11 +16,9 @@
  */
 package org.apache.camel.component.sjms2.consumer;
 
-import org.apache.activemq.ActiveMQConnectionFactory;
 import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.sjms.jms.ConnectionFactoryResource;
 import org.apache.camel.component.sjms2.Sjms2Component;
 import org.apache.camel.test.junit5.CamelTestSupport;
 import org.junit.jupiter.api.Test;
@@ -28,7 +26,6 @@ import org.junit.jupiter.api.Test;
 public class InOnlyTopicDurableConsumerTest extends CamelTestSupport {
 
     private static final String CONNECTION_ID = "test-connection-1";
-    private static final String BROKER_URI = "vm://durable.broker?broker.persistent=false&broker.useJmx=false";
 
     @Override
     protected boolean useJmx() {
@@ -51,24 +48,12 @@ public class InOnlyTopicDurableConsumerTest extends CamelTestSupport {
         assertMockEndpointsSatisfied();
     }
 
-    /*
-     * @see org.apache.camel.test.junit5.CamelTestSupport#createCamelContext()
-     *
-     * @return
-     * @throws Exception
-     */
     @Override
     protected CamelContext createCamelContext() throws Exception {
-        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URI);
-        ConnectionFactoryResource connectionResource = new ConnectionFactoryResource();
-        connectionResource.setConnectionFactory(connectionFactory);
-        connectionResource.setClientId(CONNECTION_ID);
-        CamelContext camelContext = super.createCamelContext();
-        Sjms2Component component = new Sjms2Component();
-        component.setConnectionResource(connectionResource);
-        component.setConnectionCount(1);
-        camelContext.addComponent("sjms2", component);
-        return camelContext;
+        CamelContext context = super.createCamelContext();
+        Sjms2Component sjms = context.getComponent("sjms2", Sjms2Component.class);
+        sjms.setClientId(CONNECTION_ID);
+        return context;
     }
 
     @Override
diff --git a/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicSharedConsumerTest.java b/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicSharedConsumerTest.java
index df4aaac..ba2d897 100644
--- a/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicSharedConsumerTest.java
+++ b/components/camel-sjms2/src/test/java/org/apache/camel/component/sjms2/consumer/InOnlyTopicSharedConsumerTest.java
@@ -47,12 +47,6 @@ public class InOnlyTopicSharedConsumerTest extends Jms2TestSupport {
         mock2.assertIsSatisfied();
     }
 
-    /**
-     * @see              org.apache.camel.test.junit5.CamelTestSupport#createRouteBuilder()
-     *
-     * @return
-     * @throws Exception
-     */
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
diff --git a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Sjms2ComponentBuilderFactory.java b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Sjms2ComponentBuilderFactory.java
index f3ee320..6e01843 100644
--- a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Sjms2ComponentBuilderFactory.java
+++ b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Sjms2ComponentBuilderFactory.java
@@ -107,36 +107,6 @@ public interface Sjms2ComponentBuilderFactory {
             return this;
         }
         /**
-         * Backoff in millis on consumer pool reconnection attempts.
-         * 
-         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
-         * 
-         * Default: 5000
-         * Group: consumer
-         * 
-         * @param reconnectBackOff the value to set
-         * @return the dsl builder
-         */
-        default Sjms2ComponentBuilder reconnectBackOff(long reconnectBackOff) {
-            doSetProperty("reconnectBackOff", reconnectBackOff);
-            return this;
-        }
-        /**
-         * Try to apply reconnection logic on consumer pool.
-         * 
-         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
-         * 
-         * Default: true
-         * Group: consumer
-         * 
-         * @param reconnectOnError the value to set
-         * @return the dsl builder
-         */
-        default Sjms2ComponentBuilder reconnectOnError(boolean reconnectOnError) {
-            doSetProperty("reconnectOnError", reconnectOnError);
-            return this;
-        }
-        /**
          * Whether the producer should be started lazy (on the first message).
          * By starting lazy you can use this to allow CamelContext and routes to
          * startup in situations where a producer may otherwise fail during
@@ -181,76 +151,6 @@ public interface Sjms2ComponentBuilderFactory {
             return this;
         }
         /**
-         * The client ID to use when creating javax.jms.Connection when using
-         * the default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
-         * 
-         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
-         * 
-         * Group: advanced
-         * 
-         * @param connectionClientId the value to set
-         * @return the dsl builder
-         */
-        default Sjms2ComponentBuilder connectionClientId(
-                java.lang.String connectionClientId) {
-            doSetProperty("connectionClientId", connectionClientId);
-            return this;
-        }
-        /**
-         * The max wait time in millis to block and wait on free connection when
-         * the pool is exhausted when using the default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
-         * 
-         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
-         * 
-         * Default: 5000
-         * Group: advanced
-         * 
-         * @param connectionMaxWait the value to set
-         * @return the dsl builder
-         */
-        default Sjms2ComponentBuilder connectionMaxWait(long connectionMaxWait) {
-            doSetProperty("connectionMaxWait", connectionMaxWait);
-            return this;
-        }
-        /**
-         * A ConnectionResource is an interface that allows for customization
-         * and container control of the ConnectionFactory. See Plugable
-         * Connection Resource Management for further details.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.sjms.jms.ConnectionResource&lt;/code&gt; type.
-         * 
-         * Group: advanced
-         * 
-         * @param connectionResource the value to set
-         * @return the dsl builder
-         */
-        default Sjms2ComponentBuilder connectionResource(
-                org.apache.camel.component.sjms.jms.ConnectionResource connectionResource) {
-            doSetProperty("connectionResource", connectionResource);
-            return this;
-        }
-        /**
-         * When using the default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource then
-         * should each javax.jms.Connection be tested before being used.
-         * 
-         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
-         * 
-         * Default: true
-         * Group: advanced
-         * 
-         * @param connectionTestOnBorrow the value to set
-         * @return the dsl builder
-         */
-        default Sjms2ComponentBuilder connectionTestOnBorrow(
-                boolean connectionTestOnBorrow) {
-            doSetProperty("connectionTestOnBorrow", connectionTestOnBorrow);
-            return this;
-        }
-        /**
          * To use a custom DestinationCreationStrategy.
          * 
          * The option is a:
@@ -308,6 +208,60 @@ public interface Sjms2ComponentBuilderFactory {
             return this;
         }
         /**
+         * Specifies the interval between recovery attempts, i.e. when a
+         * connection is being refreshed, in milliseconds. The default is 5000
+         * ms, that is, 5 seconds.
+         * 
+         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Default: 5000
+         * Group: advanced
+         * 
+         * @param recoveryInterval the value to set
+         * @return the dsl builder
+         */
+        default Sjms2ComponentBuilder recoveryInterval(long recoveryInterval) {
+            doSetProperty("recoveryInterval", recoveryInterval);
+            return this;
+        }
+        /**
+         * Specifies the maximum number of concurrent consumers for continue
+         * routing when timeout occurred when using request/reply over JMS.
+         * 
+         * The option is a: &lt;code&gt;int&lt;/code&gt; type.
+         * 
+         * Default: 1
+         * Group: advanced
+         * 
+         * @param replyToOnTimeoutMaxConcurrentConsumers the value to set
+         * @return the dsl builder
+         */
+        default Sjms2ComponentBuilder replyToOnTimeoutMaxConcurrentConsumers(
+                int replyToOnTimeoutMaxConcurrentConsumers) {
+            doSetProperty("replyToOnTimeoutMaxConcurrentConsumers", replyToOnTimeoutMaxConcurrentConsumers);
+            return this;
+        }
+        /**
+         * Configures how often Camel should check for timed out Exchanges when
+         * doing request/reply over JMS. By default Camel checks once per
+         * second. But if you must react faster when a timeout occurs, then you
+         * can lower this interval, to check more frequently. The timeout is
+         * determined by the option requestTimeout.
+         * 
+         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Default: 1000
+         * Group: advanced
+         * 
+         * @param requestTimeoutCheckerInterval the value to set
+         * @return the dsl builder
+         */
+        default Sjms2ComponentBuilder requestTimeoutCheckerInterval(
+                long requestTimeoutCheckerInterval) {
+            doSetProperty("requestTimeoutCheckerInterval", requestTimeoutCheckerInterval);
+            return this;
+        }
+        /**
          * To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter
          * header to and from Camel message.
          * 
@@ -326,54 +280,33 @@ public interface Sjms2ComponentBuilderFactory {
             return this;
         }
         /**
-         * The password to use when creating javax.jms.Connection when using the
-         * default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
+         * Password to use with the ConnectionFactory. You can also configure
+         * username/password directly on the ConnectionFactory.
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
          * 
          * Group: security
          * 
-         * @param connectionPassword the value to set
+         * @param password the value to set
          * @return the dsl builder
          */
-        default Sjms2ComponentBuilder connectionPassword(
-                java.lang.String connectionPassword) {
-            doSetProperty("connectionPassword", connectionPassword);
+        default Sjms2ComponentBuilder password(java.lang.String password) {
+            doSetProperty("password", password);
             return this;
         }
         /**
-         * The username to use when creating javax.jms.Connection when using the
-         * default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
+         * Username to use with the ConnectionFactory. You can also configure
+         * username/password directly on the ConnectionFactory.
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
          * 
          * Group: security
          * 
-         * @param connectionUsername the value to set
-         * @return the dsl builder
-         */
-        default Sjms2ComponentBuilder connectionUsername(
-                java.lang.String connectionUsername) {
-            doSetProperty("connectionUsername", connectionUsername);
-            return this;
-        }
-        /**
-         * To configure which kind of commit strategy to use. Camel provides two
-         * implementations out of the box, default and batch.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.sjms.TransactionCommitStrategy&lt;/code&gt; type.
-         * 
-         * Group: transaction
-         * 
-         * @param transactionCommitStrategy the value to set
+         * @param username the value to set
          * @return the dsl builder
          */
-        default Sjms2ComponentBuilder transactionCommitStrategy(
-                org.apache.camel.component.sjms.TransactionCommitStrategy transactionCommitStrategy) {
-            doSetProperty("transactionCommitStrategy", transactionCommitStrategy);
+        default Sjms2ComponentBuilder username(java.lang.String username) {
+            doSetProperty("username", username);
             return this;
         }
     }
@@ -396,21 +329,17 @@ public interface Sjms2ComponentBuilderFactory {
             case "connectionCount": ((Sjms2Component) component).setConnectionCount((java.lang.Integer) value); return true;
             case "connectionFactory": ((Sjms2Component) component).setConnectionFactory((javax.jms.ConnectionFactory) value); return true;
             case "bridgeErrorHandler": ((Sjms2Component) component).setBridgeErrorHandler((boolean) value); return true;
-            case "reconnectBackOff": ((Sjms2Component) component).setReconnectBackOff((long) value); return true;
-            case "reconnectOnError": ((Sjms2Component) component).setReconnectOnError((boolean) value); return true;
             case "lazyStartProducer": ((Sjms2Component) component).setLazyStartProducer((boolean) value); return true;
             case "autowiredEnabled": ((Sjms2Component) component).setAutowiredEnabled((boolean) value); return true;
-            case "connectionClientId": ((Sjms2Component) component).setConnectionClientId((java.lang.String) value); return true;
-            case "connectionMaxWait": ((Sjms2Component) component).setConnectionMaxWait((long) value); return true;
-            case "connectionResource": ((Sjms2Component) component).setConnectionResource((org.apache.camel.component.sjms.jms.ConnectionResource) value); return true;
-            case "connectionTestOnBorrow": ((Sjms2Component) component).setConnectionTestOnBorrow((boolean) value); return true;
             case "destinationCreationStrategy": ((Sjms2Component) component).setDestinationCreationStrategy((org.apache.camel.component.sjms.jms.DestinationCreationStrategy) value); return true;
             case "jmsKeyFormatStrategy": ((Sjms2Component) component).setJmsKeyFormatStrategy((org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy) value); return true;
             case "messageCreatedStrategy": ((Sjms2Component) component).setMessageCreatedStrategy((org.apache.camel.component.sjms.jms.MessageCreatedStrategy) value); return true;
+            case "recoveryInterval": ((Sjms2Component) component).setRecoveryInterval((long) value); return true;
+            case "replyToOnTimeoutMaxConcurrentConsumers": ((Sjms2Component) component).setReplyToOnTimeoutMaxConcurrentConsumers((int) value); return true;
+            case "requestTimeoutCheckerInterval": ((Sjms2Component) component).setRequestTimeoutCheckerInterval((long) value); return true;
             case "headerFilterStrategy": ((Sjms2Component) component).setHeaderFilterStrategy((org.apache.camel.spi.HeaderFilterStrategy) value); return true;
-            case "connectionPassword": ((Sjms2Component) component).setConnectionPassword((java.lang.String) value); return true;
-            case "connectionUsername": ((Sjms2Component) component).setConnectionUsername((java.lang.String) value); return true;
-            case "transactionCommitStrategy": ((Sjms2Component) component).setTransactionCommitStrategy((org.apache.camel.component.sjms.TransactionCommitStrategy) value); return true;
+            case "password": ((Sjms2Component) component).setPassword((java.lang.String) value); return true;
+            case "username": ((Sjms2Component) component).setUsername((java.lang.String) value); return true;
             default: return false;
             }
         }
diff --git a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SjmsComponentBuilderFactory.java b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SjmsComponentBuilderFactory.java
index 730c6ba..7d64cd5 100644
--- a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SjmsComponentBuilderFactory.java
+++ b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SjmsComponentBuilderFactory.java
@@ -150,76 +150,6 @@ public interface SjmsComponentBuilderFactory {
             return this;
         }
         /**
-         * The client ID to use when creating javax.jms.Connection when using
-         * the default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
-         * 
-         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
-         * 
-         * Group: advanced
-         * 
-         * @param connectionClientId the value to set
-         * @return the dsl builder
-         */
-        default SjmsComponentBuilder connectionClientId(
-                java.lang.String connectionClientId) {
-            doSetProperty("connectionClientId", connectionClientId);
-            return this;
-        }
-        /**
-         * The max wait time in millis to block and wait on free connection when
-         * the pool is exhausted when using the default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
-         * 
-         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
-         * 
-         * Default: 5000
-         * Group: advanced
-         * 
-         * @param connectionMaxWait the value to set
-         * @return the dsl builder
-         */
-        default SjmsComponentBuilder connectionMaxWait(long connectionMaxWait) {
-            doSetProperty("connectionMaxWait", connectionMaxWait);
-            return this;
-        }
-        /**
-         * A ConnectionResource is an interface that allows for customization
-         * and container control of the ConnectionFactory. See Plugable
-         * Connection Resource Management for further details.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.sjms.jms.ConnectionResource&lt;/code&gt; type.
-         * 
-         * Group: advanced
-         * 
-         * @param connectionResource the value to set
-         * @return the dsl builder
-         */
-        default SjmsComponentBuilder connectionResource(
-                org.apache.camel.component.sjms.jms.ConnectionResource connectionResource) {
-            doSetProperty("connectionResource", connectionResource);
-            return this;
-        }
-        /**
-         * When using the default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource then
-         * should each javax.jms.Connection be tested before being used.
-         * 
-         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
-         * 
-         * Default: true
-         * Group: advanced
-         * 
-         * @param connectionTestOnBorrow the value to set
-         * @return the dsl builder
-         */
-        default SjmsComponentBuilder connectionTestOnBorrow(
-                boolean connectionTestOnBorrow) {
-            doSetProperty("connectionTestOnBorrow", connectionTestOnBorrow);
-            return this;
-        }
-        /**
          * To use a custom DestinationCreationStrategy.
          * 
          * The option is a:
@@ -294,6 +224,43 @@ public interface SjmsComponentBuilderFactory {
             return this;
         }
         /**
+         * Specifies the maximum number of concurrent consumers for continue
+         * routing when timeout occurred when using request/reply over JMS.
+         * 
+         * The option is a: &lt;code&gt;int&lt;/code&gt; type.
+         * 
+         * Default: 1
+         * Group: advanced
+         * 
+         * @param replyToOnTimeoutMaxConcurrentConsumers the value to set
+         * @return the dsl builder
+         */
+        default SjmsComponentBuilder replyToOnTimeoutMaxConcurrentConsumers(
+                int replyToOnTimeoutMaxConcurrentConsumers) {
+            doSetProperty("replyToOnTimeoutMaxConcurrentConsumers", replyToOnTimeoutMaxConcurrentConsumers);
+            return this;
+        }
+        /**
+         * Configures how often Camel should check for timed out Exchanges when
+         * doing request/reply over JMS. By default Camel checks once per
+         * second. But if you must react faster when a timeout occurs, then you
+         * can lower this interval, to check more frequently. The timeout is
+         * determined by the option requestTimeout.
+         * 
+         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Default: 1000
+         * Group: advanced
+         * 
+         * @param requestTimeoutCheckerInterval the value to set
+         * @return the dsl builder
+         */
+        default SjmsComponentBuilder requestTimeoutCheckerInterval(
+                long requestTimeoutCheckerInterval) {
+            doSetProperty("requestTimeoutCheckerInterval", requestTimeoutCheckerInterval);
+            return this;
+        }
+        /**
          * To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter
          * header to and from Camel message.
          * 
@@ -312,54 +279,33 @@ public interface SjmsComponentBuilderFactory {
             return this;
         }
         /**
-         * The password to use when creating javax.jms.Connection when using the
-         * default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
+         * Password to use with the ConnectionFactory. You can also configure
+         * username/password directly on the ConnectionFactory.
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
          * 
          * Group: security
          * 
-         * @param connectionPassword the value to set
+         * @param password the value to set
          * @return the dsl builder
          */
-        default SjmsComponentBuilder connectionPassword(
-                java.lang.String connectionPassword) {
-            doSetProperty("connectionPassword", connectionPassword);
+        default SjmsComponentBuilder password(java.lang.String password) {
+            doSetProperty("password", password);
             return this;
         }
         /**
-         * The username to use when creating javax.jms.Connection when using the
-         * default
-         * org.apache.camel.component.sjms.jms.ConnectionFactoryResource.
+         * Username to use with the ConnectionFactory. You can also configure
+         * username/password directly on the ConnectionFactory.
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
          * 
          * Group: security
          * 
-         * @param connectionUsername the value to set
-         * @return the dsl builder
-         */
-        default SjmsComponentBuilder connectionUsername(
-                java.lang.String connectionUsername) {
-            doSetProperty("connectionUsername", connectionUsername);
-            return this;
-        }
-        /**
-         * To configure which kind of commit strategy to use. Camel provides two
-         * implementations out of the box, default and batch.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.sjms.TransactionCommitStrategy&lt;/code&gt; type.
-         * 
-         * Group: transaction
-         * 
-         * @param transactionCommitStrategy the value to set
+         * @param username the value to set
          * @return the dsl builder
          */
-        default SjmsComponentBuilder transactionCommitStrategy(
-                org.apache.camel.component.sjms.TransactionCommitStrategy transactionCommitStrategy) {
-            doSetProperty("transactionCommitStrategy", transactionCommitStrategy);
+        default SjmsComponentBuilder username(java.lang.String username) {
+            doSetProperty("username", username);
             return this;
         }
     }
@@ -384,18 +330,15 @@ public interface SjmsComponentBuilderFactory {
             case "bridgeErrorHandler": ((SjmsComponent) component).setBridgeErrorHandler((boolean) value); return true;
             case "lazyStartProducer": ((SjmsComponent) component).setLazyStartProducer((boolean) value); return true;
             case "autowiredEnabled": ((SjmsComponent) component).setAutowiredEnabled((boolean) value); return true;
-            case "connectionClientId": ((SjmsComponent) component).setConnectionClientId((java.lang.String) value); return true;
-            case "connectionMaxWait": ((SjmsComponent) component).setConnectionMaxWait((long) value); return true;
-            case "connectionResource": ((SjmsComponent) component).setConnectionResource((org.apache.camel.component.sjms.jms.ConnectionResource) value); return true;
-            case "connectionTestOnBorrow": ((SjmsComponent) component).setConnectionTestOnBorrow((boolean) value); return true;
             case "destinationCreationStrategy": ((SjmsComponent) component).setDestinationCreationStrategy((org.apache.camel.component.sjms.jms.DestinationCreationStrategy) value); return true;
             case "jmsKeyFormatStrategy": ((SjmsComponent) component).setJmsKeyFormatStrategy((org.apache.camel.component.sjms.jms.JmsKeyFormatStrategy) value); return true;
             case "messageCreatedStrategy": ((SjmsComponent) component).setMessageCreatedStrategy((org.apache.camel.component.sjms.jms.MessageCreatedStrategy) value); return true;
             case "recoveryInterval": ((SjmsComponent) component).setRecoveryInterval((long) value); return true;
+            case "replyToOnTimeoutMaxConcurrentConsumers": ((SjmsComponent) component).setReplyToOnTimeoutMaxConcurrentConsumers((int) value); return true;
+            case "requestTimeoutCheckerInterval": ((SjmsComponent) component).setRequestTimeoutCheckerInterval((long) value); return true;
             case "headerFilterStrategy": ((SjmsComponent) component).setHeaderFilterStrategy((org.apache.camel.spi.HeaderFilterStrategy) value); return true;
-            case "connectionPassword": ((SjmsComponent) component).setConnectionPassword((java.lang.String) value); return true;
-            case "connectionUsername": ((SjmsComponent) component).setConnectionUsername((java.lang.String) value); return true;
-            case "transactionCommitStrategy": ((SjmsComponent) component).setTransactionCommitStrategy((org.apache.camel.component.sjms.TransactionCommitStrategy) value); return true;
+            case "password": ((SjmsComponent) component).setPassword((java.lang.String) value); return true;
+            case "username": ((SjmsComponent) component).setUsername((java.lang.String) value); return true;
             default: return false;
             }
         }
diff --git a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Sjms2EndpointBuilderFactory.java b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Sjms2EndpointBuilderFactory.java
index 3d72324..1ea44be 100644
--- a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Sjms2EndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Sjms2EndpointBuilderFactory.java
@@ -143,6 +143,127 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
+         * Specifies whether to test the connection on startup. This ensures
+         * that when Camel starts that all the JMS consumers have a valid
+         * connection to the JMS broker. If a connection cannot be granted then
+         * Camel throws an exception on startup. This ensures that Camel is not
+         * started with failed connections. The JMS producers is tested as well.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param testConnectionOnStartup the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointConsumerBuilder testConnectionOnStartup(
+                boolean testConnectionOnStartup) {
+            doSetProperty("testConnectionOnStartup", testConnectionOnStartup);
+            return this;
+        }
+        /**
+         * Specifies whether to test the connection on startup. This ensures
+         * that when Camel starts that all the JMS consumers have a valid
+         * connection to the JMS broker. If a connection cannot be granted then
+         * Camel throws an exception on startup. This ensures that Camel is not
+         * started with failed connections. The JMS producers is tested as well.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param testConnectionOnStartup the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointConsumerBuilder testConnectionOnStartup(
+                String testConnectionOnStartup) {
+            doSetProperty("testConnectionOnStartup", testConnectionOnStartup);
+            return this;
+        }
+        /**
+         * Whether the JmsConsumer processes the Exchange asynchronously. If
+         * enabled then the JmsConsumer may pickup the next message from the JMS
+         * queue, while the previous message is being processed asynchronously
+         * (by the Asynchronous Routing Engine). This means that messages may be
+         * processed not 100% strictly in order. If disabled (as default) then
+         * the Exchange is fully processed before the JmsConsumer will pickup
+         * the next message from the JMS queue. Note if transacted has been
+         * enabled, then asyncConsumer=true does not run asynchronously, as
+         * transaction must be executed synchronously (Camel 3.0 may support
+         * async transactions).
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param asyncConsumer the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointConsumerBuilder asyncConsumer(boolean asyncConsumer) {
+            doSetProperty("asyncConsumer", asyncConsumer);
+            return this;
+        }
+        /**
+         * Whether the JmsConsumer processes the Exchange asynchronously. If
+         * enabled then the JmsConsumer may pickup the next message from the JMS
+         * queue, while the previous message is being processed asynchronously
+         * (by the Asynchronous Routing Engine). This means that messages may be
+         * processed not 100% strictly in order. If disabled (as default) then
+         * the Exchange is fully processed before the JmsConsumer will pickup
+         * the next message from the JMS queue. Note if transacted has been
+         * enabled, then asyncConsumer=true does not run asynchronously, as
+         * transaction must be executed synchronously (Camel 3.0 may support
+         * async transactions).
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param asyncConsumer the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointConsumerBuilder asyncConsumer(String asyncConsumer) {
+            doSetProperty("asyncConsumer", asyncConsumer);
+            return this;
+        }
+        /**
+         * Specifies whether the consumer container should auto-startup.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: true
+         * Group: consumer
+         * 
+         * @param autoStartup the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointConsumerBuilder autoStartup(boolean autoStartup) {
+            doSetProperty("autoStartup", autoStartup);
+            return this;
+        }
+        /**
+         * Specifies whether the consumer container should auto-startup.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: true
+         * Group: consumer
+         * 
+         * @param autoStartup the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointConsumerBuilder autoStartup(String autoStartup) {
+            doSetProperty("autoStartup", autoStartup);
+            return this;
+        }
+        /**
          * Allows for bridging the consumer to the Camel routing Error Handler,
          * which mean any exceptions occurred while the consumer is trying to
          * pickup incoming messages, or the likes, will now be processed as a
@@ -188,33 +309,45 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
-         * Sets the number of consumer listeners used for this endpoint.
+         * Specifies the default number of concurrent consumers when consuming
+         * from JMS (not for request/reply over JMS). See also the
+         * maxMessagesPerTask option to control dynamic scaling up/down of
+         * threads. When doing request/reply over JMS then the option
+         * replyToConcurrentConsumers is used to control number of concurrent
+         * consumers on the reply message listener.
          * 
          * The option is a: &lt;code&gt;int&lt;/code&gt; type.
          * 
          * Default: 1
          * Group: consumer
          * 
-         * @param consumerCount the value to set
+         * @param concurrentConsumers the value to set
          * @return the dsl builder
          */
-        default Sjms2EndpointConsumerBuilder consumerCount(int consumerCount) {
-            doSetProperty("consumerCount", consumerCount);
+        default Sjms2EndpointConsumerBuilder concurrentConsumers(
+                int concurrentConsumers) {
+            doSetProperty("concurrentConsumers", concurrentConsumers);
             return this;
         }
         /**
-         * Sets the number of consumer listeners used for this endpoint.
+         * Specifies the default number of concurrent consumers when consuming
+         * from JMS (not for request/reply over JMS). See also the
+         * maxMessagesPerTask option to control dynamic scaling up/down of
+         * threads. When doing request/reply over JMS then the option
+         * replyToConcurrentConsumers is used to control number of concurrent
+         * consumers on the reply message listener.
          * 
          * The option will be converted to a &lt;code&gt;int&lt;/code&gt; type.
          * 
          * Default: 1
          * Group: consumer
          * 
-         * @param consumerCount the value to set
+         * @param concurrentConsumers the value to set
          * @return the dsl builder
          */
-        default Sjms2EndpointConsumerBuilder consumerCount(String consumerCount) {
-            doSetProperty("consumerCount", consumerCount);
+        default Sjms2EndpointConsumerBuilder concurrentConsumers(
+                String concurrentConsumers) {
+            doSetProperty("concurrentConsumers", concurrentConsumers);
             return this;
         }
         /**
@@ -264,71 +397,6 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
-         * Backoff in millis on consumer pool reconnection attempts.
-         * 
-         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
-         * 
-         * Default: 5000
-         * Group: consumer
-         * 
-         * @param reconnectBackOff the value to set
-         * @return the dsl builder
-         */
-        default Sjms2EndpointConsumerBuilder reconnectBackOff(
-                long reconnectBackOff) {
-            doSetProperty("reconnectBackOff", reconnectBackOff);
-            return this;
-        }
-        /**
-         * Backoff in millis on consumer pool reconnection attempts.
-         * 
-         * The option will be converted to a &lt;code&gt;long&lt;/code&gt; type.
-         * 
-         * Default: 5000
-         * Group: consumer
-         * 
-         * @param reconnectBackOff the value to set
-         * @return the dsl builder
-         */
-        default Sjms2EndpointConsumerBuilder reconnectBackOff(
-                String reconnectBackOff) {
-            doSetProperty("reconnectBackOff", reconnectBackOff);
-            return this;
-        }
-        /**
-         * Try to apply reconnection logic on consumer pool.
-         * 
-         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
-         * 
-         * Default: true
-         * Group: consumer
-         * 
-         * @param reconnectOnError the value to set
-         * @return the dsl builder
-         */
-        default Sjms2EndpointConsumerBuilder reconnectOnError(
-                boolean reconnectOnError) {
-            doSetProperty("reconnectOnError", reconnectOnError);
-            return this;
-        }
-        /**
-         * Try to apply reconnection logic on consumer pool.
-         * 
-         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
-         * type.
-         * 
-         * Default: true
-         * Group: consumer
-         * 
-         * @param reconnectOnError the value to set
-         * @return the dsl builder
-         */
-        default Sjms2EndpointConsumerBuilder reconnectOnError(
-                String reconnectOnError) {
-            doSetProperty("reconnectOnError", reconnectOnError);
-            return this;
-        }
-        /**
          * Specifies whether to use persistent delivery by default for replies.
          * 
          * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
@@ -408,39 +476,6 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
-         * Sets whether synchronous processing should be strictly used or Camel
-         * is allowed to use asynchronous processing (if supported).
-         * 
-         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
-         * 
-         * Default: true
-         * Group: consumer
-         * 
-         * @param synchronous the value to set
-         * @return the dsl builder
-         */
-        default Sjms2EndpointConsumerBuilder synchronous(boolean synchronous) {
-            doSetProperty("synchronous", synchronous);
-            return this;
-        }
-        /**
-         * Sets whether synchronous processing should be strictly used or Camel
-         * is allowed to use asynchronous processing (if supported).
-         * 
-         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
-         * type.
-         * 
-         * Default: true
-         * Group: consumer
-         * 
-         * @param synchronous the value to set
-         * @return the dsl builder
-         */
-        default Sjms2EndpointConsumerBuilder synchronous(String synchronous) {
-            doSetProperty("synchronous", synchronous);
-            return this;
-        }
-        /**
          * Allows to configure the default errorHandler logging level for
          * logging uncaught exceptions.
          * 
@@ -542,48 +577,78 @@ public interface Sjms2EndpointBuilderFactory {
             doSetProperty("transacted", transacted);
             return this;
         }
+    }
+
+    /**
+     * Advanced builder for endpoint consumers for the Simple JMS2 component.
+     */
+    public interface AdvancedSjms2EndpointConsumerBuilder
+            extends
+                EndpointConsumerBuilder {
+        default Sjms2EndpointConsumerBuilder basic() {
+            return (Sjms2EndpointConsumerBuilder) this;
+        }
         /**
-         * Sets the commit strategy.
+         * Enables eager loading of JMS properties and payload as soon as a
+         * message is loaded which generally is inefficient as the JMS
+         * properties may not be required but sometimes can catch early any
+         * issues with the underlying JMS provider and the use of JMS
+         * properties. See also the option eagerPoisonBody.
          * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.sjms.TransactionCommitStrategy&lt;/code&gt; type.
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
          * 
-         * Group: transaction
+         * Default: false
+         * Group: consumer (advanced)
          * 
-         * @param transactionCommitStrategy the value to set
+         * @param eagerLoadingOfProperties the value to set
          * @return the dsl builder
          */
-        default Sjms2EndpointConsumerBuilder transactionCommitStrategy(
-                Object transactionCommitStrategy) {
-            doSetProperty("transactionCommitStrategy", transactionCommitStrategy);
+        default AdvancedSjms2EndpointConsumerBuilder eagerLoadingOfProperties(
+                boolean eagerLoadingOfProperties) {
+            doSetProperty("eagerLoadingOfProperties", eagerLoadingOfProperties);
             return this;
         }
         /**
-         * Sets the commit strategy.
+         * Enables eager loading of JMS properties and payload as soon as a
+         * message is loaded which generally is inefficient as the JMS
+         * properties may not be required but sometimes can catch early any
+         * issues with the underlying JMS provider and the use of JMS
+         * properties. See also the option eagerPoisonBody.
          * 
-         * The option will be converted to a
-         * &lt;code&gt;org.apache.camel.component.sjms.TransactionCommitStrategy&lt;/code&gt; type.
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
          * 
-         * Group: transaction
+         * Default: false
+         * Group: consumer (advanced)
          * 
-         * @param transactionCommitStrategy the value to set
+         * @param eagerLoadingOfProperties the value to set
          * @return the dsl builder
          */
-        default Sjms2EndpointConsumerBuilder transactionCommitStrategy(
-                String transactionCommitStrategy) {
-            doSetProperty("transactionCommitStrategy", transactionCommitStrategy);
+        default AdvancedSjms2EndpointConsumerBuilder eagerLoadingOfProperties(
+                String eagerLoadingOfProperties) {
+            doSetProperty("eagerLoadingOfProperties", eagerLoadingOfProperties);
             return this;
         }
-    }
-
-    /**
-     * Advanced builder for endpoint consumers for the Simple JMS2 component.
-     */
-    public interface AdvancedSjms2EndpointConsumerBuilder
-            extends
-                EndpointConsumerBuilder {
-        default Sjms2EndpointConsumerBuilder basic() {
-            return (Sjms2EndpointConsumerBuilder) this;
+        /**
+         * If eagerLoadingOfProperties is enabled and the JMS message payload
+         * (JMS body or JMS properties) is poison (cannot be read/mapped), then
+         * set this text as the message body instead so the message can be
+         * processed (the cause of the poison are already stored as exception on
+         * the Exchange). This can be turned off by setting
+         * eagerPoisonBody=false. See also the option eagerLoadingOfProperties.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Default: Poison JMS message due to ${exception.message}
+         * Group: consumer (advanced)
+         * 
+         * @param eagerPoisonBody the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder eagerPoisonBody(
+                String eagerPoisonBody) {
+            doSetProperty("eagerPoisonBody", eagerPoisonBody);
+            return this;
         }
         /**
          * To let the consumer use a custom ExceptionHandler. Notice if the
@@ -671,6 +736,45 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
+         * Whether a JMS consumer is allowed to send a reply message to the same
+         * destination that the consumer is using to consume from. This prevents
+         * an endless loop by consuming and sending back the same message to
+         * itself.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer (advanced)
+         * 
+         * @param replyToSameDestinationAllowed the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder replyToSameDestinationAllowed(
+                boolean replyToSameDestinationAllowed) {
+            doSetProperty("replyToSameDestinationAllowed", replyToSameDestinationAllowed);
+            return this;
+        }
+        /**
+         * Whether a JMS consumer is allowed to send a reply message to the same
+         * destination that the consumer is using to consume from. This prevents
+         * an endless loop by consuming and sending back the same message to
+         * itself.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: consumer (advanced)
+         * 
+         * @param replyToSameDestinationAllowed the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder replyToSameDestinationAllowed(
+                String replyToSameDestinationAllowed) {
+            doSetProperty("replyToSameDestinationAllowed", replyToSameDestinationAllowed);
+            return this;
+        }
+        /**
          * Whether to startup the consumer message listener asynchronously, when
          * starting a route. For example if a JmsConsumer cannot get a
          * connection to a remote JMS broker, then it may block while retrying
@@ -824,40 +928,6 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
-         * Initializes the connectionResource for the endpoint, which takes
-         * precedence over the component's connectionResource, if any.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.sjms.jms.ConnectionResource&lt;/code&gt; type.
-         * 
-         * Group: advanced
-         * 
-         * @param connectionResource the value to set
-         * @return the dsl builder
-         */
-        default AdvancedSjms2EndpointConsumerBuilder connectionResource(
-                Object connectionResource) {
-            doSetProperty("connectionResource", connectionResource);
-            return this;
-        }
-        /**
-         * Initializes the connectionResource for the endpoint, which takes
-         * precedence over the component's connectionResource, if any.
-         * 
-         * The option will be converted to a
-         * &lt;code&gt;org.apache.camel.component.sjms.jms.ConnectionResource&lt;/code&gt; type.
-         * 
-         * Group: advanced
-         * 
-         * @param connectionResource the value to set
-         * @return the dsl builder
-         */
-        default AdvancedSjms2EndpointConsumerBuilder connectionResource(
-                String connectionResource) {
-            doSetProperty("connectionResource", connectionResource);
-            return this;
-        }
-        /**
          * To use a custom DestinationCreationStrategy.
          * 
          * The option is a:
@@ -1120,6 +1190,136 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
+         * Specifies the interval between recovery attempts, i.e. when a
+         * connection is being refreshed, in milliseconds. The default is 5000
+         * ms, that is, 5 seconds.
+         * 
+         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Default: 5000
+         * Group: advanced
+         * 
+         * @param recoveryInterval the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder recoveryInterval(
+                long recoveryInterval) {
+            doSetProperty("recoveryInterval", recoveryInterval);
+            return this;
+        }
+        /**
+         * Specifies the interval between recovery attempts, i.e. when a
+         * connection is being refreshed, in milliseconds. The default is 5000
+         * ms, that is, 5 seconds.
+         * 
+         * The option will be converted to a &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Default: 5000
+         * Group: advanced
+         * 
+         * @param recoveryInterval the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder recoveryInterval(
+                String recoveryInterval) {
+            doSetProperty("recoveryInterval", recoveryInterval);
+            return this;
+        }
+        /**
+         * Sets whether synchronous processing should be strictly used, or Camel
+         * is allowed to use asynchronous processing (if supported).
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: advanced
+         * 
+         * @param synchronous the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder synchronous(
+                boolean synchronous) {
+            doSetProperty("synchronous", synchronous);
+            return this;
+        }
+        /**
+         * Sets whether synchronous processing should be strictly used, or Camel
+         * is allowed to use asynchronous processing (if supported).
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: advanced
+         * 
+         * @param synchronous the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder synchronous(
+                String synchronous) {
+            doSetProperty("synchronous", synchronous);
+            return this;
+        }
+        /**
+         * If enabled and you are using Request Reply messaging (InOut) and an
+         * Exchange failed on the consumer side, then the caused Exception will
+         * be send back in response as a javax.jms.ObjectMessage. If the client
+         * is Camel, the returned Exception is rethrown. This allows you to use
+         * Camel JMS as a bridge in your routing - for example, using persistent
+         * queues to enable robust routing. Notice that if you also have
+         * transferExchange enabled, this option takes precedence. The caught
+         * exception is required to be serializable. The original Exception on
+         * the consumer side can be wrapped in an outer exception such as
+         * org.apache.camel.RuntimeCamelException when returned to the producer.
+         * Use this with caution as the data is using Java Object serialization
+         * and requires the received to be able to deserialize the data at Class
+         * level, which forces a strong coupling between the producers and
+         * consumer!.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: advanced
+         * 
+         * @param transferException the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder transferException(
+                boolean transferException) {
+            doSetProperty("transferException", transferException);
+            return this;
+        }
+        /**
+         * If enabled and you are using Request Reply messaging (InOut) and an
+         * Exchange failed on the consumer side, then the caused Exception will
+         * be send back in response as a javax.jms.ObjectMessage. If the client
+         * is Camel, the returned Exception is rethrown. This allows you to use
+         * Camel JMS as a bridge in your routing - for example, using persistent
+         * queues to enable robust routing. Notice that if you also have
+         * transferExchange enabled, this option takes precedence. The caught
+         * exception is required to be serializable. The original Exception on
+         * the consumer side can be wrapped in an outer exception such as
+         * org.apache.camel.RuntimeCamelException when returned to the producer.
+         * Use this with caution as the data is using Java Object serialization
+         * and requires the received to be able to deserialize the data at Class
+         * level, which forces a strong coupling between the producers and
+         * consumer!.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: advanced
+         * 
+         * @param transferException the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSjms2EndpointConsumerBuilder transferException(
+                String transferException) {
+            doSetProperty("transferException", transferException);
+            return this;
+        }
+        /**
          * Specifies whether to share JMS session with other SJMS endpoints.
          * Turn this off if your route is accessing to multiple JMS providers.
          * If you need transaction against multiple JMS providers, use jms
@@ -1268,6 +1468,47 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
+         * Specifies whether to test the connection on startup. This ensures
+         * that when Camel starts that all the JMS consumers have a valid
+         * connection to the JMS broker. If a connection cannot be granted then
+         * Camel throws an exception on startup. This ensures that Camel is not
+         * started with failed connections. The JMS producers is tested as well.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param testConnectionOnStartup the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointProducerBuilder testConnectionOnStartup(
+                boolean testConnectionOnStartup) {
+            doSetProperty("testConnectionOnStartup", testConnectionOnStartup);
+            return this;
+        }
+        /**
+         * Specifies whether to test the connection on startup. This ensures
+         * that when Camel starts that all the JMS consumers have a valid
+         * connection to the JMS broker. If a connection cannot be granted then
+         * Camel throws an exception on startup. This ensures that Camel is not
+         * started with failed connections. The JMS producers is tested as well.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param testConnectionOnStartup the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointProducerBuilder testConnectionOnStartup(
+                String testConnectionOnStartup) {
+            doSetProperty("testConnectionOnStartup", testConnectionOnStartup);
+            return this;
+        }
+        /**
          * Specifies the delivery mode to be used. Possible values are those
          * defined by javax.jms.DeliveryMode. NON_PERSISTENT = 1 and PERSISTENT
          * = 2.
@@ -1511,6 +1752,42 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
+         * Specifies the default number of concurrent consumers when doing
+         * request/reply over JMS. See also the maxMessagesPerTask option to
+         * control dynamic scaling up/down of threads.
+         * 
+         * The option is a: &lt;code&gt;int&lt;/code&gt; type.
+         * 
+         * Default: 1
+         * Group: producer
+         * 
+         * @param replyToConcurrentConsumers the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointProducerBuilder replyToConcurrentConsumers(
+                int replyToConcurrentConsumers) {
+            doSetProperty("replyToConcurrentConsumers", replyToConcurrentConsumers);
+            return this;
+        }
+        /**
+         * Specifies the default number of concurrent consumers when doing
+         * request/reply over JMS. See also the maxMessagesPerTask option to
+         * control dynamic scaling up/down of threads.
+         * 
+         * The option will be converted to a &lt;code&gt;int&lt;/code&gt; type.
+         * 
+         * Default: 1
+         * Group: producer
+         * 
+         * @param replyToConcurrentConsumers the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointProducerBuilder replyToConcurrentConsumers(
+                String replyToConcurrentConsumers) {
+            doSetProperty("replyToConcurrentConsumers", replyToConcurrentConsumers);
+            return this;
+        }
+        /**
          * Provides an explicit ReplyTo destination in the JMS message, which
          * overrides the setting of replyTo. It is useful if you want to forward
          * the message to a remote Queue and receive the reply message from the
@@ -1529,6 +1806,54 @@ public interface Sjms2EndpointBuilderFactory {
             return this;
         }
         /**
+         * Allows for explicitly specifying which kind of strategy to use for
+         * replyTo queues when doing request/reply over JMS. Possible values
+         * are: Temporary, Shared, or Exclusive. By default Camel will use
+         * temporary queues. However if replyTo has been configured, then Shared
+         * is used by default. This option allows you to use exclusive queues
+         * instead of shared ones. See Camel JMS documentation for more details,
+         * and especially the notes about the implications if running in a
+         * clustered environment, and the fact that Shared reply queues has
+         * lower performance than its alternatives Temporary and Exclusive.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.sjms.ReplyToType&lt;/code&gt;
+         * type.
+         * 
+         * Group: producer
+         * 
+         * @param replyToType the value to set
+         * @return the dsl builder
+         */
+        default Sjms2EndpointProducerBuilder replyToType(ReplyToType replyToType) {
+            doSetProperty("replyToType", replyToType);
+            return this;
+        }
... 2156 lines suppressed ...