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 14a6528419ea CAMEL-23094: camel-core - Saga EIP fix model for
completion and compensation (#21628)
14a6528419ea is described below
commit 14a6528419eacb4b531151713cd51ce5d69b9216
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Feb 27 14:17:54 2026 +0100
CAMEL-23094: camel-core - Saga EIP fix model for completion and
compensation (#21628)
---
.../org/apache/camel/catalog/models/saga.json | 4 +-
.../apache/camel/catalog/schemas/camel-spring.xsd | 83 +++----
.../apache/camel/catalog/schemas/camel-xml-io.xsd | 83 +++----
.../org/apache/camel/spring/processor/saga.xml | 4 +-
.../org/apache/camel/spring/processor/sagaRef.xml | 4 +-
.../src/main/docs/modules/eips/pages/saga-eip.adoc | 260 +++++++++------------
.../META-INF/org/apache/camel/model/saga.json | 4 +-
.../camel/model/SagaActionUriDefinition.java | 51 ----
.../org/apache/camel/model/SagaDefinition.java | 67 ++++--
.../java/org/apache/camel/reifier/SagaReifier.java | 46 +++-
.../test/resources/org/apache/camel/model/saga.xml | 18 +-
.../java/org/apache/camel/xml/in/ModelParser.java | 7 +-
.../java/org/apache/camel/xml/out/ModelWriter.java | 9 +-
core/camel-xml-io/src/test/resources/saga.xml | 4 +-
.../org/apache/camel/yaml/out/ModelWriter.java | 9 +-
.../ROOT/pages/camel-4x-upgrade-guide-4_18.adoc | 110 +++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_19.adoc | 110 +++++++++
.../apache/camel/main/stub/StubBeanRepository.java | 6 +
.../camel-yaml-dsl-deserializers/pom.xml | 4 -
.../dsl/yaml/deserializers/ModelDeserializers.java | 81 +------
.../deserializers/ModelDeserializersResolver.java | 1 -
.../generated/resources/schema/camelYamlDsl.json | 37 +--
.../org/apache/camel/dsl/yaml/SagaTest.groovy | 41 +---
23 files changed, 535 insertions(+), 508 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/saga.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/saga.json
index 1334df81a513..15543e203db7 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/saga.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/saga.json
@@ -20,8 +20,8 @@
"propagation": { "index": 5, "kind": "attribute", "displayName":
"Propagation", "group": "advanced", "label": "advanced", "required": false,
"type": "enum", "javaType": "org.apache.camel.model.SagaPropagation", "enum": [
"REQUIRED", "REQUIRES_NEW", "MANDATORY", "SUPPORTS", "NOT_SUPPORTED", "NEVER"
], "deprecated": false, "autowired": false, "secret": false, "defaultValue":
"REQUIRED", "description": "Set the Saga propagation mode (REQUIRED,
REQUIRES_NEW, MANDATORY, SUPPORTS, NOT_SUPP [...]
"completionMode": { "index": 6, "kind": "attribute", "displayName":
"Completion Mode", "group": "advanced", "label": "advanced", "required": false,
"type": "enum", "javaType": "org.apache.camel.model.SagaCompletionMode",
"enum": [ "AUTO", "MANUAL" ], "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "AUTO", "description": "Determine how the saga
should be considered complete. When set to AUTO, the saga is completed when the
exchange that initiates the saga is [...]
"timeout": { "index": 7, "kind": "attribute", "displayName": "Timeout",
"group": "common", "required": false, "type": "duration", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Set the maximum amount of time for the Saga. After the timeout
is expired, the saga will be compensated automatically (unless a different
decision has been taken in the meantime)." },
- "compensation": { "index": 8, "kind": "element", "displayName":
"Compensation", "group": "common", "required": false, "type": "object",
"javaType": "org.apache.camel.model.SagaActionUriDefinition", "deprecated":
false, "autowired": false, "secret": false, "description": "The compensation
endpoint URI that must be called to compensate all changes done in the route.
The route corresponding to the compensation URI must perform compensation and
complete without error. If errors occur dur [...]
- "completion": { "index": 9, "kind": "element", "displayName":
"Completion", "group": "common", "required": false, "type": "object",
"javaType": "org.apache.camel.model.SagaActionUriDefinition", "deprecated":
false, "autowired": false, "secret": false, "description": "The completion
endpoint URI that will be called when the Saga is completed successfully. The
route corresponding to the completion URI must perform completion tasks and
terminate without error. If errors occur during com [...]
+ "compensation": { "index": 8, "kind": "attribute", "displayName":
"Compensation", "group": "common", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "The compensation endpoint URI that must be
called to compensate all changes done in the route. The route corresponding to
the compensation URI must perform compensation and complete without error. If
errors occur during compensation, the saga s [...]
+ "completion": { "index": 9, "kind": "attribute", "displayName":
"Completion", "group": "common", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "The completion endpoint URI that will be
called when the Saga is completed successfully. The route corresponding to the
completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga service ma [...]
"option": { "index": 10, "kind": "element", "displayName": "Option",
"group": "advanced", "label": "advanced", "required": false, "type": "array",
"javaType":
"java.util.List<org.apache.camel.model.PropertyExpressionDefinition>",
"deprecated": false, "autowired": false, "secret": false, "description":
"Allows to save properties of the current exchange in order to re-use them in a
compensation\/completion callback route. Options are usually helpful e.g. to
store and retrieve identifie [...]
"outputs": { "index": 11, "kind": "element", "displayName": "Outputs",
"group": "common", "required": true, "type": "array", "javaType":
"java.util.List", "oneOf": [ "aggregate", "bean", "choice", "circuitBreaker",
"claimCheck", "convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay",
"doCatch", "doFinally", "doTry", "dynamicRouter", "enrich", "filter",
"idempotentConsumer", "intercept", "interceptFrom", "interceptSendToEndpoint",
"kamelet", "loadBalance", "log", "loop", "ma [...]
}
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 296d19fddb5b..fc03a837c852 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -13378,29 +13378,6 @@ However if there are a high degree of dynamic
endpoints that have been used befo
to reuse both producers and endpoints and therefore the cache size can be set
accordingly or rely on the default size
(1000). If there is a mix of unique and used before dynamic endpoints, then
setting a reasonable cache size can help
reduce memory usage to avoid storing too many non frequent used producers.
-]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="sagaActionUriDefinition">
- <xs:complexContent>
- <xs:extension base="tns:sendDefinition">
- <xs:sequence/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType abstract="true" name="sendDefinition">
- <xs:complexContent>
- <xs:extension base="tns:noOutputDefinition">
- <xs:sequence/>
- <xs:attribute name="uri" type="xs:string">
- <xs:annotation>
- <xs:documentation xml:lang="en">
-<![CDATA[
-Sets the uri of the endpoint to send to.
]]>
</xs:documentation>
</xs:annotation>
@@ -13412,28 +13389,6 @@ Sets the uri of the endpoint to send to.
<xs:complexContent>
<xs:extension base="tns:output">
<xs:sequence>
- <xs:element minOccurs="0" name="compensation"
type="tns:sagaActionUriDefinition">
- <xs:annotation>
- <xs:documentation xml:lang="en">
-<![CDATA[
-The compensation endpoint URI that must be called to compensate all changes
done in the route. The route corresponding
-to the compensation URI must perform compensation and complete without error.
If errors occur during compensation, the
-saga service may call again the compensation URI to retry.
-]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element minOccurs="0" name="completion"
type="tns:sagaActionUriDefinition">
- <xs:annotation>
- <xs:documentation xml:lang="en">
-<![CDATA[
-The completion endpoint URI that will be called when the Saga is completed
successfully. The route corresponding to the
-completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga
-service may call again the completion URI to retry.
-]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
<xs:element maxOccurs="unbounded" minOccurs="0" name="option"
type="tns:propertyExpressionDefinition">
<xs:annotation>
<xs:documentation xml:lang="en">
@@ -13555,6 +13510,28 @@ user must complete or compensate the saga using the
saga:complete or saga:compen
<![CDATA[
Set the maximum amount of time for the Saga. After the timeout is expired, the
saga will be compensated automatically
(unless a different decision has been taken in the meantime).
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="compensation" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+The compensation endpoint URI that must be called to compensate all changes
done in the route. The route corresponding
+to the compensation URI must perform compensation and complete without error.
If errors occur during compensation, the
+saga service may call again the compensation URI to retry.
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="completion" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+The completion endpoint URI that will be called when the Saga is completed
successfully. The route corresponding to the
+completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga
+service may call again the completion URI to retry.
]]>
</xs:documentation>
</xs:annotation>
@@ -13622,6 +13599,22 @@ Sets the sample message count which only a single
Exchange will pass through aft
</xs:extension>
</xs:complexContent>
</xs:complexType>
+ <xs:complexType abstract="true" name="sendDefinition">
+ <xs:complexContent>
+ <xs:extension base="tns:noOutputDefinition">
+ <xs:sequence/>
+ <xs:attribute name="uri" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+Sets the uri of the endpoint to send to.
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
<xs:complexType name="setBodyDefinition">
<xs:complexContent>
<xs:extension base="tns:processorDefinition">
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
index aae3eba9da82..a794e359f73b 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
@@ -12072,29 +12072,6 @@ However if there are a high degree of dynamic
endpoints that have been used befo
to reuse both producers and endpoints and therefore the cache size can be set
accordingly or rely on the default size
(1000). If there is a mix of unique and used before dynamic endpoints, then
setting a reasonable cache size can help
reduce memory usage to avoid storing too many non frequent used producers.
-]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="sagaActionUriDefinition">
- <xs:complexContent>
- <xs:extension base="tns:sendDefinition">
- <xs:sequence/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType abstract="true" name="sendDefinition">
- <xs:complexContent>
- <xs:extension base="tns:noOutputDefinition">
- <xs:sequence/>
- <xs:attribute name="uri" type="xs:string">
- <xs:annotation>
- <xs:documentation xml:lang="en">
-<![CDATA[
-Sets the uri of the endpoint to send to.
]]>
</xs:documentation>
</xs:annotation>
@@ -12106,28 +12083,6 @@ Sets the uri of the endpoint to send to.
<xs:complexContent>
<xs:extension base="tns:output">
<xs:sequence>
- <xs:element minOccurs="0" name="compensation"
type="tns:sagaActionUriDefinition">
- <xs:annotation>
- <xs:documentation xml:lang="en">
-<![CDATA[
-The compensation endpoint URI that must be called to compensate all changes
done in the route. The route corresponding
-to the compensation URI must perform compensation and complete without error.
If errors occur during compensation, the
-saga service may call again the compensation URI to retry.
-]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element minOccurs="0" name="completion"
type="tns:sagaActionUriDefinition">
- <xs:annotation>
- <xs:documentation xml:lang="en">
-<![CDATA[
-The completion endpoint URI that will be called when the Saga is completed
successfully. The route corresponding to the
-completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga
-service may call again the completion URI to retry.
-]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
<xs:element maxOccurs="unbounded" minOccurs="0" name="option"
type="tns:propertyExpressionDefinition">
<xs:annotation>
<xs:documentation xml:lang="en">
@@ -12249,6 +12204,28 @@ user must complete or compensate the saga using the
saga:complete or saga:compen
<![CDATA[
Set the maximum amount of time for the Saga. After the timeout is expired, the
saga will be compensated automatically
(unless a different decision has been taken in the meantime).
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="compensation" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+The compensation endpoint URI that must be called to compensate all changes
done in the route. The route corresponding
+to the compensation URI must perform compensation and complete without error.
If errors occur during compensation, the
+saga service may call again the compensation URI to retry.
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="completion" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+The completion endpoint URI that will be called when the Saga is completed
successfully. The route corresponding to the
+completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga
+service may call again the completion URI to retry.
]]>
</xs:documentation>
</xs:annotation>
@@ -12316,6 +12293,22 @@ Sets the sample message count which only a single
Exchange will pass through aft
</xs:extension>
</xs:complexContent>
</xs:complexType>
+ <xs:complexType abstract="true" name="sendDefinition">
+ <xs:complexContent>
+ <xs:extension base="tns:noOutputDefinition">
+ <xs:sequence/>
+ <xs:attribute name="uri" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+Sets the uri of the endpoint to send to.
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
<xs:complexType name="setBodyDefinition">
<xs:complexContent>
<xs:extension base="tns:processorDefinition">
diff --git
a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/saga.xml
b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/saga.xml
index 25127c0c44f5..0e8c7724e310 100644
---
a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/saga.xml
+++
b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/saga.xml
@@ -31,9 +31,7 @@
<jmxAgent id="jmx" disabled="true"/>
<route>
<from uri="direct:start"/>
- <saga>
- <compensation uri="mock:compensation" />
- <completion uri="mock:completion" />
+ <saga compensation="mock:compensation" completion="mock:completion">
<option key="myOptionKey">
<constant>myOptionValue</constant>
</option>
diff --git
a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/sagaRef.xml
b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/sagaRef.xml
index c9f08253f123..2e12eddd504c 100644
---
a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/sagaRef.xml
+++
b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/sagaRef.xml
@@ -32,9 +32,7 @@
<jmxAgent id="jmx" disabled="true"/>
<route>
<from uri="direct:start"/>
- <saga sagaService="mySagaService">
- <compensation uri="mock:compensation"/>
- <completion uri="mock:completion"/>
+ <saga sagaService="mySagaService" compensation="mock:compensation"
completion="mock:completion">
<option key="myOptionKey">
<constant>myOptionValue</constant>
</option>
diff --git
a/core/camel-core-engine/src/main/docs/modules/eips/pages/saga-eip.adoc
b/core/camel-core-engine/src/main/docs/modules/eips/pages/saga-eip.adoc
index 0e67b73e965e..27eb8668d216 100644
--- a/core/camel-core-engine/src/main/docs/modules/eips/pages/saga-eip.adoc
+++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/saga-eip.adoc
@@ -256,8 +256,7 @@ XML::
----
<route>
<from uri="direct:newOrder"/>
- <saga propagation="MANDATORY">
- <compensation uri="direct:cancelOrder"/>
+ <saga propagation="MANDATORY" compensation="direct:cancelOrder">
<transform>
<header>Long-Running-Action</header>
</transform>
@@ -277,8 +276,7 @@ YAML::
steps:
- saga:
propagation: MANDATORY
- compensation:
- uri: direct:cancelOrder
+ compensation: direct:cancelOrder
steps:
- transform:
expression:
@@ -387,11 +385,11 @@ Java::
// action
from("direct:reserveCredit")
.saga()
- .propagation(SagaPropagation.MANDATORY)
- .compensation("direct:refundCredit")
- .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
- .bean("creditService", "reserveCredit")
- .log("Credit ${header.amount} reserved in action ${body}");
+ .propagation(SagaPropagation.MANDATORY)
+ .compensation("direct:refundCredit")
+ .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
+ .bean("creditService", "reserveCredit")
+ .log("Credit ${header.amount} reserved in action ${body}");
// compensation
from("direct:refundCredit")
@@ -406,14 +404,12 @@ XML::
----
<route>
<from uri="direct:reserveCredit"/>
- <saga propagation="MANDATORY">
- <compensation uri="direct:refundCredit"/>
- <transform>
- <header>Long-Running-Action</header>
- </transform>
- <bean ref="creditService" method="reserveCredit"/>
- <log message="Credit ${header.amount} reserved in action ${body}"/>
- </saga>
+ <saga propagation="MANDATORY" compensation="direct:refundCredit"/>
+ <transform>
+ <header>Long-Running-Action</header>
+ </transform>
+ <bean ref="creditService" method="reserveCredit"/>
+ <log message="Credit ${header.amount} reserved in action ${body}"/>
</route>
<route>
@@ -436,18 +432,16 @@ YAML::
steps:
- saga:
propagation: MANDATORY
- compensation:
- uri: direct:refundCredit
- steps:
- - transform:
- expression:
- header:
- expression: Long-Running-Action
- - bean:
- ref: creditService
- method: reserveCredit
- - log:
- message: "Credit ${header.amount} reserved in action ${body}"
+ compensation: direct:refundCredit
+ - transform:
+ expression:
+ header:
+ expression: Long-Running-Action
+ - bean:
+ ref: creditService
+ method: reserveCredit
+ - log:
+ message: "Credit ${header.amount} reserved in action ${body}"
- route:
from:
uri: direct:refundCredit
@@ -493,12 +487,12 @@ The compensation route is the same as in the previous
example above
----
from("direct:newOrder")
.saga()
- .propagation(SagaPropagation.MANDATORY)
- .compensation("direct:cancelOrder")
- .completion("direct:completeOrder") // completion endpoint
- .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
- .bean("orderManagerService", "newOrder")
- .log("Order ${body} created");
+ .propagation(SagaPropagation.MANDATORY)
+ .compensation("direct:cancelOrder")
+ .completion("direct:completeOrder") // completion endpoint
+ .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
+ .bean("orderManagerService", "newOrder")
+ .log("Order ${body} created");
// direct:cancelOrder is the same as in the previous example
@@ -518,15 +512,12 @@ The compensation route is the same as in the previous
example above
----
<route>
<from uri="direct:newOrder"/>
- <saga propagation="MANDATORY">
- <completion uri="direct:completeOrder"/>
- <compensation uri="direct:cancelOrder"/>
- <transform>
- <header>Long-Running-Action</header>
- </transform>
- <bean ref="orderManagerService" method="newOrder"/>
- <log message="Order ${body} created"/>
- </saga>
+ <saga propagation="MANDATORY" completion="direct:completeOrder"
compensation="direct:cancelOrder"/>
+ <transform>
+ <header>Long-Running-Action</header>
+ </transform>
+ <bean ref="orderManagerService" method="newOrder"/>
+ <log message="Order ${body} created"/>
</route>
<route>
@@ -552,20 +543,17 @@ The compensation route is the same as in the previous
example above
steps:
- saga:
propagation: MANDATORY
- compensation:
- uri: direct:cancelOrder
- completion:
- uri: direct:completeOrder
- steps:
- - transform:
- expression:
- header:
- expression: Long-Running-Action
- - bean:
- ref: orderManagerService
- method: newOrder
- - log:
- message: "Order ${body} created"
+ compensation: direct:cancelOrder
+ completion: direct:completeOrder
+ - transform:
+ expression:
+ header:
+ expression: Long-Running-Action
+ - bean:
+ ref: orderManagerService
+ method: newOrder
+ - log:
+ message: "Order ${body} created"
- route:
from:
uri: direct:completeOrder
@@ -617,11 +605,11 @@ from("direct:reserveCredit")
// delegate action
from("direct:creditReservation")
.saga()
- .propagation(SagaPropagation.SUPPORTS)
- .option("CreditId", body()) // mark the current body as needed in the
compensating action
- .compensation("direct:creditRefund")
- .bean("creditService", "reserveCredit")
- .log("Credit ${header.amount} reserved. Custom Id used is ${body}");
+ .propagation(SagaPropagation.SUPPORTS)
+ .option("CreditId", body()) // mark the current body as needed in the
compensating action
+ .compensation("direct:creditRefund")
+ .bean("creditService", "reserveCredit")
+ .log("Credit ${header.amount} reserved. Custom Id used is ${body}");
// called only if the saga is canceled
from("direct:creditRefund")
@@ -644,14 +632,13 @@ Notice the listing below is not using the
`Long-Running-Action` header at all.
<route>
<from uri="direct:creditReservation"/>
- <saga propagation="SUPPORTS">
+ <saga propagation="SUPPORTS" compensation="direct:creditRefund">
<option key="CreditId">
<simple>${body}</simple>
</option>
- <compensation uri="direct:creditRefund"/>
- <bean ref="creditService" method="reserveCredit"/>
- <log message="Credit ${header.amount} reserved. Custom Id used is
${body}"/>
</saga>
+ <bean ref="creditService" method="reserveCredit"/>
+ <log message="Credit ${header.amount} reserved. Custom Id used is
${body}"/>
</route>
<route>
@@ -690,14 +677,12 @@ Notice the listing below is not using the
`Long-Running-Action` header at all.
expression:
simple:
expression: "${body}"
- compensation:
- uri: direct:creditRefund
- steps:
- - bean:
- ref: creditService
- method: reserveCredit
- - log:
- message: "Credit ${header.amount} reserved. Custom Id used
is ${body}"
+ compensation: direct:creditRefund
+ - bean:
+ ref: creditService
+ method: reserveCredit
+ - log:
+ message: "Credit ${header.amount} reserved. Custom Id used is
${body}"
- route:
from:
uri: direct:creditRefund
@@ -742,12 +727,12 @@ Java::
----
from("direct:newOrder")
.saga()
- .timeout(1, TimeUnit.MINUTES) // newOrder requires that the saga is
completed within 1 minute
- .propagation(SagaPropagation.MANDATORY)
- .compensation("direct:cancelOrder")
- .completion("direct:completeOrder")
+ .timeout(1, TimeUnit.MINUTES) // newOrder requires that the saga is
completed within 1 minute
+ .propagation(SagaPropagation.MANDATORY)
+ .compensation("direct:cancelOrder")
+ .completion("direct:completeOrder")
// ...
- .log("Order ${body} created");
+ .log("Order ${body} created");
----
XML::
@@ -756,11 +741,8 @@ XML::
----
<route>
<from uri="direct:newOrder"/>
- <saga propagation="MANDATORY" timeout="1m">
- <completion uri="direct:completeOrder"/>
- <compensation uri="direct:cancelOrder"/>
- <log message="Order ${body} created"/>
- </saga>
+ <saga propagation="MANDATORY" timeout="1m"
completion="direct:completeOrder" compensation="direct:cancelOrder"/>
+ <log message="Order ${body} created"/>
</route>
----
@@ -775,13 +757,10 @@ YAML::
- saga:
propagation: MANDATORY
timeout: 1m
- compensation:
- uri: direct:cancelOrder
- completion:
- uri: direct:completeOrder
- steps:
- - log:
- message: "Order ${body} created"
+ compensation: direct:cancelOrder
+ completion: direct:completeOrder
+ - log:
+ message: "Order ${body} created"
----
====
@@ -803,10 +782,9 @@ Java::
[source,java]
----
from("direct:buy")
- .saga()
- .timeout(5, TimeUnit.MINUTES) // timeout at saga level
- .to("direct:newOrder")
- .to("direct:reserveCredit");
+ .saga().timeout(5, TimeUnit.MINUTES) // timeout at saga level
+ .to("direct:newOrder")
+ .to("direct:reserveCredit");
----
XML::
@@ -815,10 +793,9 @@ XML::
----
<route>
<from uri="direct:buy"/>
- <saga timeout="5m">
- <to uri="direct:newOrder"/>
- <to uri="direct:reserveCredit"/>
- </saga>
+ <saga timeout="5m"/>
+ <to uri="direct:newOrder"/>
+ <to uri="direct:reserveCredit"/>
</route>
----
@@ -831,12 +808,11 @@ YAML::
uri: direct:buy
steps:
- saga:
- timeout: 5m
- steps:
- - to:
- uri: direct:newOrder
- - to:
- uri: direct:reserveCredit
+ timeout: "5m"
+ - to:
+ uri: direct:newOrder
+ - to:
+ uri: direct:reserveCredit
----
====
@@ -876,22 +852,22 @@ Java::
----
from("direct:mysaga")
.saga()
- .completionMode(SagaCompletionMode.MANUAL)
- .completion("direct:finalize")
- .timeout(2, TimeUnit.HOURS)
- .to("seda:newOrder")
- .to("seda:reserveCredit");
+ .completionMode(SagaCompletionMode.MANUAL)
+ .completion("direct:finalize")
+ .timeout(2, TimeUnit.HOURS)
+ .to("seda:newOrder")
+ .to("seda:reserveCredit");
// Put here asynchronous processing for seda:newOrder and seda:reserveCredit
// They will send asynchronous callbacks to seda:operationCompleted
from("seda:operationCompleted") // an asynchronous callback
.saga()
- .propagation(SagaPropagation.MANDATORY)
- .bean("controlService", "actionExecuted")
- .filter(simple("${body} == 'ok'"))
- .to("saga:complete") // complete the current saga manually (saga
component)
- .end();
+ .propagation(SagaPropagation.MANDATORY)
+ .bean("controlService", "actionExecuted")
+ .filter(simple("${body} == 'ok'"))
+ .to("saga:complete") // complete the current saga manually (saga
component)
+ .end();
// You can put here the direct:finalize endpoint to execute final actions
----
@@ -902,22 +878,19 @@ XML::
----
<route>
<from uri="direct:mysaga"/>
- <saga completionMode="MANUAL" timeout="2h0m0s">
- <completion uri="direct:finalize"/>
- <to uri="seda:newOrder"/>
- <to uri="seda:reserveCredit"/>
- </saga>
+ <saga completionMode="MANUAL" timeout="2h0m0s"
completion="direct:finalize"/>
+ <to uri="seda:newOrder"/>
+ <to uri="seda:reserveCredit"/>
</route>
<route>
<from uri="seda:operationCompleted"/>
- <saga propagation="MANDATORY">
- <bean ref="controlService" method="actionExecuted"/>
- <filter>
- <simple>${body} == 'ok'</simple>
- <to uri="saga:complete"/>
- </filter>
- </saga>
+ <saga propagation="MANDATORY"/>
+ <bean ref="controlService" method="actionExecuted"/>
+ <filter>
+ <simple>${body} == 'ok'</simple>
+ <to uri="saga:complete"/>
+ </filter>
</route>
----
@@ -932,30 +905,27 @@ YAML::
- saga:
completionMode: MANUAL
timeout: 2h
- completion:
- uri: direct:finalize
- steps:
- - to:
- uri: seda:newOrder
- - to:
- uri: seda:reserveCredit
+ completion: direct:finalize
+ - to:
+ uri: seda:newOrder
+ - to:
+ uri: seda:reserveCredit
- route:
from:
uri: seda:operationCompleted
steps:
- saga:
propagation: MANDATORY
+ - bean:
+ ref: controlService
+ method: actionExecuted
+ - filter:
+ expression:
+ simple:
+ expression: "${body} == 'ok'"
steps:
- - bean:
- ref: controlService
- method: actionExecuted
- - filter:
- expression:
- simple:
- expression: "${body} == 'ok'"
- steps:
- - to:
- uri: saga:complete
+ - to:
+ uri: saga:complete
----
====
diff --git
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/saga.json
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/saga.json
index 1334df81a513..15543e203db7 100644
---
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/saga.json
+++
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/saga.json
@@ -20,8 +20,8 @@
"propagation": { "index": 5, "kind": "attribute", "displayName":
"Propagation", "group": "advanced", "label": "advanced", "required": false,
"type": "enum", "javaType": "org.apache.camel.model.SagaPropagation", "enum": [
"REQUIRED", "REQUIRES_NEW", "MANDATORY", "SUPPORTS", "NOT_SUPPORTED", "NEVER"
], "deprecated": false, "autowired": false, "secret": false, "defaultValue":
"REQUIRED", "description": "Set the Saga propagation mode (REQUIRED,
REQUIRES_NEW, MANDATORY, SUPPORTS, NOT_SUPP [...]
"completionMode": { "index": 6, "kind": "attribute", "displayName":
"Completion Mode", "group": "advanced", "label": "advanced", "required": false,
"type": "enum", "javaType": "org.apache.camel.model.SagaCompletionMode",
"enum": [ "AUTO", "MANUAL" ], "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "AUTO", "description": "Determine how the saga
should be considered complete. When set to AUTO, the saga is completed when the
exchange that initiates the saga is [...]
"timeout": { "index": 7, "kind": "attribute", "displayName": "Timeout",
"group": "common", "required": false, "type": "duration", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Set the maximum amount of time for the Saga. After the timeout
is expired, the saga will be compensated automatically (unless a different
decision has been taken in the meantime)." },
- "compensation": { "index": 8, "kind": "element", "displayName":
"Compensation", "group": "common", "required": false, "type": "object",
"javaType": "org.apache.camel.model.SagaActionUriDefinition", "deprecated":
false, "autowired": false, "secret": false, "description": "The compensation
endpoint URI that must be called to compensate all changes done in the route.
The route corresponding to the compensation URI must perform compensation and
complete without error. If errors occur dur [...]
- "completion": { "index": 9, "kind": "element", "displayName":
"Completion", "group": "common", "required": false, "type": "object",
"javaType": "org.apache.camel.model.SagaActionUriDefinition", "deprecated":
false, "autowired": false, "secret": false, "description": "The completion
endpoint URI that will be called when the Saga is completed successfully. The
route corresponding to the completion URI must perform completion tasks and
terminate without error. If errors occur during com [...]
+ "compensation": { "index": 8, "kind": "attribute", "displayName":
"Compensation", "group": "common", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "The compensation endpoint URI that must be
called to compensate all changes done in the route. The route corresponding to
the compensation URI must perform compensation and complete without error. If
errors occur during compensation, the saga s [...]
+ "completion": { "index": 9, "kind": "attribute", "displayName":
"Completion", "group": "common", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "The completion endpoint URI that will be
called when the Saga is completed successfully. The route corresponding to the
completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga service ma [...]
"option": { "index": 10, "kind": "element", "displayName": "Option",
"group": "advanced", "label": "advanced", "required": false, "type": "array",
"javaType":
"java.util.List<org.apache.camel.model.PropertyExpressionDefinition>",
"deprecated": false, "autowired": false, "secret": false, "description":
"Allows to save properties of the current exchange in order to re-use them in a
compensation\/completion callback route. Options are usually helpful e.g. to
store and retrieve identifie [...]
"outputs": { "index": 11, "kind": "element", "displayName": "Outputs",
"group": "common", "required": true, "type": "array", "javaType":
"java.util.List", "oneOf": [ "aggregate", "bean", "choice", "circuitBreaker",
"claimCheck", "convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay",
"doCatch", "doFinally", "doTry", "dynamicRouter", "enrich", "filter",
"idempotentConsumer", "intercept", "interceptFrom", "interceptSendToEndpoint",
"kamelet", "loadBalance", "log", "loop", "ma [...]
}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/SagaActionUriDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/SagaActionUriDefinition.java
deleted file mode 100644
index cdcadbd87893..000000000000
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/SagaActionUriDefinition.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.model;
-
-import jakarta.xml.bind.annotation.XmlAccessType;
-import jakarta.xml.bind.annotation.XmlAccessorType;
-
-import org.apache.camel.spi.Metadata;
-
-/**
- * Allows to declare saga actions to complete or compensate a saga
- */
-@Metadata(label = "configuration")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class SagaActionUriDefinition extends
SendDefinition<SagaActionUriDefinition> {
-
- public SagaActionUriDefinition() {
- }
-
- public SagaActionUriDefinition(SagaActionUriDefinition source) {
- super(source);
- }
-
- public SagaActionUriDefinition(String uri) {
- super(uri);
- }
-
- @Override
- public SagaActionUriDefinition copyDefinition() {
- return new SagaActionUriDefinition(this);
- }
-
- @Override
- public String getShortName() {
- return "SagaAction";
- }
-}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/SagaDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/SagaDefinition.java
index 248a29893ac3..92be490ff371 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/SagaDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/SagaDefinition.java
@@ -30,7 +30,9 @@ import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import org.apache.camel.Expression;
+import org.apache.camel.builder.EndpointProducerBuilder;
import org.apache.camel.saga.CamelSagaService;
+import org.apache.camel.spi.AsEndpointUri;
import org.apache.camel.spi.Metadata;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.TimeUtils;
@@ -43,6 +45,11 @@ import org.apache.camel.util.TimeUtils;
@XmlAccessorType(XmlAccessType.FIELD)
public class SagaDefinition extends OutputDefinition<SagaDefinition> {
+ @XmlTransient
+ private EndpointProducerBuilder compensationEndpointProducerBuilder;
+ @XmlTransient
+ private EndpointProducerBuilder completionEndpointProducerBuilder;
+
@XmlTransient
private CamelSagaService sagaServiceBean;
@XmlAttribute
@@ -59,10 +66,12 @@ public class SagaDefinition extends
OutputDefinition<SagaDefinition> {
@XmlAttribute
@Metadata(javaType = "java.time.Duration")
private String timeout;
- @XmlElement
- private SagaActionUriDefinition compensation;
- @XmlElement
- private SagaActionUriDefinition completion;
+ @XmlAttribute
+ @Metadata
+ private String compensation;
+ @XmlAttribute
+ @Metadata
+ private String completion;
@XmlElement(name = "option")
@Metadata(label = "advanced")
private List<PropertyExpressionDefinition> options;
@@ -77,8 +86,10 @@ public class SagaDefinition extends
OutputDefinition<SagaDefinition> {
this.propagation = source.propagation;
this.completionMode = source.completionMode;
this.timeout = source.timeout;
- this.compensation = source.compensation != null ?
source.compensation.copyDefinition() : null;
- this.completion = source.completion != null ?
source.completion.copyDefinition() : null;
+ this.compensation = source.compensation;
+ this.completion = source.completion;
+ this.compensationEndpointProducerBuilder =
source.compensationEndpointProducerBuilder;
+ this.completionEndpointProducerBuilder =
source.completionEndpointProducerBuilder;
this.options =
ProcessorDefinitionHelper.deepCopyDefinitions(source.options);
}
@@ -135,6 +146,14 @@ public class SagaDefinition extends
OutputDefinition<SagaDefinition> {
// Properties
+ public EndpointProducerBuilder getCompensationEndpointProducerBuilder() {
+ return compensationEndpointProducerBuilder;
+ }
+
+ public EndpointProducerBuilder getCompletionEndpointProducerBuilder() {
+ return completionEndpointProducerBuilder;
+ }
+
public CamelSagaService getSagaServiceBean() {
return sagaServiceBean;
}
@@ -150,7 +169,7 @@ public class SagaDefinition extends
OutputDefinition<SagaDefinition> {
this.sagaService = sagaService;
}
- public SagaActionUriDefinition getCompensation() {
+ public String getCompensation() {
return compensation;
}
@@ -159,11 +178,20 @@ public class SagaDefinition extends
OutputDefinition<SagaDefinition> {
* corresponding to the compensation URI must perform compensation and
complete without error. If errors occur
* during compensation, the saga service may call again the compensation
URI to retry.
*/
- public void setCompensation(SagaActionUriDefinition compensation) {
+ public void setCompensation(@AsEndpointUri String compensation) {
this.compensation = compensation;
}
- public SagaActionUriDefinition getCompletion() {
+ /**
+ * The compensation endpoint URI that must be called to compensate all
changes done in the route. The route
+ * corresponding to the compensation URI must perform compensation and
complete without error. If errors occur
+ * during compensation, the saga service may call again the compensation
URI to retry.
+ */
+ public void setCompensation(@AsEndpointUri EndpointProducerBuilder
compensation) {
+ this.compensationEndpointProducerBuilder = compensation;
+ }
+
+ public String getCompletion() {
return completion;
}
@@ -172,10 +200,19 @@ public class SagaDefinition extends
OutputDefinition<SagaDefinition> {
* to the completion URI must perform completion tasks and terminate
without error. If errors occur during
* completion, the saga service may call again the completion URI to retry.
*/
- public void setCompletion(SagaActionUriDefinition completion) {
+ public void setCompletion(@AsEndpointUri String completion) {
this.completion = completion;
}
+ /**
+ * The completion endpoint URI that will be called when the Saga is
completed successfully. The route corresponding
+ * to the completion URI must perform completion tasks and terminate
without error. If errors occur during
+ * completion, the saga service may call again the completion URI to retry.
+ */
+ public void setCompletion(@AsEndpointUri EndpointProducerBuilder
completion) {
+ this.completionEndpointProducerBuilder = completion;
+ }
+
public String getPropagation() {
return propagation;
}
@@ -236,18 +273,12 @@ public class SagaDefinition extends
OutputDefinition<SagaDefinition> {
// Builders
public SagaDefinition compensation(String compensation) {
- if (this.compensation != null) {
- throw new IllegalStateException("Compensation has already been
set");
- }
- this.compensation = new SagaActionUriDefinition(compensation);
+ this.compensation = compensation;
return this;
}
public SagaDefinition completion(String completion) {
- if (this.completion != null) {
- throw new IllegalStateException("Completion has already been set");
- }
- this.completion = new SagaActionUriDefinition(completion);
+ this.completion = completion;
return this;
}
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java
index cc7b8412ad90..75737ae210d5 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java
@@ -17,16 +17,17 @@
package org.apache.camel.reifier;
import java.util.Map;
-import java.util.Optional;
import java.util.TreeMap;
+import org.apache.camel.CamelContextAware;
import org.apache.camel.Endpoint;
import org.apache.camel.Expression;
import org.apache.camel.Processor;
import org.apache.camel.Route;
import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.ProcessorDefinitionHelper;
import org.apache.camel.model.PropertyExpressionDefinition;
-import org.apache.camel.model.SagaActionUriDefinition;
+import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.SagaDefinition;
import org.apache.camel.processor.saga.SagaCompletionMode;
import org.apache.camel.processor.saga.SagaProcessor;
@@ -34,6 +35,7 @@ import org.apache.camel.processor.saga.SagaProcessorBuilder;
import org.apache.camel.processor.saga.SagaPropagation;
import org.apache.camel.saga.CamelSagaService;
import org.apache.camel.saga.CamelSagaStep;
+import org.apache.camel.support.EndpointHelper;
public class SagaReifier extends ProcessorReifier<SagaDefinition> {
@@ -43,15 +45,38 @@ public class SagaReifier extends
ProcessorReifier<SagaDefinition> {
@Override
public Processor createProcessor() throws Exception {
- Endpoint compensationEndpoint =
Optional.ofNullable(definition.getCompensation())
- .map(SagaActionUriDefinition::getUri)
- .map(this::resolveEndpoint)
- .orElse(null);
- Endpoint completionEndpoint =
Optional.ofNullable(definition.getCompletion())
- .map(SagaActionUriDefinition::getUri)
- .map(this::resolveEndpoint)
- .orElse(null);
+ // compensation
+ String uri;
+ if (definition.getCompensationEndpointProducerBuilder() != null) {
+ uri =
definition.getCompensationEndpointProducerBuilder().getRawUri();
+ } else {
+ uri = definition.getCompensation();
+ }
+ // route templates should pre parse uri as they have dynamic values as
part of their template parameters
+ RouteDefinition rd = ProcessorDefinitionHelper.getRoute(definition);
+ if (uri != null && rd != null && rd.isTemplate() != null &&
rd.isTemplate()) {
+ uri =
EndpointHelper.resolveEndpointUriPropertyPlaceholders(camelContext, uri);
+ }
+ Endpoint compensationEndpoint = null;
+ if (uri != null) {
+ compensationEndpoint = camelContext.getEndpoint(uri);
+ }
+
+ // completion
+ if (definition.getCompletionEndpointProducerBuilder() != null) {
+ uri =
definition.getCompletionEndpointProducerBuilder().getRawUri();
+ } else {
+ uri = definition.getCompletion();
+ }
+ // route templates should pre parse uri as they have dynamic values as
part of their template parameters
+ if (uri != null && rd != null && rd.isTemplate() != null &&
rd.isTemplate()) {
+ uri =
EndpointHelper.resolveEndpointUriPropertyPlaceholders(camelContext, uri);
+ }
+ Endpoint completionEndpoint = null;
+ if (uri != null) {
+ completionEndpoint = camelContext.getEndpoint(uri);
+ }
Map<String, Expression> optionsMap = new TreeMap<>();
if (definition.getOptions() != null) {
@@ -81,6 +106,7 @@ public class SagaReifier extends
ProcessorReifier<SagaDefinition> {
Processor childProcessor = this.createChildProcessor(true);
CamelSagaService camelSagaService = resolveSagaService();
+ CamelContextAware.trySetCamelContext(camelSagaService,
getCamelContext());
camelSagaService.registerStep(step);
diff --git a/core/camel-core/src/test/resources/org/apache/camel/model/saga.xml
b/core/camel-core/src/test/resources/org/apache/camel/model/saga.xml
index 03412a85621b..23fc27f62011 100644
--- a/core/camel-core/src/test/resources/org/apache/camel/model/saga.xml
+++ b/core/camel-core/src/test/resources/org/apache/camel/model/saga.xml
@@ -18,14 +18,12 @@
-->
<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
- <route>
- <from uri="direct:start"/>
- <saga>
- <compensation uri="mock:uri" />
- </saga>
- <setBody>
- <simple>${in.body} extra data!</simple>
- </setBody>
- <to uri="mock:end"/>
- </route>
+ <route>
+ <from uri="direct:start"/>
+ <saga compensation="mock:uri"/>
+ <setBody>
+ <simple>${in.body} extra data!</simple>
+ </setBody>
+ <to uri="mock:end"/>
+ </route>
</routes>
diff --git
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 13920b6e1df8..598c58845a34 100644
---
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -1061,21 +1061,18 @@ public class ModelParser extends BaseParser {
}
protected SagaDefinition doParseSagaDefinition() throws IOException,
XmlPullParserException {
return doParse(new SagaDefinition(), (def, key, val) -> switch (key) {
+ case "compensation": def.setCompensation(val); yield true;
+ case "completion": def.setCompletion(val); yield true;
case "completionMode": def.setCompletionMode(val); yield true;
case "propagation": def.setPropagation(val); yield true;
case "sagaService": def.setSagaService(val); yield true;
case "timeout": def.setTimeout(val); yield true;
default: yield
processorDefinitionAttributeHandler().accept(def, key, val);
}, (def, key) -> switch (key) {
- case "compensation":
def.setCompensation(doParseSagaActionUriDefinition()); yield true;
- case "completion":
def.setCompletion(doParseSagaActionUriDefinition()); yield true;
case "option": doAdd(doParsePropertyExpressionDefinition(),
def.getOptions(), def::setOptions); yield true;
default: yield outputDefinitionElementHandler().accept(def,
key);
}, noValueHandler());
}
- protected SagaActionUriDefinition doParseSagaActionUriDefinition() throws
IOException, XmlPullParserException {
- return doParse(new SagaActionUriDefinition(),
sendDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(),
noValueHandler());
- }
protected SamplingDefinition doParseSamplingDefinition() throws
IOException, XmlPullParserException {
return doParse(new SamplingDefinition(), (def, key, val) -> switch
(key) {
case "messageFrequency": def.setMessageFrequency(val); yield
true;
diff --git
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index 212452be88c4..b6bb134bac52 100644
---
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -1712,11 +1712,6 @@ public class ModelWriter extends BaseWriter {
doWriteExpressionNodeElements(def);
endElement(name);
}
- protected void doWriteSagaActionUriDefinition(String name,
SagaActionUriDefinition def) throws IOException {
- startElement(name);
- doWriteSendDefinitionAttributes(def);
- endElement(name);
- }
protected void doWriteSagaDefinition(String name, SagaDefinition def)
throws IOException {
startElement(name);
doWriteProcessorDefinitionAttributes(def);
@@ -1724,9 +1719,9 @@ public class ModelWriter extends BaseWriter {
doWriteAttribute("propagation", def.getPropagation(), "REQUIRED");
doWriteAttribute("completionMode", def.getCompletionMode(), "AUTO");
doWriteAttribute("timeout", def.getTimeout(), null);
+ doWriteAttribute("compensation", def.getCompensation(), null);
+ doWriteAttribute("completion", def.getCompletion(), null);
doWriteList(null, "option", def.getOptions(),
this::doWritePropertyExpressionDefinition);
- doWriteElement("compensation", def.getCompensation(),
this::doWriteSagaActionUriDefinition);
- doWriteElement("completion", def.getCompletion(),
this::doWriteSagaActionUriDefinition);
doWriteList(null, null, def.getOutputs(),
this::doWriteProcessorDefinitionRef);
endElement(name);
}
diff --git a/core/camel-xml-io/src/test/resources/saga.xml
b/core/camel-xml-io/src/test/resources/saga.xml
index 0ac00028695e..6e24d3490d2a 100644
--- a/core/camel-xml-io/src/test/resources/saga.xml
+++ b/core/camel-xml-io/src/test/resources/saga.xml
@@ -20,9 +20,7 @@
<routes id="camel" xmlns="http://camel.apache.org/schema/xml-io">
<route>
<from uri="direct:start"/>
- <saga>
- <compensation uri="mock:uri" />
- </saga>
+ <saga compensation="mock:uri"/>
<setBody>
<simple>${in.body} extra data!</simple>
</setBody>
diff --git
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 846612c5ee75..c4c310422894 100644
---
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -1712,11 +1712,6 @@ public class ModelWriter extends BaseWriter {
doWriteExpressionNodeElements(def);
endElement(name);
}
- protected void doWriteSagaActionUriDefinition(String name,
SagaActionUriDefinition def) throws IOException {
- startElement(name);
- doWriteSendDefinitionAttributes(def);
- endElement(name);
- }
protected void doWriteSagaDefinition(String name, SagaDefinition def)
throws IOException {
startElement(name);
doWriteProcessorDefinitionAttributes(def);
@@ -1724,9 +1719,9 @@ public class ModelWriter extends BaseWriter {
doWriteAttribute("propagation", def.getPropagation(), "REQUIRED");
doWriteAttribute("completionMode", def.getCompletionMode(), "AUTO");
doWriteAttribute("timeout", def.getTimeout(), null);
+ doWriteAttribute("compensation", def.getCompensation(), null);
+ doWriteAttribute("completion", def.getCompletion(), null);
doWriteList(null, "option", def.getOptions(),
this::doWritePropertyExpressionDefinition);
- doWriteElement("compensation", def.getCompensation(),
this::doWriteSagaActionUriDefinition);
- doWriteElement("completion", def.getCompletion(),
this::doWriteSagaActionUriDefinition);
doWriteList(null, null, def.getOutputs(),
this::doWriteProcessorDefinitionRef);
endElement(name);
}
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
index 590023ca05d9..6135543c315a 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
@@ -18,6 +18,116 @@ See the xref:camel-upgrade-recipes-tool.adoc[documentation]
page for details.
In the YAML DSL we have renamed `routePolicy` to `routePolicyRef` on the
`route` node,
as that is the correct name.
+==== Saga EIP
+
+The Saga EIP has _fixed_ the model for how to configure completion and
compensation URIs.
+
+For Java DSL there is no changes, but XML and YAML DSL is affected. Here the
`<compensation>` and `<completion>` tags
+has been changed to be an attribute on `<saga>` instead as shown below:
+
+Before:
+
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <saga sagaService="mySagaService">
+ <compensation uri="mock:compensation"/>
+ <completion uri="mock:completion"/>
+ <option key="myOptionKey">
+ <constant>myOptionValue</constant>
+ </option>
+ <option key="myOptionKey2">
+ <constant>myOptionValue2</constant>
+ </option>
+ </saga>
+ <choice>
+ <when>
+ <simple>${body} == 'fail'</simple>
+ <throwException exceptionType="java.lang.RuntimeException"
message="fail"/>
+ </when>
+ </choice>
+ <to uri="mock:end"/>
+</route>
+----
+
+In YAML DSL the changes are even simpler as the endpoint is moved from `uri`
to the value of `completion` or `compensation`.
+
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - saga:
+ sagaService: mySagaService
+ compensation:
+ uri: mock:compensation
+ completion:
+ uri: mock:completion
+ key: myOptionKey2
+ - choice:
+ when:
+ - expression:
+ simple:
+ expression: "${body} == 'fail'"
+ steps:
+ - throwException:
+ message: fail
+ exceptionType: java.lang.RuntimeException
+ - to:
+ uri: mock:end
+
+----
+
+After:
+
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <saga sagaService="mySagaService" compensation="mock:compensation"
completion="mock:completion">
+ <option key="myOptionKey">
+ <constant>myOptionValue</constant>
+ </option>
+ <option key="myOptionKey2">
+ <constant>myOptionValue2</constant>
+ </option>
+ </saga>
+ <choice>
+ <when>
+ <simple>${body} == 'fail'</simple>
+ <throwException exceptionType="java.lang.RuntimeException"
message="fail"/>
+ </when>
+ </choice>
+ <to uri="mock:end"/>
+</route>
+----
+
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - saga:
+ sagaService: mySagaService
+ compensation: mock:compensation
+ completion: mock:completion
+ key: myOptionKey2
+ - choice:
+ when:
+ - expression:
+ simple:
+ expression: "${body} == 'fail'"
+ steps:
+ - throwException:
+ message: fail
+ exceptionType: java.lang.RuntimeException
+ - to:
+ uri: mock:end
+----
+
=== camel-simple
In the simple language then init blocks syntax has changed to require that
each variable ends with a semicolon and new line (no trailing comments etc is
allowed)
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc
index 4a9675848ec8..a189f00ed4e9 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc
@@ -20,6 +20,116 @@ uses `InOnly` pattern.
Removed 2 deprecated methods in Java DSL for `throttler` EIP.
+==== Saga EIP
+
+The Saga EIP has _fixed_ the model for how to configure completion and
compensation URIs.
+
+For Java DSL there is no changes, but XML and YAML DSL is affected. Here the
`<compensation>` and `<completion>` tags
+has been changed to be an attribute on `<saga>` instead as shown below:
+
+Before:
+
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <saga sagaService="mySagaService">
+ <compensation uri="mock:compensation"/>
+ <completion uri="mock:completion"/>
+ <option key="myOptionKey">
+ <constant>myOptionValue</constant>
+ </option>
+ <option key="myOptionKey2">
+ <constant>myOptionValue2</constant>
+ </option>
+ </saga>
+ <choice>
+ <when>
+ <simple>${body} == 'fail'</simple>
+ <throwException exceptionType="java.lang.RuntimeException"
message="fail"/>
+ </when>
+ </choice>
+ <to uri="mock:end"/>
+</route>
+----
+
+In YAML DSL the changes are even simpler as the endpoint is moved from `uri`
to the value of `completion` or `compensation`.
+
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - saga:
+ sagaService: mySagaService
+ compensation:
+ uri: mock:compensation
+ completion:
+ uri: mock:completion
+ key: myOptionKey2
+ - choice:
+ when:
+ - expression:
+ simple:
+ expression: "${body} == 'fail'"
+ steps:
+ - throwException:
+ message: fail
+ exceptionType: java.lang.RuntimeException
+ - to:
+ uri: mock:end
+
+----
+
+After:
+
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <saga sagaService="mySagaService" compensation="mock:compensation"
completion="mock:completion">
+ <option key="myOptionKey">
+ <constant>myOptionValue</constant>
+ </option>
+ <option key="myOptionKey2">
+ <constant>myOptionValue2</constant>
+ </option>
+ </saga>
+ <choice>
+ <when>
+ <simple>${body} == 'fail'</simple>
+ <throwException exceptionType="java.lang.RuntimeException"
message="fail"/>
+ </when>
+ </choice>
+ <to uri="mock:end"/>
+</route>
+----
+
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - saga:
+ sagaService: mySagaService
+ compensation: mock:compensation
+ completion: mock:completion
+ key: myOptionKey2
+ - choice:
+ when:
+ - expression:
+ simple:
+ expression: "${body} == 'fail'"
+ steps:
+ - throwException:
+ message: fail
+ exceptionType: java.lang.RuntimeException
+ - to:
+ uri: mock:end
+----
+
=== camel-simple
In the simple language then init blocks syntax has changed to require that
each variable ends with a semicolon and new line (no trailing comments etc is
allowed)
diff --git
a/dsl/camel-kamelet-main-support/src/main/java/org/apache/camel/main/stub/StubBeanRepository.java
b/dsl/camel-kamelet-main-support/src/main/java/org/apache/camel/main/stub/StubBeanRepository.java
index a6a6f44cd370..b925b7850836 100644
---
a/dsl/camel-kamelet-main-support/src/main/java/org/apache/camel/main/stub/StubBeanRepository.java
+++
b/dsl/camel-kamelet-main-support/src/main/java/org/apache/camel/main/stub/StubBeanRepository.java
@@ -34,6 +34,8 @@ import
org.apache.camel.processor.aggregate.GroupedBodyAggregationStrategy;
import org.apache.camel.processor.aggregate.MemoryAggregationRepository;
import org.apache.camel.processor.loadbalancer.LoadBalancer;
import org.apache.camel.processor.loadbalancer.RoundRobinLoadBalancer;
+import org.apache.camel.saga.CamelSagaService;
+import org.apache.camel.saga.InMemorySagaService;
import org.apache.camel.spi.AggregationRepository;
import org.apache.camel.spi.BeanRepository;
import org.apache.camel.spi.ClaimCheckRepository;
@@ -62,6 +64,7 @@ public class StubBeanRepository implements BeanRepository {
private final RoutePolicy service9 = new RoutePolicySupport() {
};
private final ExecutorService service10 = Executors.newCachedThreadPool();
+ private final CamelSagaService service11 = new InMemorySagaService();
private final String stubPattern;
@@ -139,6 +142,9 @@ public class StubBeanRepository implements BeanRepository {
if (ExecutorService.class.isAssignableFrom(type)) {
return (T) service10;
}
+ if (CamelSagaService.class.isAssignableFrom(type)) {
+ return (T) service11;
+ }
if (Logger.class.isAssignableFrom(type)) {
return (T) LOG;
}
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/pom.xml
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/pom.xml
index 462412e678a5..a8f48fccea23 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/pom.xml
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/pom.xml
@@ -140,10 +140,6 @@
<bannedDefinition>org.apache.camel.model.app.BeansDefinition</bannedDefinition>
<bannedDefinition>org.apache.camel.model.app.ApplicationDefinition</bannedDefinition>
</bannedDefinitions>
- <additionalDefinitions>
- <!-- saga -->
-
<additionalDefinition>org.apache.camel.model.SagaActionUriDefinition</additionalDefinition>
- </additionalDefinitions>
</configuration>
</execution>
</executions>
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index b858b853a32c..7f9da6c9d827 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -77,7 +77,6 @@ import org.apache.camel.model.RouteContextRefDefinition;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.RouteTemplateParameterDefinition;
import org.apache.camel.model.RoutingSlipDefinition;
-import org.apache.camel.model.SagaActionUriDefinition;
import org.apache.camel.model.SagaDefinition;
import org.apache.camel.model.SamplingDefinition;
import org.apache.camel.model.ScriptDefinition;
@@ -16239,78 +16238,6 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
}
}
- @YamlType(
- inline = true,
- types = org.apache.camel.model.SagaActionUriDefinition.class,
- order =
org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
- properties = {
- @YamlProperty(name = "description", type = "string"),
- @YamlProperty(name = "disabled", type = "boolean"),
- @YamlProperty(name = "id", type = "string"),
- @YamlProperty(name = "note", type = "string"),
- @YamlProperty(name = "parameters", type = "object"),
- @YamlProperty(name = "uri", type = "string", required =
true)
- }
- )
- public static class SagaActionUriDefinitionDeserializer extends
YamlDeserializerEndpointAwareBase<SagaActionUriDefinition> {
- public SagaActionUriDefinitionDeserializer() {
- super(SagaActionUriDefinition.class);
- }
-
- @Override
- protected SagaActionUriDefinition newInstance() {
- return new SagaActionUriDefinition();
- }
-
- @Override
- protected SagaActionUriDefinition newInstance(String value) {
- return new SagaActionUriDefinition(value);
- }
-
- @Override
- protected void setEndpointUri(CamelContext camelContext, Node node,
- SagaActionUriDefinition target, Map<String, Object>
parameters) {
-
target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext,
node, target.getUri(), parameters));
- }
-
- @Override
- protected boolean setProperty(SagaActionUriDefinition target, String
propertyKey,
- String propertyName, Node node) {
- propertyKey =
org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
- switch(propertyKey) {
- case "disabled": {
- String val = asText(node);
- target.setDisabled(val);
- break;
- }
- case "uri": {
- String val = asText(node);
- target.setUri(val);
- break;
- }
- case "id": {
- String val = asText(node);
- target.setId(val);
- break;
- }
- case "description": {
- String val = asText(node);
- target.setDescription(val);
- break;
- }
- case "note": {
- String val = asText(node);
- target.setNote(val);
- break;
- }
- default: {
- return false;
- }
- }
- return true;
- }
- }
-
@YamlType(
nodes = "saga",
types = org.apache.camel.model.SagaDefinition.class,
@@ -16319,8 +16246,8 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
description = "Enables Sagas on the route",
deprecated = false,
properties = {
- @YamlProperty(name = "compensation", type =
"object:org.apache.camel.model.SagaActionUriDefinition", description = "The
compensation endpoint URI that must be called to compensate all changes done in
the route. The route corresponding to the compensation URI must perform
compensation and complete without error. If errors occur during compensation,
the saga service may call again the compensation URI to retry.", displayName =
"Compensation"),
- @YamlProperty(name = "completion", type =
"object:org.apache.camel.model.SagaActionUriDefinition", description = "The
completion endpoint URI that will be called when the Saga is completed
successfully. The route corresponding to the completion URI must perform
completion tasks and terminate without error. If errors occur during
completion, the saga service may call again the completion URI to retry.",
displayName = "Completion"),
+ @YamlProperty(name = "compensation", type = "string",
description = "The compensation endpoint URI that must be called to compensate
all changes done in the route. The route corresponding to the compensation URI
must perform compensation and complete without error. If errors occur during
compensation, the saga service may call again the compensation URI to retry.",
displayName = "Compensation"),
+ @YamlProperty(name = "completion", type = "string",
description = "The completion endpoint URI that will be called when the Saga is
completed successfully. The route corresponding to the completion URI must
perform completion tasks and terminate without error. If errors occur during
completion, the saga service may call again the completion URI to retry.",
displayName = "Completion"),
@YamlProperty(name = "completionMode", type =
"enum:AUTO,MANUAL", defaultValue = "AUTO", description = "Determine how the
saga should be considered complete. When set to AUTO, the saga is completed
when the exchange that initiates the saga is processed successfully, or
compensated when it completes exceptionally. When set to MANUAL, the user must
complete or compensate the saga using the saga:complete or saga:compensate
endpoints.", displayName = "Completion Mode"),
@YamlProperty(name = "description", type = "string",
description = "Sets the description of this node", displayName = "Description"),
@YamlProperty(name = "disabled", type = "boolean",
defaultValue = "false", description = "Disables this EIP from the route.",
displayName = "Disabled"),
@@ -16349,12 +16276,12 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
propertyKey =
org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
switch(propertyKey) {
case "compensation": {
- org.apache.camel.model.SagaActionUriDefinition val =
asType(node, org.apache.camel.model.SagaActionUriDefinition.class);
+ String val = asText(node);
target.setCompensation(val);
break;
}
case "completion": {
- org.apache.camel.model.SagaActionUriDefinition val =
asType(node, org.apache.camel.model.SagaActionUriDefinition.class);
+ String val = asText(node);
target.setCompletion(val);
break;
}
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index a500d5828274..09d84f8285d4 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -367,7 +367,6 @@ public final class ModelDeserializersResolver implements
YamlDeserializerResolve
case "org.apache.camel.model.RoutingSlipDefinition": return new
ModelDeserializers.RoutingSlipDefinitionDeserializer();
case "rss": return new
ModelDeserializers.RssDataFormatDeserializer();
case "org.apache.camel.model.dataformat.RssDataFormat": return new
ModelDeserializers.RssDataFormatDeserializer();
- case "org.apache.camel.model.SagaActionUriDefinition": return new
ModelDeserializers.SagaActionUriDefinitionDeserializer();
case "saga": return new
ModelDeserializers.SagaDefinitionDeserializer();
case "org.apache.camel.model.SagaDefinition": return new
ModelDeserializers.SagaDefinitionDeserializer();
case "sample": return new
ModelDeserializers.SamplingDefinitionDeserializer();
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index faa6977a189d..75c0a28249bd 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -6102,35 +6102,6 @@
}
} ]
},
- "org.apache.camel.model.SagaActionUriDefinition" : {
- "oneOf" : [ {
- "type" : "string"
- }, {
- "type" : "object",
- "additionalProperties" : false,
- "properties" : {
- "description" : {
- "type" : "string"
- },
- "disabled" : {
- "type" : "boolean"
- },
- "id" : {
- "type" : "string"
- },
- "note" : {
- "type" : "string"
- },
- "parameters" : {
- "type" : "object"
- },
- "uri" : {
- "type" : "string"
- }
- }
- } ],
- "required" : [ "uri" ]
- },
"org.apache.camel.model.SagaDefinition" : {
"title" : "Saga",
"description" : "Enables Sagas on the route",
@@ -6138,14 +6109,14 @@
"additionalProperties" : false,
"properties" : {
"compensation" : {
+ "type" : "string",
"title" : "Compensation",
- "description" : "The compensation endpoint URI that must be called
to compensate all changes done in the route. The route corresponding to the
compensation URI must perform compensation and complete without error. If
errors occur during compensation, the saga service may call again the
compensation URI to retry.",
- "$ref" :
"#/items/definitions/org.apache.camel.model.SagaActionUriDefinition"
+ "description" : "The compensation endpoint URI that must be called
to compensate all changes done in the route. The route corresponding to the
compensation URI must perform compensation and complete without error. If
errors occur during compensation, the saga service may call again the
compensation URI to retry."
},
"completion" : {
+ "type" : "string",
"title" : "Completion",
- "description" : "The completion endpoint URI that will be called
when the Saga is completed successfully. The route corresponding to the
completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga service may call again the completion
URI to retry.",
- "$ref" :
"#/items/definitions/org.apache.camel.model.SagaActionUriDefinition"
+ "description" : "The completion endpoint URI that will be called
when the Saga is completed successfully. The route corresponding to the
completion URI must perform completion tasks and terminate without error. If
errors occur during completion, the saga service may call again the completion
URI to retry."
},
"completionMode" : {
"type" : "string",
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy
index 84f3ca3d5858..a8c8dd6376f7 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy
@@ -17,7 +17,6 @@
package org.apache.camel.dsl.yaml
import org.apache.camel.dsl.yaml.support.YamlTestSupport
-import org.apache.camel.model.SagaActionUriDefinition
import org.apache.camel.model.SagaDefinition
import org.apache.camel.model.ToDefinition
import org.apache.camel.model.language.JqExpression
@@ -34,13 +33,8 @@ class SagaTest extends YamlTestSupport {
with(context.routeDefinitions[0].outputs[0], SagaDefinition) {
propagation == "MANDATORY"
completionMode == "MANUAL"
-
- with(compensation, SagaActionUriDefinition) {
- uri == "direct:compensation"
- }
- with(completion, SagaActionUriDefinition) {
- uri == "direct:completion"
- }
+ compensation == "direct:compensation"
+ completion == "direct:completion"
// saga spans the entire route so steps are inserted before
any saga specific step
// https://issues.apache.org/jira/browse/CAMEL-17129
with(outputs[0], ToDefinition) {
@@ -66,12 +60,8 @@ class SagaTest extends YamlTestSupport {
- saga:
propagation: "MANDATORY"
completionMode: "MANUAL"
- compensation:
- uri: "direct"
- parameters:
- name: compensation
- completion:
- uri: "direct:completion"
+ compensation: direct:compensation
+ completion: direct:completion
steps:
- to: "direct:something"
option:
@@ -84,29 +74,6 @@ class SagaTest extends YamlTestSupport {
expression: "${body}"
- to: "mock:result"
'''),
- asResource('full-parameters-out-of-order)', '''
- - from:
- uri: "direct:start"
- steps:
- - saga:
- propagation: "MANDATORY"
- completionMode: "MANUAL"
- compensation:
- parameters:
- name: compensation
- uri: "direct"
- completion:
- uri: "direct:completion"
- steps:
- - to: "direct:something"
- option:
- - key: o1
- jq: ".foo"
- - key: o2
- expression:
- simple: "${body}"
- - to: "mock:result"
- '''),
asResource('short', '''
- from:
uri: "direct:start"