Repository: camel Updated Branches: refs/heads/master b788b9f7e -> 583a4a098
Converted the jms components wiki docs to ascii doc and integrated it into the gitbook build. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/583a4a09 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/583a4a09 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/583a4a09 Branch: refs/heads/master Commit: 583a4a09820d5f177ac1eb69407a600ab40fa548 Parents: b788b9f Author: Hiram Chirino <[email protected]> Authored: Thu Jan 21 13:00:44 2016 -0500 Committer: Hiram Chirino <[email protected]> Committed: Thu Jan 21 13:00:44 2016 -0500 ---------------------------------------------------------------------- camel-website/pom.xml | 12 +- components/camel-jms/src/main/docs/readme.adoc | 1689 +++++++++++++++++++ docs/user-manual/en/SUMMARY.md | 2 + 3 files changed, 1702 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/583a4a09/camel-website/pom.xml ---------------------------------------------------------------------- diff --git a/camel-website/pom.xml b/camel-website/pom.xml index 6aa9660..a3d4379 100644 --- a/camel-website/pom.xml +++ b/camel-website/pom.xml @@ -76,11 +76,21 @@ </condition> <!-- lets generate the gitbook --> + <mkdir dir="${basedir}/target/docs/user-manual" /> + <copy todir="${basedir}/target/docs/user-manual" > + <fileset dir="${basedir}/../docs/user-manual/en"/> + </copy> + <copy todir="${basedir}/target/docs/user-manual/components"> + <fileset dir="{basedir}/../../components"> + <include name="**/src/main/docs/**"/> + </fileset> + </copy> + <mkdir dir="${basedir}/target/classes/user-manual" /> <echo>executing ${gitbook.cmd}</echo> <exec executable="${gitbook.cmd}"> <arg value="build" /> - <arg value="${basedir}/../docs/user-manual/en" /> + <arg value="${basedir}/target/docs/user-manual" /> <arg value="${basedir}/target/classes/user-manual" /> </exec> http://git-wip-us.apache.org/repos/asf/camel/blob/583a4a09/components/camel-jms/src/main/docs/readme.adoc ---------------------------------------------------------------------- diff --git a/components/camel-jms/src/main/docs/readme.adoc b/components/camel-jms/src/main/docs/readme.adoc new file mode 100644 index 0000000..f786b2f --- /dev/null +++ b/components/camel-jms/src/main/docs/readme.adoc @@ -0,0 +1,1689 @@ +[[JMS-JMSComponent]] +JMS Component +~~~~~~~~~~~~~ + +Using ActiveMQ + +If you are using http://activemq.apache.org/[Apache ActiveMQ], you +should prefer the link:activemq.html[ActiveMQ] component as it has been +optimized for link:activemq.html[ActiveMQ]. All of the options and +samples on this page are also valid for the link:activemq.html[ActiveMQ] +component. + +Transacted and caching + +See section _Transactions and Cache Levels_ below if you are using +transactions with link:jms.html[JMS] as it can impact performance. + +Request/Reply over JMS + +Make sure to read the section _Request-reply over JMS_ further below on +this page for important notes about request/reply, as Camel offers a +number of options to configure for performance, and clustered +environments. + +This component allows messages to be sent to (or consumed from) a +http://java.sun.com/products/jms/[JMS] Queue or Topic. It uses Spring's +JMS support for declarative transactions, including Spring's +`JmsTemplate` for sending and a `MessageListenerContainer` for +consuming. + +Maven users will need to add the following dependency to their `pom.xml` +for this component: + +[source,xml] +------------------------------------------------------------ +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jms</artifactId> + <version>x.x.x</version> + <!-- use the same version as your Camel core version --> +</dependency> +------------------------------------------------------------ + +[[JMS-URIformat]] +URI format +^^^^^^^^^^ + +-------------------------------------------- +jms:[queue:|topic:]destinationName[?options] +-------------------------------------------- + +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: + +----------- +jms:FOO.BAR +----------- + +You can include the optional `queue:` prefix, if you prefer: + +----------------- +jms:queue:FOO.BAR +----------------- + +To connect to a topic, you _must_ include the `topic:` prefix. For +example, to + + connect to the topic, `Stocks.Prices`, use: + +----------------------- +jms:topic:Stocks.Prices +----------------------- + +You append query options to the URI using the following format, +`?option=value&option=value&...` + +[[JMS-Notes]] +Notes +^^^^^ + +[[JMS-UsingActiveMQ]] +Using ActiveMQ +++++++++++++++ + +The JMS component reuses Spring 2's `JmsTemplate` for sending messages. +This is not ideal for use in a non-J2EE container and typically requires +some caching in the JMS provider to avoid +http://activemq.apache.org/jmstemplate-gotchas.html[poor performance]. + +If you intend to use http://activemq.apache.org/[Apache ActiveMQ] as +your Message Broker - which is a good choice as ActiveMQ rocks +image:https://cwiki.apache.org/confluence/s/en_GB/5982/f2b47fb3d636c8bc9fd0b11c0ec6d0ae18646be7.1/_/images/icons/emoticons/smile.png[(smile)] +, then we recommend that you either: + +* Use the link:activemq.html[ActiveMQ] component, which is already +optimized to use ActiveMQ efficiently +* Use the `PoolingConnectionFactory` in ActiveMQ. + +[[JMS-TransactionsandCacheLevels]] +Transactions and Cache Levels ++++++++++++++++++++++++++++++ + + + + If you are consuming messages and using transactions +(`transacted=true`) then the default settings for cache level can impact +performance. + + If you are using XA transactions then you cannot cache as it can cause +the XA transaction to not work properly. + +If you are *not* using XA, then you should consider caching as it speeds +up performance, such as setting `cacheLevelName=CACHE_CONSUMER`. + +Through Camel 2.7.x, the default setting for `cacheLevelName` is +`CACHE_CONSUMER`. You will need to explicitly set +`cacheLevelName=CACHE_NONE`. + + In Camel 2.8 onwards, the default setting for `cacheLevelName` is +`CACHE_AUTO`. This default auto detects the mode and sets the cache +level accordingly to: + +* CACHE_CONSUMER = if transacted=false +* CACHE_NONE = if transacted=true + +So you can say the default setting is conservative. Consider using +`cacheLevelName=CACHE_CONSUMER` if you are using non-XA transactions. + +[[JMS-DurableSubscriptions]] +Durable Subscriptions ++++++++++++++++++++++ + +If you wish to use durable topic subscriptions, you need to specify both +*clientId* and **durableSubscriptionName**. The value of the `clientId` +must be unique and can only be used by a single JMS connection instance +in your entire network. You may prefer to use +http://activemq.apache.org/virtual-destinations.html[Virtual Topics] +instead to avoid this limitation. More background on durable messaging +http://activemq.apache.org/how-do-durable-queues-and-topics-work.html[here]. + +[[JMS-MessageHeaderMapping]] +Message Header Mapping +++++++++++++++++++++++ + +When using message headers, the JMS specification states that header +names must be valid Java identifiers. So try to name your headers to be +valid Java identifiers. One benefit of doing this is that you can then +use your headers inside a JMS Selector (whose SQL92 syntax mandates Java +identifier syntax for headers). + +A simple strategy for mapping header names is used by default. The +strategy is to replace any dots and hyphens in the header name as shown +below and to reverse the replacement when the header name is restored +from a JMS message sent over the wire. What does this mean? No more +losing method names to invoke on a bean component, no more losing the +filename header for the File Component, and so on. + +The current header name strategy for accepting header names in Camel is +as follows: + +* Dots are replaced by `_DOT_` and the replacement is reversed when +Camel consume the message +* Hyphen is replaced by `_HYPHEN_` and the replacement is reversed when +Camel consumes the message + +[[JMS-Options]] +Options +^^^^^^^ + +You can configure many different properties on the JMS endpoint which +map to properties on the +http://camel.apache.org/maven/current/camel-jms/apidocs/org/apache/camel/component/jms/JmsConfiguration.html[JMSConfiguration +POJO]. + +Mapping to Spring JMS + +Many of these properties map to properties on Spring JMS, which Camel +uses for sending and receiving messages. So you can get more information +about these properties by consulting the relevant Spring documentation. + +The options are divided into two tables, the first one with the most +common options used. The latter contains the rest. + +[[JMS-Mostcommonlyusedoptions]] +Most commonly used options +++++++++++++++++++++++++++ + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Option |Default Value |Description +|`clientId` |`null` |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. You may prefer to use +http://activemq.apache.org/virtual-destinations.html[Virtual Topics] +instead. + +|`concurrentConsumers` |`1` |Specifies the default number of concurrent +consumers. From *Camel 2.10.3* onwards this option can also be used when +doing request/reply over JMS. From *Camel 2.16* onwards there is a new +replyToConcurrentConsumers. See also the `maxMessagesPerTask` option to +control dynamic scaling up/down of threads. + +|`replyToConcurrentConsumers` |1 |*Camel 2.16:* Specifies the default +number of concurrent consumers when doing request/reply over JMS. + +|`disableReplyTo` |`false` |If `true`, a producer will behave like a +InOnly exchange with the exception that `JMSReplyTo` header is sent out +and not be suppressed like in the case of `InOnly`. Like `InOnly` the +producer will not wait for a reply. A consumer with this flag will +behave like `InOnly`. This feature can be used to bridge `InOut` +requests to another queue so that a route on the other queue will send +it´s response directly back to the original `JMSReplyTo`. + +|`durableSubscriptionName` |`null` |The durable subscriber name for +specifying durable topic subscriptions. The `clientId` option *must* be +configured as well. + +|`maxConcurrentConsumers` |`1` |Specifies the maximum number of +concurrent consumers. From *Camel 2.10.3* onwards this option can also +be used when doing request/reply over JMS. From **Camel 2.16** onwards +there is a new replyToMaxConcurrentConsumers. See also the +`maxMessagesPerTask` option to control dynamic scaling up/down of +threads. The `maxMessagesPerTask` option MUST be set to an integer +greater than 0 for threads to scale down. Otherwise, the number of +threads will stay at maxConcurrentConsumers until shutdown. + +|`replyToMaxConcurrentConsumers` |1 |*Camel 2.16:* Specifies the maximum +number of concurrent consumers when doing request/reply over JMS. See +also the `maxMessagesPerTask` option to control dynamic scaling up/down +of threads. + +|`maxMessagesPerTask` |`-1` |The number of messages per task. -1 is +unlimited. If you use a range for concurrent consumers (eg min < max), +then this option can be used to set a value to eg `100` to control how +fast the consumers will shrink when less work is required. + +|`preserveMessageQos` |`false` |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 +`explicitQosEnabled` option, by contrast, will only use options set on +the endpoint, and not values from the message header. + +|`replyTo` |`null` |Provides an explicit ReplyTo destination, which +overrides any incoming value of `Message.getJMSReplyTo()`. If you do +link:request-reply.html[Request Reply] over JMS then *make sure* to read +the section _Request-reply over JMS_ further below for more details, and +the `replyToType` option as well. + +|`replyToOverride` |`null` |*Camel 2.15:* 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` |`null` |*Camel 2.9:* 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 +further below 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`. + +|`requestTimeout` |`20000` |*Producer only:* The timeout for waiting for +a reply when using the InOut link:exchange-pattern.html[Exchange +Pattern] (in milliseconds). The default is 20 seconds. From *Camel +2.13/2.12.3* onwards you can include the header +`"CamelJmsRequestTimeout"` to override this endpoint configured timeout +value, and thus have per message individual timeout values. See below in +section _About time to live_ for more details. See also the +_requestTimeoutCheckerInterval_ option. + +|`selector` |`null` |Sets the JMS Selector, which is an SQL 92 predicate +that is used to filter messages within the broker. You may have to +encode special characters such as = as %3D **Before Camel 2.3.0**, we +don't support this option in CamelConsumerTemplate + +|`timeToLive` |`null` |When sending messages, specifies the time-to-live +of the message (in milliseconds). See below in section _About time to +live_ for more details. + +|`transacted` |`false` |Specifies whether to use transacted mode for +sending/receiving messages using the InOnly +link:exchange-pattern.html[Exchange Pattern]. + +|`testConnectionOnStartup` |`false` |*Camel 2.1:* 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. From +*Camel 2.8* onwards also the JMS producers is tested as well. +|======================================================================= + +[[JMS-Alltheotheroptions]] +All the other options ++++++++++++++++++++++ + + + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Option |Default Value |Description +|`acceptMessagesWhileStopping` |`false` |Specifies whether the consumer +accept messages while it is stopping. You may consider enabling this +option, if you start and stop link:jms.html[JMS] routes at runtime, +while there are still messages enqued on the queue. If this option is +`false`, and you stop the link:jms.html[JMS] route, then messages may be +rejected, and the JMS broker would have to attempt redeliveries, which +yet again may be rejected, and eventually the message may be moved at a +dead letter queue on the JMS broker. To avoid this its recommended to +enable this option. + +|`acknowledgementModeName` |`AUTO_ACKNOWLEDGE` |The JMS acknowledgement +name, which is one of: `SESSION_TRANSACTED`, `CLIENT_ACKNOWLEDGE`, +`AUTO_ACKNOWLEDGE`, `DUPS_OK_ACKNOWLEDGE` + +|`acknowledgementMode` |`-1` |The JMS acknowledgement mode defined as an +Integer. Allows you to set vendor-specific extensions to the +acknowledgment mode. For the regular modes, it is preferable to use the +`acknowledgementModeName` instead. + +|`allowNullBody` |`true` |*Camel 2.9.3/2.10.1:* Whether to allow sending +messages with no body. If this option is `false` and the message body is +null, then an `JMSException` is thrown. + +|`alwaysCopyMessage` |`false` |If `true`, Camel will always make a JMS +message copy of the message when it is passed to the producer for +sending. Copying the message is needed in some situations, such as when +a `replyToDestinationSelectorName` is set (incidentally, Camel will set +the `alwaysCopyMessage` option to `true`, if a +`replyToDestinationSelectorName` is set) + +|`asyncConsumer` |`false` |*Camel 2.9:* Whether the `JmsConsumer` +processes the link:exchange.html[Exchange] +link:asynchronous-routing-engine.html[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 +link:asynchronous-routing-engine.html[Asynchronous Routing Engine]). +This means that messages may be processed not 100% strictly in order. If +disabled (as default) then the link:exchange.html[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 transactions must +be executed synchronously (Camel 3.0 may support async transactions). + +|`asyncStartListener` |`false` |*Camel 2.10:* Whether to startup the +`JmsConsumer` 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 beware that if the connection could not be +established, then an exception is logged at `WARN` level, and the +consumer will not be able to receive messages; You can then restart the +route to retry. + +|`asyncStopListener` |`false` |*Camel 2.10:* Whether to stop the +`JmsConsumer` message listener asynchronously, when stopping a route. + +|`autoStartup` |`true` |Specifies whether the consumer container should +auto-startup. + +|`cacheLevelName` |CACHE_AUTO (Camel >= 2.8.0) + + CACHE_CONSUMER (Camel <= 2.7.1) |Sets the cache level by name for the +underlying JMS resources. Possible values are: `CACHE_AUTO`, +`CACHE_CONNECTION`, `CACHE_CONSUMER`, `CACHE_NONE`, and `CACHE_SESSION`. +The default setting for *Camel 2.8* and newer is `CACHE_AUTO`. For +*Camel 2.7.1* and older the default is `CACHE_CONSUMER`. See the +http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/jms/listener/DefaultMessageListenerContainer.html[Spring +documentation] and link:jms.html[Transactions Cache Levels] for more +information. + +|`cacheLevel` | |Sets the cache level by ID for the underlying JMS +resources. See `cacheLevelName` option for more details. + +|`consumerType` |`Default` |The consumer type to use, which can be one +of: `Simple`, `Default`, or `Custom`. The consumer type determines which +Spring JMS listener to use. `Default` will use +`org.springframework.jms.listener.DefaultMessageListenerContainer`, +`Simple` will use +`org.springframework.jms.listener.SimpleMessageListenerContainer`. When +`Custom` is specified, the `MessageListenerContainerFactory` defined by +the `messageListenerContainerFactoryRef` option will determine what +`org.springframework.jms.listener.AbstractMessageListenerContainer` to +use (**new option in Camel 2.10.2 onwards**). This option was temporary +removed in Camel 2.7 and 2.8. But has been added back from Camel 2.9 +onwards. + +|`connectionFactory` |`null` |The default JMS connection factory to use +for the `listenerConnectionFactory` and `templateConnectionFactory`, if +neither is specified. + +|`defaultTaskExecutorType` |(see description) |*Camel 2.10.4:* Specifies +what default TaskExecutor type to use in the +DefaultMessageListenerContainer, for both consumer endpoints and the +ReplyTo consumer of producer endpoints. Possible values: `SimpleAsync` +(uses Spring's +http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/core/task/SimpleAsyncTaskExecutor.html[SimpleAsyncTaskExecutor]) +or `ThreadPool` (uses Spring's +http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html[ThreadPoolTaskExecutor] +with optimal values - cached threadpool-like). If not set, it defaults +to the previous behaviour, which uses a cached thread pool for consumer +endpoints and SimpleAsync for reply consumers. The use of `ThreadPool` +is recommended to reduce "thread trash" in elastic configurations with +dynamically increasing and decreasing concurrent consumers. + +|`deliveryMode` |null |*Camel 2.12.2/2.13:* Specifies the delivery mode +to be used. Possibles values are those defined by +`javax.jms.DeliveryMode`. + +|`deliveryPersistent` |`true` |Specifies whether persistent delivery is +used by default. + +|`destination` |`null` |Specifies the JMS Destination object to use on +this endpoint. + +|`destinationName` |`null` |Specifies the JMS destination name to use on +this endpoint. + +|`destinationResolver` |`null` |A pluggable +`org.springframework.jms.support.destination.DestinationResolver` that +allows you to use your own resolver (for example, to lookup the real +destination in a JNDI registry). + +|`disableTimeToLive` |`false` |*Camel 2.8:* 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 will not expire on the receiver system. See +below in section _About time to live_ for more details. + +|`eagerLoadingOfProperties` |`false` |Enables eager loading of JMS +properties as soon as a message is received, which is generally +inefficient, because the JMS properties might not be required. But this +feature can sometimes catch early any issues with the underlying JMS +provider and the use of JMS properties. This feature can also be used +for testing purposes, to ensure JMS properties can be understood and +handled correctly. + +|`exceptionListener` |`null` |Specifies the JMS Exception Listener that +is to be notified of any underlying JMS exceptions. + +|`errorHandler` |`null` |*Camel 2.8.2, 2.9:* Specifies a +`org.springframework.util.ErrorHandler` to be invoked in case of any +uncaught exceptions thrown while processing a `Message`. By default +these exceptions will be logged at the WARN level, if no `errorHandler` +has been configured. From *Camel 2.9.1:* onwards you can configure +logging level and whether stack traces should be logged using the below +two options. This makes it much easier to configure, than having to code +a custom `errorHandler`. + +|`errorHandlerLoggingLevel` |`WARN` |*Camel 2.9.1:* Allows to configure +the default `errorHandler` logging level for logging uncaught +exceptions. + +|`errorHandlerLogStackTrace` |`true` |*Camel 2.9.1:* Allows to control +whether stacktraces should be logged or not, by the default +`errorHandler`. + +|`explicitQosEnabled` |`false` |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. + +|`exposeListenerSession` |`true` |Specifies whether the listener session +should be exposed when consuming messages. + +|`forceSendOriginalMessage` |`false` |*Camel 2.7:* When using +`mapJmsMessage=false` Camel will create a new JMS message to send to a +new JMS destination if you touch the headers (get or set) during the +route. Set this option to `true` to force Camel to send the original JMS +message that was received. + +|`idleTaskExecutionLimit` |`1` |Specifies the limit for idle executions +of a receive task, not having received any message within its execution. +If this limit is reached, the task will shut down and leave receiving to +other executing tasks (in the case of dynamic scheduling; see the +`maxConcurrentConsumers` setting). There is additional doc available +from +http://static.springsource.org/spring/docs/3.0.5.RELEASE/api/org/springframework/jms/listener/DefaultMessageListenerContainer.html#setIdleTaskExecutionLimit(int)[Spring]. + +|`idleConsumerLimit` |`1` |*Camel 2.8.2, 2.9:* Specify the limit for the +number of consumers that are allowed to be idle at any given time. + +|`includeSentJMSMessageID` |`false` |*Camel 2.10.3:* Only applicable +when sending to JMS destination using InOnly (eg fire and forget). +Enabling this option will enrich the Camel link:exchange.html[Exchange] +with the actual JMSMessageID that was used by the JMS client when the +message was sent to the JMS destination. + +|`includeAllJMSXProperties` |`false` |*Camel 2.11.2/2.12:* Whether to +include all JMSXxxx properties when mapping from JMS to Camel Message. +Setting this to `true` will include properties such as `JMSXAppID`, and +`JMSXUserID` etc. *Note:* If you are using a custom +`headerFilterStrategy` then this option does not apply. + +|`jmsMessageType` |`null` |Allows you to force the use of a specific +`javax.jms.Message` implementation for sending JMS messages. Possible +values are: `Bytes`, `Map`, `Object`, `Stream`, `Text`. By default, +Camel would determine which JMS message type to use from the In body +type. This option allows you to specify it. + +|`jmsKeyFormatStrategy` |`default` |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.camel.component.jms.JmsKeyFormatStrategy` and refer to +it using the `#` notation. + +|`jmsOperations` |`null` |Allows you to use your own implementation of +the `org.springframework.jms.core.JmsOperations` interface. Camel uses +`JmsTemplate` as default. Can be used for testing purpose, but not used +much as stated in the spring API docs. + +|`lazyCreateTransactionManager` |`true` |If `true`, Camel will create a +`JmsTransactionManager`, if there is no `transactionManager` injected +when option `transacted=true`. + +|`listenerConnectionFactory` |`null` |The JMS connection factory used +for consuming messages. + +|`mapJmsMessage` |`true` |Specifies whether Camel should auto map the +received JMS message to an appropiate payload type, such as +`javax.jms.TextMessage` to a `String` etc. See section about how mapping +works below for more details. + +|`maximumBrowseSize` |`-1` |Limits the number of messages fetched at +most, when browsing endpoints using link:browse.html[Browse] or JMX API. + +|`messageConverter` |`null` |To use a custom Spring +`org.springframework.jms.support.converter.MessageConverter` so you can +be 100% in control how to map to/from a `javax.jms.Message`. + +|`messageIdEnabled` |`true` |When sending, specifies whether message IDs +should be added. + +|`messageListenerContainerFactoryRef` |`null` |*Camel 2.10.2:* Registry +ID of the `MessageListenerContainerFactory` used to determine what +`org.springframework.jms.listener.AbstractMessageListenerContainer` to +use to consume messages. Setting this will automatically set +`consumerType` to `Custom`. + +|`messageTimestampEnabled` |`true` |Specifies whether timestamps should +be enabled by default on sending messages. + +|`password` |`null` |The password for the connector factory. + +|`priority` |`4` |Values greater than 1 specify the message priority +when sending (where 0 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. + +|`pubSubNoLocal` |`false` |Specifies whether to inhibit the delivery of +messages published by its own connection. + +|`receiveTimeout` |1000 |The timeout for receiving messages (in +milliseconds). + +|`recoveryInterval` |`5000` |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. + +|`replyToSameDestinationAllowed` |`false` |*Camel 2.16:* **Consumer +only:**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. + +|`replyToCacheLevelName` |CACHE_CONSUMER |*Camel 2.9.1:* Sets the cache +level by name for the reply consumer when doing request/reply over JMS. +This option only applies when using fixed reply queues (not temporary). +Camel will by default use: `CACHE_CONSUMER` for exclusive or shared w/ +`replyToSelectorName`. And `CACHE_SESSION` for shared without +`replyToSelectorName`. Some JMS brokers such as IBM WebSphere may +require to set the `replyToCacheLevelName=CACHE_NONE` to work. *Note:* +If using temporary queues then `CACHE_NONE` is not allowed, and you must +use a higher value such as `CACHE_CONSUMER` or `CACHE_SESSION`. + +|`replyToDestinationSelectorName` |`null` |Sets the JMS Selector using +the fixed name to be used so you can filter out your own replies from +the others when using a shared queue (that is, if you are not using a +temporary reply queue). + +|`replyToDeliveryPersistent` |`true` |Specifies whether to use +persistent delivery by default for replies. + +|`requestTimeoutCheckerInterval` |`1000` |*Camel 2.9.2:* Configures how +often Camel should check for timed out link:exchange.html[Exchange]s +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__. + +|`subscriptionDurable` |`false` |*@deprecated:* Enabled by default, if +you specify a `durableSubscriptionName` and a `clientId`. + +|`taskExecutor` |`null` |Allows you to specify a custom task executor +for consuming messages. + +|`taskExecutorSpring2` |`null` |*Camel 2.6:* To use when using Spring +2.x with Camel. Allows you to specify a custom task executor for +consuming messages. + +|`templateConnectionFactory` |`null` |The JMS connection factory used +for sending messages. + +|`transactedInOut` |`false` |*@deprecated:* Specifies whether to use +transacted mode for sending messages using the InOut +link:exchange-pattern.html[Exchange Pattern]. Applies only to producer +endpoints. See section link:jms.html[Enabling Transacted Consumption] +for more details. + +|`transactionManager` |`null` |The Spring transaction manager to use. + +|`transactionName` |`"JmsConsumer [destinationName]"` |The name of the +transaction to use. + +|`transactionTimeout` |`null` |The timeout value of the transaction (in +seconds), if using transacted mode. + +|`transferException` |`false` |If enabled and you are using +link:request-reply.html[Request Reply] messaging (InOut) and an +link:exchange.html[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 link:jms.html[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. + +|`transferFault` |`false` |*Camel 2.17:* If enabled and you are using +Request Reply messaging (InOut) and an Exchange failed with a SOAP fault +(not exception) on the consumer side, then the fault flag on +org.apache.camel.Message.isFault() will be send back in the response as +a JMS header with the key JmsConstants.JMS_TRANSFER_FAULT. If the client +is Camel, the returned fault flag will be set on the +org.apache.camel.Message.setFault(boolean). You may want to enable this +when using Camel components that support faults such as SOAP based such +as cxf or spring-ws. + +|`transferExchange` |`false` |You can transfer the exchange over the +wire instead of just the body and headers. The following fields are +transferred: In body, Out body, Fault body, In headers, Out headers, +Fault headers, exchange properties, exchange exception. This requires +that the objects are serializable. Camel will exclude any +non-serializable objects and log it at `WARN` level. You *must* enable +this option on both the producer and consumer side, so Camel knows the +payloads is an Exchange and not a regular payload. + +|`username` |`null` |The username for the connector factory. + +|`useMessageIDAsCorrelationID` |`false` |Specifies whether +`JMSMessageID` should always be used as `JMSCorrelationID` for *InOut* +messages. + +|`useVersion102` |`false` |*@deprecated (removed from Camel 2.5 +onwards):* Specifies whether the old JMS API should be used. +|======================================================================= + +[[JMS-MessageMappingbetweenJMSandCamel]] +Message Mapping between JMS and Camel +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Camel automatically maps messages between `javax.jms.Message` and +`org.apache.camel.Message`. + +When sending a JMS message, Camel converts the message body to the +following JMS message types: + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Body Type |JMS Message |Comment +|`String` |`javax.jms.TextMessage` | + +|`org.w3c.dom.Node` |`javax.jms.TextMessage` |The DOM will be converted +to `String`. + +|`Map` |`javax.jms.MapMessage` | + +|`java.io.Serializable` |`javax.jms.ObjectMessage` | + +|`byte[]` |`javax.jms.BytesMessage` | + +|`java.io.File` |`javax.jms.BytesMessage` | + +|`java.io.Reader` |`javax.jms.BytesMessage` | + +|`java.io.InputStream` |`javax.jms.BytesMessage` | + +|`java.nio.ByteBuffer` |`javax.jms.BytesMessage` | +|======================================================================= + +When receiving a JMS message, Camel converts the JMS message to the +following body type: + +[width="100%",cols="50%,50%",options="header",] +|============================================= +|JMS Message |Body Type +|`javax.jms.TextMessage` |`String` +|`javax.jms.BytesMessage` |`byte[]` +|`javax.jms.MapMessage` |`Map<String, Object>` +|`javax.jms.ObjectMessage` |`Object` +|============================================= + +[[JMS-Disablingauto-mappingofJMSmessages]] +Disabling auto-mapping of JMS messages +++++++++++++++++++++++++++++++++++++++ + +You can use the `mapJmsMessage` option to disable the auto-mapping +above. If disabled, Camel will not try to map the received JMS message, +but instead uses it directly as the payload. This allows you to avoid +the overhead of mapping and let Camel just pass through the JMS message. +For instance, it even allows you to route `javax.jms.ObjectMessage` JMS +messages with classes you do *not* have on the classpath. + +[[JMS-UsingacustomMessageConverter]] +Using a custom MessageConverter ++++++++++++++++++++++++++++++++ + +You can use the `messageConverter` option to do the mapping yourself in +a Spring `org.springframework.jms.support.converter.MessageConverter` +class. + +For example, in the route below we use a custom message converter when +sending a message to the JMS order queue: + +[source,java] +---------------------------------------------------------------------------------------- + from("file://inbox/order").to("jms:queue:order?messageConverter=#myMessageConverter"); +---------------------------------------------------------------------------------------- + +You can also use a custom message converter when consuming from a JMS +destination. + +[[JMS-Controllingthemappingstrategyselected]] +Controlling the mapping strategy selected ++++++++++++++++++++++++++++++++++++++++++ + +You can use the *jmsMessageType* option on the endpoint URL to force a +specific message type for all messages. + + In the route below, we poll files from a folder and send them as +`javax.jms.TextMessage` as we have forced the JMS producer endpoint to +use text messages: + +[source,java] +----------------------------------------------------------------------- + from("file://inbox/order").to("jms:queue:order?jmsMessageType=Text"); +----------------------------------------------------------------------- + +You can also specify the message type to use for each messabe by setting +the header with the key `CamelJmsMessageType`. For example: + +[source,java] +--------------------------------------------------------------------------------------------------------- + from("file://inbox/order").setHeader("CamelJmsMessageType", JmsMessageType.Text).to("jms:queue:order"); +--------------------------------------------------------------------------------------------------------- + +The possible values are defined in the `enum` class, +`org.apache.camel.jms.JmsMessageType`. + +[[JMS-Messageformatwhensending]] +Message format when sending +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The exchange that is sent over the JMS wire must conform to the +http://java.sun.com/j2ee/1.4/docs/api/javax/jms/Message.html[JMS Message +spec]. + +For the `exchange.in.header` the following rules apply for the header +**keys**: + +* Keys starting with `JMS` or `JMSX` are reserved. +* `exchange.in.headers` keys must be literals and all be valid Java +identifiers (do not use dots in the key name). +* Camel replaces dots & hyphens and the reverse when when consuming JMS +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**: + +* The values must be primitives or their counter objects (such as +`Integer`, `Long`, `Character`). The types, `String`, `CharSequence`, +`Date`, `BigDecimal` and `BigInteger` are all converted to their +`toString()` representation. All other types are dropped. + +Camel will log with category `org.apache.camel.component.jms.JmsBinding` +at *DEBUG* level if it drops a given header value. For example: + +---------------------------------------------------------------------------------------------------------------------------------------------------------------- +2008-07-09 06:43:04,046 [main ] DEBUG JmsBinding + - Ignoring non primitive header: order of class: org.apache.camel.component.jms.issues.DummyOrder with value: DummyOrder{orderId=333, itemId=4444, quantity=2} +---------------------------------------------------------------------------------------------------------------------------------------------------------------- + +[[JMS-Messageformatwhenreceiving]] +Message format when receiving +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Camel adds the following properties to the `Exchange` when it receives a +message: + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Property |Type |Description +|`org.apache.camel.jms.replyDestination` |`javax.jms.Destination` |The +reply destination. +|======================================================================= + +Camel adds the following JMS properties to the In message headers when +it receives a JMS message: + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Header |Type |Description +|`JMSCorrelationID` |`String` |The JMS correlation ID. + +|`JMSDeliveryMode` |`int` |The JMS delivery mode. + +|`JMSDestination` |`javax.jms.Destination` |The JMS destination. + +|`JMSExpiration` |`long` |The JMS expiration. + +|`JMSMessageID` |`String` |The JMS unique message ID. + +|`JMSPriority` |`int` |The JMS priority (with 0 as the lowest priority +and 9 as the highest). + +|`JMSRedelivered` |`boolean` |Is the JMS message redelivered. + +|`JMSReplyTo` |`javax.jms.Destination` |The JMS reply-to destination. + +|`JMSTimestamp` |`long` |The JMS timestamp. + +|`JMSType` |`String` |The JMS type. + +|`JMSXGroupID` |`String` |The JMS group ID. +|======================================================================= + +As all the above information is standard JMS you can check the +http://java.sun.com/javaee/5/docs/api/javax/jms/Message.html[JMS +documentation] for further details. + +[[JMS-AboutusingCameltosendandreceivemessagesandJMSReplyTo]] +About using Camel to send and receive messages and JMSReplyTo +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The JMS component is complex and you have to pay close attention to how +it works in some cases. So this is a short summary of some of the +areas/pitfalls to look for. + +When Camel sends a message using its `JMSProducer`, it checks the +following conditions: + +* The message exchange pattern, +* Whether a `JMSReplyTo` was set in the endpoint or in the message +headers, +* Whether any of the following options have been set on the JMS +endpoint: `disableReplyTo`, `preserveMessageQos`, `explicitQosEnabled`. + +All this can be a tad complex to understand and configure to support +your use case. + +[[JMS-JmsProducer]] +JmsProducer ++++++++++++ + +The `JmsProducer` behaves as follows, depending on configuration: + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Exchange Pattern |Other options |Description +|_InOut_ |- |Camel will expect a reply, set a temporary `JMSReplyTo`, +and after sending the message, it will start to listen for the reply +message on the temporary queue. + +|_InOut_ |`JMSReplyTo` is set |Camel will expect a reply and, after +sending the message, it will start to listen for the reply message on +the specified `JMSReplyTo` queue. + +|_InOnly_ |- |Camel will send the message and *not* expect a reply. + +|_InOnly_ |`JMSReplyTo` is set |By default, Camel discards the +`JMSReplyTo` destination and clears the `JMSReplyTo` header before +sending the message. Camel then sends the message and does *not* expect +a reply. Camel logs this in the log at `WARN` level (changed to `DEBUG` +level from *Camel 2.6* onwards. You can use `preserveMessageQuo=true` to +instruct Camel to keep the `JMSReplyTo`. In all situations the +`JmsProducer` does *not* expect any reply and thus continue after +sending the message. +|======================================================================= + +[[JMS-JmsConsumer]] +JmsConsumer ++++++++++++ + +The `JmsConsumer` behaves as follows, depending on configuration: + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Exchange Pattern |Other options |Description +|_InOut_ |- |Camel will send the reply back to the `JMSReplyTo` queue. + +|_InOnly_ |- |Camel will not send a reply back, as the pattern is +__InOnly__. + +|- |`disableReplyTo=true` |This option suppresses replies. +|======================================================================= + +So pay attention to the message exchange pattern set on your exchanges. + +If you send a message to a JMS destination in the middle of your route +you can specify the exchange pattern to use, see more at +link:request-reply.html[Request Reply]. + + This is useful if you want to send an `InOnly` message to a JMS topic: + +[source,java] +------------------------------------------------------ +from("activemq:queue:in") + .to("bean:validateOrder") + .to(ExchangePattern.InOnly, "activemq:topic:order") + .to("bean:handleOrder"); +------------------------------------------------------ + +[[JMS-Reuseendpointandsendtodifferentdestinationscomputedatruntime]] +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 JMS 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. + +You can specify the destination in the following headers: + +[width="100%",cols="10%,10%,80%",options="header",] +|===================================================================== +|Header |Type |Description +|`CamelJmsDestination` |`javax.jms.Destination` |A destination object. +|`CamelJmsDestinationName` |`String` |The destination name. +|===================================================================== + +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("file://inbox") + .to("bean:computeDestination") + .to("activemq:queue:dummy"); +-------------------------------- + +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. + +In the `computeDestination` bean, specify the real destination by +setting the `CamelJmsDestinationName` header as follows: + +[source,java] +------------------------------------------------------------------------- +public void setJmsHeader(Exchange exchange) { + String id = .... + exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id"); +} +------------------------------------------------------------------------- + +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 `activemq:queue:order:2`, assuming the `id` value was 2. + +If both the `CamelJmsDestination` and the `CamelJmsDestinationName` +headers are set, `CamelJmsDestination` takes priority. Keep in mind that +the JMS producer removes both `CamelJmsDestination` and +`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). + +[[JMS-ConfiguringdifferentJMSproviders]] +Configuring different JMS providers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can configure your JMS provider in link:spring.html[Spring] XML as +follows: + +Basically, you can configure as many JMS component instances as you wish +and give them *a unique name using the* `id` **attribute**. The +preceding example configures an `activemq` component. You could do the +same to configure MQSeries, TibCo, BEA, Sonic and so on. + +Once you have a named JMS component, you can then refer to endpoints +within that component using URIs. For example for the component name, +`activemq`, you can then refer to destinations using the URI format, +`activemq:[queue:|topic:]destinationName`. You can use the same approach +for all other JMS providers. + +This works by the SpringCamelContext lazily fetching components from the +spring context for the scheme name you use for +link:endpoint.html[Endpoint] link:uris.html[URIs] and having the +link:component.html[Component] resolve the endpoint URIs. + +[[JMS-UsingJNDItofindtheConnectionFactory]] +Using JNDI to find the ConnectionFactory +++++++++++++++++++++++++++++++++++++++++ + +If you are using a J2EE container, you might need to look up JNDI to +find the JMS `ConnectionFactory` rather than use the usual `<bean>` +mechanism in Spring. You can do this using Spring's factory bean or the +new Spring XML namespace. For example: + +[source,xml] +----------------------------------------------------------------------------- +<bean id="weblogic" class="org.apache.camel.component.jms.JmsComponent"> + <property name="connectionFactory" ref="myConnectionFactory"/> +</bean> + +<jee:jndi-lookup id="myConnectionFactory" jndi-name="jms/connectionFactory"/> +----------------------------------------------------------------------------- + +See +http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/xsd-config.html#xsd-config-body-schemas-jee[The +jee schema] in the Spring reference documentation for more details about +JNDI lookup. + +[[JMS-ConcurrentConsuming]] +Concurrent Consuming +^^^^^^^^^^^^^^^^^^^^ + +A common requirement with JMS is to consume messages concurrently in +multiple threads in order to make an application more responsive. You +can set the `concurrentConsumers` option to specify the number of +threads servicing the JMS endpoint, as follows: + +[source,java] +--------------------------------------------- +from("jms:SomeQueue?concurrentConsumers=20"). + bean(MyClass.class); +--------------------------------------------- + +You can configure this option in one of the following ways: + +* On the `JmsComponent`, +* On the endpoint URI or, +* By invoking `setConcurrentConsumers()` directly on the `JmsEndpoint`. + +[[JMS-ConcurrentConsumingwithasyncconsumer]] +Concurrent Consuming with async consumer +++++++++++++++++++++++++++++++++++++++++ + +Notice that each concurrent consumer will only pickup the next available +message from the JMS broker, when the current message has been fully +processed. You can set the option `asyncConsumer=true` to let the +consumer pickup the next message from the JMS queue, while the previous +message is being processed asynchronously (by the +link:asynchronous-routing-engine.html[Asynchronous Routing Engine]). See +more details in the table on top of the page about the `asyncConsumer` +option. + +[source,java] +---------------------------------------------------------------- +from("jms:SomeQueue?concurrentConsumers=20&asyncConsumer=true"). + bean(MyClass.class); +---------------------------------------------------------------- + +[[JMS-Request-replyoverJMS]] +Request-reply over JMS +^^^^^^^^^^^^^^^^^^^^^^ + +Camel supports link:request-reply.html[Request Reply] over JMS. In +essence the MEP of the Exchange should be `InOut` when you send a +message to a JMS queue. + +Camel offers a number of options to configure request/reply over JMS +that influence performance and clustered environments. The table below +summaries the options. + +[width="100%",cols="10%,10%,10%,70%",options="header",] +|======================================================================= +|Option |Performance |Cluster |Description +|`Temporary` |Fast |Yes |A temporary queue is used as reply queue, and +automatic created by Camel. To use this do *not* specify a replyTo queue +name. And you can optionally configure `replyToType=Temporary` to make +it stand out that temporary queues are in use. + +|`Shared` |Slow |Yes |A shared persistent queue is used as reply queue. +The queue must be created beforehand, although some brokers can create +them on the fly such as Apache ActiveMQ. To use this you must specify +the replyTo queue name. And you can optionally configure +`replyToType=Shared` to make it stand out that shared queues are in use. +A shared queue can be used in a clustered environment with multiple +nodes running this Camel application at the same time. All using the +same shared reply queue. This is possible because JMS Message selectors +are used to correlate expected reply messages; this impacts performance +though. JMS Message selectors is slower, and therefore not as fast as +`Temporary` or `Exclusive` queues. See further below how to tweak this +for better performance. + +|`Exclusive` |Fast |No (*Yes) |An exclusive persistent queue is used as +reply queue. The queue must be created beforehand, although some brokers +can create them on the fly such as Apache ActiveMQ. To use this you must +specify the replyTo queue name. And you *must* configure +`replyToType=Exclusive` to instruct Camel to use exclusive queues, as +`Shared` is used by default, if a `replyTo` queue name was configured. +When using exclusive reply queues, then JMS Message selectors are *not* +in use, and therefore other applications must not use this queue as +well. An exclusive queue *cannot* be used in a clustered environment +with multiple nodes running this Camel application at the same time; as +we do not have control if the reply queue comes back to the same node +that sent the request message; that is why shared queues use JMS Message +selectors to make sure of this. *Though* if you configure each Exclusive +reply queue with an unique name per node, then you can run this in a +clustered environment. As then the reply message will be sent back to +that queue for the given node, that awaits the reply message. + +|`concurrentConsumers` |Fast |Yes |*Camel 2.10.3:* Allows to process +reply messages concurrently using concurrent message listeners in use. +You can specify a range using the `concurrentConsumers` and +`maxConcurrentConsumers` options. *Notice:* That using `Shared` reply +queues may not work as well with concurrent listeners, so use this +option with care. + +|`maxConcurrentConsumers` |Fast |Yes |*Camel 2.10.3:* Allows to process +reply messages concurrently using concurrent message listeners in use. +You can specify a range using the `concurrentConsumers` and +`maxConcurrentConsumers` options. *Notice:* That using `Shared` reply +queues may not work as well with concurrent listeners, so use this +option with care. +|======================================================================= + +The `JmsProducer` detects the `InOut` and provides a `JMSReplyTo` header +with the reply destination to be used. By default Camel uses a temporary +queue, but you can use the `replyTo` option on the endpoint to specify a +fixed reply queue (see more below about fixed reply queue). + +Camel will automatic setup a consumer which listen on the reply queue, +so you should *not* do anything. + + This consumer is a Spring `DefaultMessageListenerContainer` which +listen for replies. However it's fixed to 1 concurrent consumer. + + That means replies will be processed in sequence as there are only 1 +thread to process the replies. If you want to process replies faster, +then we need to use concurrency. But *not* using the +`concurrentConsumer` option. We should use the `threads` from the Camel +DSL instead, as shown in the route below: + +Instead of using threads, then use concurrentConsumers option if using +Camel 2.10.3 or better. See further below. + +[source,java] +--------------------------------- +from(xxx) +.inOut().to("activemq:queue:foo") +.threads(5) +.to(yyy) +.to(zzz); +--------------------------------- + +In this route we instruct Camel to route replies +link:async.html[asynchronously] using a thread pool with 5 threads. + +From *Camel 2.10.3* onwards you can now configure the listener to use +concurrent threads using the `concurrentConsumers` and +`maxConcurrentConsumers` options. This allows you to easier configure +this in Camel as shown below: + +[source,java] +------------------------------------------------------- +from(xxx) +.inOut().to("activemq:queue:foo?concurrentConsumers=5") +.to(yyy) +.to(zzz); +------------------------------------------------------- + +[[JMS-Request-replyoverJMSandusingasharedfixedreplyqueue]] +Request-reply over JMS and using a shared fixed reply queue ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +If you use a fixed reply queue when doing +link:request-reply.html[Request Reply] over JMS as shown in the example +below, then pay attention. + +[source,java] +--------------------------------------------- +from(xxx) +.inOut().to("activemq:queue:foo?replyTo=bar") +.to(yyy) +--------------------------------------------- + +In this example the fixed reply queue named "bar" is used. By default +Camel assumes the queue is shared when using fixed reply queues, and +therefore it uses a `JMSSelector` to only pickup the expected reply +messages (eg based on the `JMSCorrelationID`). See next section for +exclusive fixed reply queues. That means its not as fast as temporary +queues. You can speedup how often Camel will pull for reply messages +using the `receiveTimeout` option. By default its 1000 millis. So to +make it faster you can set it to 250 millis to pull 4 times per second +as shown: + +[source,java] +---------------------------------------------------------------- +from(xxx) +.inOut().to("activemq:queue:foo?replyTo=bar&receiveTimeout=250") +.to(yyy) +---------------------------------------------------------------- + +Notice this will cause the Camel to send pull requests to the message +broker more frequent, and thus require more network traffic. + + It is generally recommended to use temporary queues if possible. + +[[JMS-Request-replyoverJMSandusinganexclusivefixedreplyqueue]] +Request-reply over JMS and using an exclusive fixed reply queue ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +*Available as of Camel 2.9* + +In the previous example, Camel would anticipate the fixed reply queue +named "bar" was shared, and thus it uses a `JMSSelector` to only consume +reply messages which it expects. However there is a drawback doing this +as JMS selectos is slower. Also the consumer on the reply queue is +slower to update with new JMS selector ids. In fact it only updates when +the `receiveTimeout` option times out, which by default is 1 second. So +in theory the reply messages could take up till about 1 sec to be +detected. On the other hand if the fixed reply queue is exclusive to the +Camel reply consumer, then we can avoid using the JMS selectors, and +thus be more performant. In fact as fast as using temporary queues. So +in *Camel 2.9* onwards we introduced the `ReplyToType` option which you +can configure to `Exclusive` + + to tell Camel that the reply queue is exclusive as shown in the example +below: + +[source,java] +------------------------------------------------------------------- +from(xxx) +.inOut().to("activemq:queue:foo?replyTo=bar&replyToType=Exclusive") +.to(yyy) +------------------------------------------------------------------- + +Mind that the queue must be exclusive to each and every endpoint. So if +you have two routes, then they each need an unique reply queue as shown +in the next example: + +[source,java] +----------------------------------------------------------------------------- +from(xxx) +.inOut().to("activemq:queue:foo?replyTo=bar&replyToType=Exclusive") +.to(yyy) + +from(aaa) +.inOut().to("activemq:queue:order?replyTo=order.reply&replyToType=Exclusive") +.to(bbb) +----------------------------------------------------------------------------- + +The same applies if you run in a clustered environment. Then each node +in the cluster must use an unique reply queue name. As otherwise each +node in the cluster may pickup messages which was intended as a reply on +another node. For clustered environments its recommended to use shared +reply queues instead. + +[[JMS-Synchronizingclocksbetweensendersandreceivers]] +Synchronizing clocks between senders and receivers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When doing messaging between systems, its desirable that the systems +have synchronized clocks. For example when sending a link:jms.html[JMS] +message, then you can set a time to live value on the message. Then the +receiver can inspect this value, and determine if the message is already +expired, and thus drop the message instead of consume and process it. +However this requires that both sender and receiver have synchronized +clocks. If you are using http://activemq.apache.org/[ActiveMQ] then you +can use the http://activemq.apache.org/timestampplugin.html[timestamp +plugin] to synchronize clocks. + +[[JMS-Abouttimetolive]] +About time to live +^^^^^^^^^^^^^^^^^^ + +Read first above about synchronized clocks. + +When you do request/reply (InOut) over link:jms.html[JMS] with Camel +then Camel uses a timeout on the sender side, which is default 20 +seconds from the `requestTimeout` option. You can control this by +setting a higher/lower value. However the time to live value is still +set on the link:jms.html[JMS] message being send. So that requires the +clocks to be synchronized between the systems. If they are not, then you +may want to disable the time to live value being set. This is now +possible using the `disableTimeToLive` option from *Camel 2.8* onwards. +So if you set this option to `disableTimeToLive=true`, then Camel does +*not* set any time to live value when sending link:jms.html[JMS] +messages. *But* the request timeout is still active. So for example if +you do request/reply over link:jms.html[JMS] and have disabled time to +live, then Camel will still use a timeout by 20 seconds (the +`requestTimeout` option). That option can of course also be configured. +So the two options `requestTimeout` and `disableTimeToLive` gives you +fine grained control when doing request/reply. + +From *Camel 2.13/2.12.3* onwards you can provide a header in the message +to override and use as the request timeout value instead of the endpoint +configured value. For example: + +[source,java] +-------------------------------------------------------- + from("direct:someWhere") + .to("jms:queue:foo?replyTo=bar&requestTimeout=30s") + .to("bean:processReply"); +-------------------------------------------------------- + +In the route above we have a endpoint configured `requestTimeout` of 30 +seconds. So Camel will wait up till 30 seconds for that reply message to +come back on the bar queue. If no reply message is received then a +`org.apache.camel.ExchangeTimedOutException` is set on the +link:exchange.html[Exchange] and Camel continues routing the message, +which would then fail due the exception, and Camel's error handler +reacts. + +If you want to use a per message timeout value, you can set the header +with key +`org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT` which +has constant value `"CamelJmsRequestTimeout"` with a timeout value as +long type. + +For example we can use a bean to compute the timeout value per +individual message, such as calling the `"whatIsTheTimeout"` method on +the service bean as shown below: + +[source,java] +---------------------------------------------------------------------------------------- + from("direct:someWhere") + .setHeader("CamelJmsRequestTimeout", method(ServiceBean.class, "whatIsTheTimeout")) + .to("jms:queue:foo?replyTo=bar&requestTimeout=30s") + .to("bean:processReply"); +---------------------------------------------------------------------------------------- + +When you do fire and forget (InOut) over link:jms.html[JMS] with Camel +then Camel by default does *not* set any time to live value on the +message. You can configure a value by using the `timeToLive` option. For +example to indicate a 5 sec., you set `timeToLive=5000`. The option +`disableTimeToLive` can be used to force disabling the time to live, +also for InOnly messaging. The `requestTimeout` option is not being used +for InOnly messaging. + +[[JMS-EnablingTransactedConsumption]] +Enabling Transacted Consumption +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A common requirement is to consume from a queue in a transaction and +then process the message using the Camel route. To do this, just ensure +that you set the following properties on the component/endpoint: + +* `transacted` = true +* `transactionManager` = a _Transsaction Manager_ - typically the +`JmsTransactionManager` + +See the link:transactional-client.html[Transactional Client] EIP pattern +for further details. + +Transactions and [Request Reply] over JMS + +When using link:request-reply.html[Request Reply] over JMS you cannot +use a single transaction; JMS will not send any messages until a commit +is performed, so the server side won't receive anything at all until the +transaction commits. Therefore to use link:request-reply.html[Request +Reply] you must commit a transaction after sending the request and then +use a separate transaction for receiving the response. + +To address this issue the JMS component uses different properties to +specify transaction use for oneway messaging and request reply +messaging: + +The `transacted` property applies *only* to the InOnly message +link:exchange-pattern.html[Exchange Pattern] (MEP). + +The `transactedInOut` property applies to the +InOut(link:request-reply.html[Request Reply]) message +link:exchange-pattern.html[Exchange Pattern] (MEP). + +If you want to use transactions for link:request-reply.html[Request +Reply](InOut MEP), you *must* set `transactedInOut=true`. + +*Available as of Camel 2.10* + +You can leverage the +http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jms/listener/AbstractPollingMessageListenerContainer.html#setSessionTransacted(boolean)[DMLC +transacted session API] using the following properties on +component/endpoint: + +* `transacted` = true +* `lazyCreateTransactionManager` = false + +The benefit of doing so is that the cacheLevel setting will be honored +when using local transactions without a configured TransactionManager. +When a TransactionManager is configured, no caching happens at DMLC +level and its necessary to rely on a pooled connection factory. For more +details about this kind of setup see +http://tmielke.blogspot.com/2012/03/camel-jms-with-transactions-lessons.html[here] +and +http://forum.springsource.org/showthread.php?123631-JMS-DMLC-not-caching%20connection-when-using-TX-despite-cacheLevel-CACHE_CONSUMER&p=403530&posted=1#post403530[here]. + +[[JMS-UsingJMSReplyToforlatereplies]] +Using JMSReplyTo for late replies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When using Camel as a JMS listener, it sets an Exchange property with +the value of the ReplyTo `javax.jms.Destination` object, having the key +`ReplyTo`. You can obtain this `Destination` as follows: + +[source,java] +----------------------------------------------------------------------------------------------------------------- +Destination replyDestination = exchange.getIn().getHeader(JmsConstants.JMS_REPLY_DESTINATION, Destination.class); +----------------------------------------------------------------------------------------------------------------- + +And then later use it to send a reply using regular JMS or Camel. + +[source,java] +---------------------------------------------------------------------------------------- + // we need to pass in the JMS component, and in this sample we use ActiveMQ + JmsEndpoint endpoint = JmsEndpoint.newInstance(replyDestination, activeMQComponent); + // now we have the endpoint we can use regular Camel API to send a message to it + template.sendBody(endpoint, "Here is the late reply."); +---------------------------------------------------------------------------------------- + +A different solution to sending a reply is to provide the +`replyDestination` object in the same Exchange property when sending. +Camel will then pick up this property and use it for the real +destination. The endpoint URI must include a dummy destination, however. +For example: + +[source,java] +---------------------------------------------------------------------------------------------------------------------------------------- + // we pretend to send it to some non existing dummy queue + template.send("activemq:queue:dummy, new Processor() { + public void process(Exchange exchange) throws Exception { + // and here we override the destination with the ReplyTo destination object so the message is sent to there instead of dummy + exchange.getIn().setHeader(JmsConstants.JMS_DESTINATION, replyDestination); + exchange.getIn().setBody("Here is the late reply."); + } + } +---------------------------------------------------------------------------------------------------------------------------------------- + +[[JMS-Usingarequesttimeout]] +Using a request timeout +^^^^^^^^^^^^^^^^^^^^^^^ + +In the sample below we send a link:request-reply.html[Request Reply] +style message link:exchange.html[Exchange] (we use the `requestBody` +method = `InOut`) to the slow queue for further processing in Camel and +we wait for a return reply: + +[[JMS-Samples]] +Samples +^^^^^^^ + +JMS is used in many examples for other components as well. But we +provide a few samples below to get started. + +[[JMS-ReceivingfromJMS]] +Receiving from JMS +++++++++++++++++++ + +In the following sample we configure a route that receives JMS messages +and routes the message to a POJO: + +[source,java] +-------------------------------- + from("jms:queue:foo"). + to("bean:myBusinessLogic"); +-------------------------------- + +You can of course use any of the EIP patterns so the route can be +context based. For example, here's how to filter an order topic for the +big spenders: + +[source,java] +---------------------------------------------- +from("jms:topic:OrdersTopic"). + filter().method("myBean", "isGoldCustomer"). + to("jms:queue:BigSpendersQueue"); +---------------------------------------------- + +[[JMS-SendingtoaJMS]] +Sending to a JMS +++++++++++++++++ + +In the sample below we poll a file folder and send the file content to a +JMS topic. As we want the content of the file as a `TextMessage` instead +of a `BytesMessage`, we need to convert the body to a `String`: + +[source,java] +------------------------------ +from("file://orders"). + convertBodyTo(String.class). + to("jms:topic:OrdersTopic"); +------------------------------ + +[[JMS-UsingAnnotations]] +Using link:bean-integration.html[Annotations] ++++++++++++++++++++++++++++++++++++++++++++++ + +Camel also has annotations so you can use link:pojo-consuming.html[POJO +Consuming] and link:pojo-producing.html[POJO Producing]. + +[[JMS-SpringDSLsample]] +Spring DSL sample ++++++++++++++++++ + +The preceding examples use the Java DSL. Camel also supports Spring XML +DSL. Here is the big spender sample using Spring DSL: + +[source,xml] +--------------------------------------------------- +<route> + <from uri="jms:topic:OrdersTopic"/> + <filter> + <method bean="myBean" method="isGoldCustomer"/> + <to uri="jms:queue:BigSpendersQueue"/> + </filter> +</route> +--------------------------------------------------- + +[[JMS-Othersamples]] +Other samples ++++++++++++++ + +JMS appears in many of the examples for other components and EIP +patterns, as well in this Camel documentation. So feel free to browse +the documentation. If you have time, check out the this tutorial that +uses JMS but focuses on how well Spring Remoting and Camel works +together link:tutorial-jmsremoting.html[Tutorial-JmsRemoting]. + +[[JMS-UsingJMSasaDeadLetterQueuestoringExchange]] +Using JMS as a Dead Letter Queue storing Exchange ++++++++++++++++++++++++++++++++++++++++++++++++++ + +Normally, when using link:jms.html[JMS] as the transport, it only +transfers the body and headers as the payload. If you want to use +link:jms.html[JMS] with a link:dead-letter-channel.html[Dead Letter +Channel], using a JMS queue as the Dead Letter Queue, then normally the +caused Exception is not stored in the JMS message. You can, however, use +the *transferExchange* option on the JMS dead letter queue to instruct +Camel to store the entire link:exchange.html[Exchange] in the queue as a +`javax.jms.ObjectMessage` that holds a +`org.apache.camel.impl.DefaultExchangeHolder`. This allows you to +consume from the Dead Letter Queue and retrieve the caused exception +from the Exchange property with the key `Exchange.EXCEPTION_CAUGHT`. The +demo below illustrates this: + +[source,java] +------------------------------------------------------------------------ +// setup error handler to use JMS as queue and store the entire Exchange +errorHandler(deadLetterChannel("jms:queue:dead?transferExchange=true")); +------------------------------------------------------------------------ + +Then you can consume from the JMS queue and analyze the problem: + +[source,java] +----------------------------------------------------------------------------------- +from("jms:queue:dead").to("bean:myErrorAnalyzer"); + +// and in our bean +String body = exchange.getIn().getBody(); +Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); +// the cause message is +String problem = cause.getMessage(); +----------------------------------------------------------------------------------- + +[[JMS-UsingJMSasaDeadLetterChannelstoringerroronly]] +Using JMS as a Dead Letter Channel storing error only ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +You can use JMS to store the cause error message or to store a custom +body, which you can initialize yourself. The following example uses the +link:message-translator.html[Message Translator] EIP to do a +transformation on the failed exchange before it is moved to the +link:jms.html[JMS] dead letter queue: + +[source,java] +-------------------------------------------------------------------------------------------------- +// we sent it to a seda dead queue first +errorHandler(deadLetterChannel("seda:dead")); + +// and on the seda dead queue we can do the custom transformation before its sent to the JMS queue +from("seda:dead").transform(exceptionMessage()).to("jms:queue:dead"); +-------------------------------------------------------------------------------------------------- + +Here we only store the original cause error message in the transform. +You can, however, use any link:expression.html[Expression] to send +whatever you like. For example, you can invoke a method on a Bean or use +a custom processor. + +[[JMS-SendinganInOnlymessageandkeepingtheJMSReplyToheader]] +Sending an InOnly message and keeping the JMSReplyTo header +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When sending to a link:jms.html[JMS] destination using *camel-jms* the +producer will use the MEP to detect if its InOnly or InOut messaging. +However there can be times where you want to send an InOnly message but +keeping the JMSReplyTo header. To do so you have to instruct Camel to +keep it, otherwise the JMSReplyTo header will be dropped. + +For example to send an InOnly message to the foo queue, but with a +JMSReplyTo with bar queue you can do as follows: + +[source,java] +------------------------------------------------------------------------------------- + template.send("activemq:queue:foo?preserveMessageQos=true", new Processor() { + public void process(Exchange exchange) throws Exception { + exchange.getIn().setBody("World"); + exchange.getIn().setHeader("JMSReplyTo", "bar"); + } + }); +------------------------------------------------------------------------------------- + +Notice we use `preserveMessageQos=true` to instruct Camel to keep the +JMSReplyTo header. + +[[JMS-SettingJMSprovideroptionsonthedestination]] +Setting JMS provider options on the destination +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some JMS providers, like IBM's WebSphere MQ need options to be set on +the JMS destination. For example, you may need to specify the +targetClient option. Since targetClient is a WebSphere MQ option and not +a Camel URI option, you need to set that on the JMS destination name +like so: + +[source,java] +----------------------------------------------------------------------------------- +... +.setHeader("CamelJmsDestinationName", constant("queue:///MY_QUEUE?targetClient=1")) +.to("wmq:queue:MY_QUEUE?useMessageIDAsCorrelationID=true"); +----------------------------------------------------------------------------------- + +Some versions of WMQ won't accept this option on the destination name +and you will get an exception like: + +________________________________________________________________________________________________________________________________________________ +com.ibm.msg.client.jms.DetailedJMSException: JMSCC0005: The specified +value 'MY_QUEUE?targetClient=1' is not allowed for +'XMSC_DESTINATION_NAME' +________________________________________________________________________________________________________________________________________________ + +A workaround is to use a custom DestinationResolver: + +[source,java] +---------------------------------------------------------------------------------------------------------------------------------- +JmsComponent wmq = new JmsComponent(connectionFactory); + +wmq.setDestinationResolver(new DestinationResolver(){ + public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException { + MQQueueSession wmqSession = (MQQueueSession) session; + return wmqSession.createQueue("queue:///" + destinationName + "?targetClient=1"); + } +}); +---------------------------------------------------------------------------------------------------------------------------------- + +[[JMS-SeeAlso]] +See Also +^^^^^^^^ + +* link:configuring-camel.html[Configuring Camel] +* link:component.html[Component] +* link:endpoint.html[Endpoint] +* link:getting-started.html[Getting Started] + +* link:transactional-client.html[Transactional Client] +* link:bean-integration.html[Bean Integration] +* link:tutorial-jmsremoting.html[Tutorial-JmsRemoting] +* http://activemq.apache.org/jmstemplate-gotchas.html[JMSTemplate +gotchas] http://git-wip-us.apache.org/repos/asf/camel/blob/583a4a09/docs/user-manual/en/SUMMARY.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md index 0cedb30..0e64b28 100644 --- a/docs/user-manual/en/SUMMARY.md +++ b/docs/user-manual/en/SUMMARY.md @@ -2,3 +2,5 @@ * [Introduction](README.md) * [Legal Notice](notice.md) +* Componnet Reference + * [JMS](components/camel-jms/src/main/docs/readme.adoc)
