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

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


The following commit(s) were added to refs/heads/main by this push:
     new 1110e5e  CAMEL-16861: Cleanup and update EIP docs
1110e5e is described below

commit 1110e5e930ac234c14cc4302cf61f2053a59b101
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Mon Oct 25 17:12:31 2021 +0200

    CAMEL-16861: Cleanup and update EIP docs
---
 .../modules/eips/pages/transactional-client.adoc   | 177 ++++++++++++++++-----
 1 file changed, 136 insertions(+), 41 deletions(-)

diff --git 
a/core/camel-core-engine/src/main/docs/modules/eips/pages/transactional-client.adoc
 
b/core/camel-core-engine/src/main/docs/modules/eips/pages/transactional-client.adoc
index 7026c9e..5a9e2a2 100644
--- 
a/core/camel-core-engine/src/main/docs/modules/eips/pages/transactional-client.adoc
+++ 
b/core/camel-core-engine/src/main/docs/modules/eips/pages/transactional-client.adoc
@@ -69,7 +69,7 @@ TODO:
 
 === About Spring Transactions
 
-Camel uses Spring Transaction to manage transactions via its 
`TransactionManager`
+Camel uses Spring Transaction (`camel-spring`) to manage transactions via its 
`TransactionManager`
 API. Depending on the kinds of resources that are taking part in the 
transaction,
 an appropriate implementation of the transaction manager must be chosen. Spring
 offers a number of transaction managers out of the box that work for various 
local
@@ -81,70 +81,124 @@ API abstract that Camel uses.
 === About JTA Transactions
 
 TODO:
+TODO: (`camel-jta`)
 
 == Using Transactions in Camel
 
-TODO:
+In Camel, transactions are used by:
+
+. Setting up transaction manager via either Spring Transactions or JTA 
Transactions.
+. Marking routes as transacted
+. Using different transaction propagations for rare use-cases
+
+You will later in the two transactional examples further below, see how to set 
up transaction manager in Camel.
+
+=== Marking a route as transacted
+
+When using transactions (JTA or Spring Transaction) in Camel then you enable 
this on routes by using `transacted`
+right after `from` in the routes.
+
+For example in Java that would be:
+
+[source,java]
+----
+from("jms:cheese")
+    .transacted()
+    .to("bean:foo");
+----
+
+And in XML:
+
+[source,xml]
+----
+<route>
+    <from uri="jms:cheese"/>
+    <transacted/>
+    <to uri="bean:foo"/>
+</route>
+----
+
+When you specify `<transacted/>` in a route, Camel uses transactions for that 
particular
+route and any other routes that the message may undertake.
+
+When a route is specified as `<transacted/>`, then under the hood Camel looks 
up
+the Spring/JTA transaction manager and uses it. This is convention over 
configuration.
 
-=== Transaction error handler
+The convention over configuration applies only when you have a single 
Spring/JTA transaction
+manager configured. In more complex scenarios, where you either use multiple
+transaction managers or transaction propagation policies, you have to do 
additional
+configuration.
 
-When a route is marked as transacted using ``<transacted/>` Camel will
-automatically use `TransactionErrorHandler` as the
-xref:latest@manual:ROOT:error-handler.adoc[Error Handler].
+=== Using different transaction propagations
 
-This error handler supports basically the same
-feature set as the 
xref:latest@manual:ROOT:defaulterrorhandler.adoc[DefaultErrorHandler].
+In some rare situations, you may need to use multiple transactions with the 
same exchange.
 
-=== Transaction Policies
+For example an exchange starts off using `PROPAGATION_REQUIRED`, and then you 
need
+to use another transaction that’s independent of the existing transaction. You 
can
+do this by using PROPAGATION_REQUIRES_NEW, which will start a new transaction.
 
-Outbound endpoints will automatically enlist in the current transaction
-context. But what if you do not want your outbound endpoint to enlist in
-the same transaction as your inbound endpoint? The solution is to add a
-Transaction Policy to the processing route. You first have to define
-transaction policies that you will be using. The policies use a spring
-TransactionTemplate under the covers for declaring the transaction
-demarcation to use. So you will need to add something like the following
-to your spring xml:
+NOTE: In Camel a route can only have exactly one transaction policy, which 
means, that if
+you need to change transaction propagation, then you must use a new route.
+
+When the exchange completes, the transaction manager will issue commits
+or rollbacks to these two transactions, which ensures that they both complete 
at
+the same time. Because two transaction legs are in play, they can have 
different
+outcomes; for example, transaction 1 can roll back, while transaction 2 
commits,
+and vice versa.
+
+In Camel, you need to configure the propagations using 
`SpringTransactionPolicy`
+as shown in the following XML snippets:
 
 [source,xml]
 ----
-<bean id="PROPAGATION_REQUIRED" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
+<bean id="txRequired" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
     <property name="transactionManager" ref="jmsTransactionManager"/>
 </bean>
 
-<bean id="PROPAGATION_REQUIRES_NEW" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
+<bean id="txRequiresNew" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
     <property name="transactionManager" ref="jmsTransactionManager"/>
     <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
 </bean>
+
+<bean id="txMandatory" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
+    <property name="transactionManager" ref="jmsTransactionManager"/>
+    <property name="propagationBehaviorName" 
value="PROPAGATION_REQUIRES_MANDATORY"/>
+</bean>
 ----
 
-Then in your
-https://www.javadoc.io/doc/org.apache.camel/camel-spring/current/org/apache/camel/spring/SpringRouteBuilder.html[SpringRouteBuilder],
-you just need to create new SpringTransactionPolicy objects for each of
-the templates.
+Then we have routes, where each of the route use their different policy:
 
-[source,java]
-----
-public void configure() {
-    ...
-    Policy required = bean(SpringTransactionPolicy.class, 
"PROPAGATION_REQUIRED"));
-    Policy requirenew = bean(SpringTransactionPolicy.class, 
"PROPAGATION_REQUIRES_NEW"));
-    ...
-}
+[source,xml]
 ----
+<camelContext xmlns="http://camel.apache.org/schema/spring";>
+    <route>
+        <from uri="activemq:queue:inbox"/>
+        <transacted ref="txRequired"/>
+        <to uri="direct:audit"/>
+        <to uri="direct:order"/>
+        <to uri="activemq:queue:order"/>
+    </route>
 
-Once created, you can use the Policy objects in your processing routes:
+    <route>
+        <from uri="direct:audit"/>
+        <transacted ref="txRequiresNew"/>
+        <bean ref="auditLogService" method="insertAuditLog"/>
+    </route>
 
-[source,java]
+    <route>
+        <from uri="direct:order"/>
+        <transacted ref="txMandatory"/>
+        <bean ref="orderService" method="insertOrder"/>
+    </route>
+</camelContext>
 ----
-// Send to bar in a new transaction
-from("activemq:queue:foo").policy(requirenew)
-    .to("activemq:queue:bar");
 
-// Send to bar without a transaction.
-from("activemq:queue:foo").policy(notsupported)
-    .to("activemq:queue:bar");
-----
+Notice how the ref attribute on `<transacted>` refers to the corresponding 
bean id of the transaction policy.
+
+TIP: **Keep it simple:** Although you can use multiple propagation behaviors 
with multiple routes in Camel, do
+so with care. Try to design your solutions with as few propagations as 
possible, because
+complexity increases dramatically when you introduce new propagation behaviors
+
 
 == Transaction example with database
 
@@ -241,7 +295,7 @@ 
https://github.com/apache/camel/tree/main/components/camel-jms/src/test/java/org
 the destination is a mock endpoint.
 
 First we configure the standard Spring XML to declare a JMS connection
-factory, a JMS transaction manager and our ActiveMQ component that we
+factory, a JMS transaction manager and our 
xref:ROOT:activemq-component.adoc[ActiveMQ] component that we
 use in our routing.
 
 [source,xml]
@@ -292,3 +346,44 @@ route as transacted using the `<transacted/>` XML tag.
 </camelContext>
 ----
 
+== Local vs Global Transactions
+
+When talking about transactions, you need to distinguish between single- and
+multiple-resource transactions. The former are also known as local 
transactions,
+and the latter as global transactions
+
+=== Local Transactions
+
+If you only have a single resource (such as one database, or one messaging 
system) then
+transactions can be simpler to orchestrate by the transaction manager. This is 
known as local transactions.
+
+The previous two examples above are both using a single resource, and are 
therefore using local transactions.
+When using local transactions and Spring Transactions, then you can use the 
dedicated transaction manager for the resource type:
+
+- org.springframework.jdbc.datasource.DataSourceTransactionManager
+- org.springframework.jms.connection.JmsTransactionManager
+
+TIP: Consult the spring documentation for more local transaction managers.
+
+=== Global Transactions
+
+The situation changes when you need to span multiple resources in the
+same transaction, such as JMS and JDBC resources together.
+
+To support multiple resources you need to use a JTA (XA) capable transaction 
manager,
+which means using `org.springframework.transaction.jta.JtaTransactionManager` 
with Spring Transactions.
+
+NOTE: For more information on JTA, see the Wikipedia page on the subject:
+http://en.wikipedia.org/wiki/Java_Transaction_API. XA is also briefly discussed
+here: http://en.wikipedia.org/wiki/X/Open_XA.
+
+That is not all, you also need to use a JTA transaction implementation such as:
+
+- Atomikos - https://www.atomikos.com/
+- Narayana - https://narayana.io/
+- JEE Application Server with JTA
+
+And all of this must be configured correctly to have JTA transaction working.
+You may also need to do special configuration from the vendors of the 
resources (i.e. database or messaging system)
+to have this work properly with JTA/XA transactions. Consult the documentation 
of those systems for more details.
+

Reply via email to