This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feature/CAMEL-23789-wave1-multi-dsl-docs in repository https://gitbox.apache.org/repos/asf/camel.git
commit 43f70072210f4ebea38def6846f21aaefaf7b81a Author: Claus Ibsen <[email protected]> AuthorDate: Wed Jun 17 19:02:26 2026 +0200 CAMEL-23789: Make JMS component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../camel-jms/src/main/docs/jms-component.adoc | 272 ++++++++++++++++++--- 1 file changed, 237 insertions(+), 35 deletions(-) diff --git a/components/camel-jms/src/main/docs/jms-component.adoc b/components/camel-jms/src/main/docs/jms-component.adoc index 1dc15de302b4..9fb1cc18c6fa 100644 --- a/components/camel-jms/src/main/docs/jms-component.adoc +++ b/components/camel-jms/src/main/docs/jms-component.adoc @@ -367,6 +367,7 @@ 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: +._Java-only: `errorHandler` configuration is Java DSL specific_ [source,java] ------------------------------------------------------------------------ // setup error handler to use JMS as queue and store the entire Exchange @@ -375,11 +376,43 @@ errorHandler(deadLetterChannel("jms:queue:dead?transferExchange=true")); Then you can consume from the JMS queue and analyze the problem: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------ +---- from("jms:queue:dead").to("bean:myErrorAnalyzer"); +---- + +XML:: ++ +[source,xml] +---- +<route> + <from uri="jms:queue:dead"/> + <to uri="bean:myErrorAnalyzer"/> +</route> +---- -// and in our bean +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:queue:dead + steps: + - to: + uri: bean:myErrorAnalyzer +---- +==== + +And in the `myErrorAnalyzer` bean: + +._Java-only: programmatic access to exchange properties and exception_ +[source,java] +----------------------------------------------------------------------------------- String body = exchange.getIn().getBody(); Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); // the cause message is @@ -394,6 +427,7 @@ Message Translator EIP to do a transformation on the failed exchange before it is moved to the xref:jms-component.adoc[JMS] dead letter queue: +._Java-only: `errorHandler` and `exceptionMessage()` are Java DSL specific_ [source,java] -------------------------------------------------------------------------------------------------- // we sent it to a seda dead queue first @@ -554,6 +588,7 @@ YAML:: You can also specify the message type to use for each message by setting the header with the key `CamelJmsMessageType`. For example: +._Java-only: uses the `JmsMessageType` enum which requires Java code_ [source,java] --------------------------------------------------------------------------------------------------------- from("file://inbox/order").setHeader("CamelJmsMessageType", JmsMessageType.Text).to("jms:queue:order"); @@ -712,13 +747,46 @@ you can specify the exchange pattern to use, see more at Request Reply. + This is useful if you want to send an `InOnly` message to a JMS topic: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------- +---- from("activemq:queue:in") .to("bean:validateOrder") .to(ExchangePattern.InOnly, "activemq:topic:order") .to("bean:handleOrder"); ------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- +<route> + <from uri="activemq:queue:in"/> + <to uri="bean:validateOrder"/> + <inOnly uri="activemq:topic:order"/> + <to uri="bean:handleOrder"/> +</route> +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: activemq:queue:in + steps: + - to: + uri: bean:validateOrder + - inOnly: + uri: activemq:topic:order + - to: + uri: bean:handleOrder +---- +==== === Reuse endpoint and send to different destinations computed at runtime @@ -784,11 +852,12 @@ 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: +._Java-only: bean method that sets the destination header programmatically_ [source,java] ------------------------------------------------------------------------- public void setJmsHeader(Exchange exchange) { String id = .... - exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id"); + exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id); } ------------------------------------------------------------------------- @@ -853,11 +922,40 @@ multiple threads to make an application more responsive. You can set the `concurrentConsumers` option to specify the number of threads servicing the JMS endpoint, as follows: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------- -from("jms:SomeQueue?concurrentConsumers=20"). - bean(MyClass.class); ---------------------------------------------- +---- +from("jms:SomeQueue?concurrentConsumers=20") + .bean(MyClass.class); +---- + +XML:: ++ +[source,xml] +---- +<route> + <from uri="jms:SomeQueue?concurrentConsumers=20"/> + <to uri="bean:MyClass"/> +</route> +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:SomeQueue + parameters: + concurrentConsumers: 20 + steps: + - to: + uri: bean:MyClass +---- +==== You can configure this option in one of the following ways: @@ -876,11 +974,41 @@ Asynchronous Routing Engine). See more details in the table on top of the page about the `asyncConsumer` option. +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------------------------------- -from("jms:SomeQueue?concurrentConsumers=20&asyncConsumer=true"). - bean(MyClass.class); ----------------------------------------------------------------- +---- +from("jms:SomeQueue?concurrentConsumers=20&asyncConsumer=true") + .bean(MyClass.class); +---- + +XML:: ++ +[source,xml] +---- +<route> + <from uri="jms:SomeQueue?concurrentConsumers=20&asyncConsumer=true"/> + <to uri="bean:MyClass"/> +</route> +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:SomeQueue + parameters: + concurrentConsumers: 20 + asyncConsumer: true + steps: + - to: + uri: bean:MyClass +---- +==== === Request-reply over JMS @@ -960,6 +1088,7 @@ concurrent threads using the `concurrentConsumers` and `maxConcurrentConsumers` options. This allows you to easier configure this in Camel as shown below: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ------------------------------------------------------- from(xxx) @@ -977,6 +1106,7 @@ If you use a fixed reply queue when doing Request Reply over JMS as shown in the example below, then pay attention. +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] --------------------------------------------- from(xxx) @@ -994,6 +1124,7 @@ using the `receiveTimeout` option. By default, its 1000 milliseconds. So to make it faster, you can set it to 250 millis to pull 4 times per second as shown: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ---------------------------------------------------------------- from(xxx) @@ -1021,6 +1152,7 @@ the `ReplyToType` option which you can configure to `Exclusive` + to tell Camel that the reply queue is exclusive as shown in the example below: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ------------------------------------------------------------------- from(xxx) @@ -1032,6 +1164,7 @@ Mind that the queue must be exclusive to each and every endpoint. So if you have two routes, then they each need a unique reply queue as shown in the next example: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ----------------------------------------------------------------------------- from(xxx) @@ -1140,22 +1273,62 @@ 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 -a long type. +`CamelJmsRequestTimeout` with a timeout value as a long type. + +TIP: In Java code, you can use the constant `JmsConstants.JMS_REQUEST_TIMEOUT` for the header name. 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: +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------------------------------------------------------- +---- from("direct:someWhere") .setHeader("CamelJmsRequestTimeout", method(ServiceBean.class, "whatIsTheTimeout")) .to("jms:queue:foo?replyTo=bar&requestTimeout=30s") .to("bean:processReply"); ----------------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- +<route> + <from uri="direct:someWhere"/> + <setHeader name="CamelJmsRequestTimeout"> + <method ref="serviceBean" method="whatIsTheTimeout"/> + </setHeader> + <to uri="jms:queue:foo?replyTo=bar&requestTimeout=30s"/> + <to uri="bean:processReply"/> +</route> +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:someWhere + steps: + - setHeader: + name: CamelJmsRequestTimeout + method: + ref: serviceBean + method: whatIsTheTimeout + - to: + uri: jms:queue:foo + parameters: + replyTo: bar + requestTimeout: 30s + - to: + uri: bean:processReply +---- +==== When you do fire and forget (InOut) over xref:jms-component.adoc[JMS] with Camel, then Camel by default does *not* set any time to live value on the @@ -1217,13 +1390,15 @@ 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: +._Java-only: uses JMS `Destination` object and Camel Java API_ [source,java] ----------------------------------------------------------------------------------------------------------------- -Destination replyDestination = exchange.getIn().getHeader(JmsConstants.JMS_REPLY_DESTINATION, Destination.class); +Destination replyDestination = exchange.getIn().getHeader("JMSReplyTo", Destination.class); ----------------------------------------------------------------------------------------------------------------- And then later use it to send a reply using regular JMS or Camel. +._Java-only: uses `JmsEndpoint` and `ProducerTemplate` Java API_ [source,java] ---------------------------------------------------------------------------------------- // we need to pass in the JMS component, and in this sample we use ActiveMQ @@ -1238,16 +1413,15 @@ 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: +._Java-only: uses `ProducerTemplate` and `Processor` to set the JMS destination object programmatically_ [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 { +template.send("activemq:queue:dummy", exchange -> { // 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().setHeader("CamelJmsDestination", replyDestination); exchange.getIn().setBody("Here is the late reply."); - } -} +}); ---------------------------------------------------------------------------------------------------------------------------------------- === Using a request timeout @@ -1269,13 +1443,12 @@ 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: +._Java-only: uses `ProducerTemplate` test API to send with custom JMS headers_ [source,java] ------------------------------------------------------------------------------------- -template.send("activemq:queue:foo?preserveMessageQos=true", new Processor() { - public void process(Exchange exchange) throws Exception { +template.send("activemq:queue:foo?preserveMessageQos=true", exchange -> { exchange.getIn().setBody("World"); exchange.getIn().setHeader("JMSReplyTo", "bar"); - } }); ------------------------------------------------------------------------------------- @@ -1290,12 +1463,42 @@ the JMS destination. For example, you may need to specify the a Camel URI option, you need to set that on the JMS destination name like so: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------ +---- // ... .setHeader("CamelJmsDestinationName", constant("queue:///MY_QUEUE?targetClient=1")) .to("wmq:queue:MY_QUEUE?useMessageIDAsCorrelationID=true"); ------------------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- +<!-- ... --> +<setHeader name="CamelJmsDestinationName"> + <constant>queue:///MY_QUEUE?targetClient=1</constant> +</setHeader> +<to uri="wmq:queue:MY_QUEUE?useMessageIDAsCorrelationID=true"/> +---- + +YAML:: ++ +[source,yaml] +---- +# ... +- setHeader: + name: CamelJmsDestinationName + constant: "queue:///MY_QUEUE?targetClient=1" +- to: + uri: wmq:queue:MY_QUEUE + parameters: + useMessageIDAsCorrelationID: true +---- +==== Some versions of WMQ won't accept this option on the destination name, and you will get an exception like: @@ -1308,15 +1511,14 @@ value 'MY_QUEUE?targetClient=1' is not allowed for A workaround is to use a custom DestinationResolver: +._Java-only: programmatic JMS component configuration with 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"); - } +wmq.setDestinationResolver((session, destinationName, pubSubDomain) -> { + MQQueueSession wmqSession = (MQQueueSession) session; + return wmqSession.createQueue("queue:///" + destinationName + "?targetClient=1"); }); ----------------------------------------------------------------------------------------------------------------------------------
