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

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot-examples.git


The following commit(s) were added to refs/heads/main by this push:
     new 14a0f56  CAMEL-18273 Add Camel EIP Saga example
14a0f56 is described below

commit 14a0f56f37f7df5a672393687ad1fac4ab461cff
Author: Marco Carletti <[email protected]>
AuthorDate: Fri Jul 15 12:50:49 2022 +0200

    CAMEL-18273 Add Camel EIP Saga example
---
 README.adoc                                        |   4 +-
 pom.xml                                            |   1 +
 saga/doc-resources/compesate-diagram.png           | Bin 0 -> 37193 bytes
 saga/doc-resources/logic-diagram.png               | Bin 0 -> 27916 bytes
 saga/doc-resources/tech-diagram.png                | Bin 0 -> 33322 bytes
 saga/install-ocp-ephemeral.sh                      |  10 +
 saga/install-ocp.sh                                |  10 +
 saga/local-resources/docker-compose.yml            |  14 ++
 saga/ocp-resources/amq-broker-ephemeral.yaml       | 116 ++++++++++++
 saga/ocp-resources/amq-broker.yaml                 | 138 ++++++++++++++
 saga/ocp-resources/lra-coordinator-ephemeral.yaml  |  92 +++++++++
 saga/ocp-resources/lra-coordinator.yaml            | 112 +++++++++++
 saga/pom.xml                                       | 134 +++++++++++++
 saga/readme.adoc                                   | 207 +++++++++++++++++++++
 saga/run-local.sh                                  |  23 +++
 saga/saga-app/pom.xml                              |  98 ++++++++++
 .../camel/example/saga/CamelSagaApplication.java   |  39 ++++
 .../org/apache/camel/example/saga/SagaRoute.java   |  56 ++++++
 saga/saga-app/src/main/jkube/deployment.yml        |  11 ++
 saga/saga-app/src/main/resources/application.yml   |  51 +++++
 saga/saga-flight-service/pom.xml                   |  98 ++++++++++
 .../camel/example/saga/CamelSagaFlightService.java |  23 +++
 .../org/apache/camel/example/saga/FlightRoute.java |  44 +++++
 .../src/main/jkube/deployment.yml                  |  11 ++
 .../src/main/resources/application.yml             |  49 +++++
 saga/saga-payment-service/pom.xml                  |  98 ++++++++++
 .../example/saga/CamelSagaPaymentService.java      |  23 +++
 .../apache/camel/example/saga/PaymentRoute.java    |  51 +++++
 .../src/main/jkube/deployment.yml                  |  11 ++
 .../src/main/resources/application.yml             |  49 +++++
 saga/saga-train-service/pom.xml                    |  98 ++++++++++
 .../camel/example/saga/CamelSagaTrainService.java  |  23 +++
 .../org/apache/camel/example/saga/TrainRoute.java  |  44 +++++
 .../src/main/jkube/deployment.yml                  |  11 ++
 .../src/main/resources/application.yml             |  49 +++++
 saga/stop-local.sh                                 |  16 ++
 36 files changed, 1813 insertions(+), 1 deletion(-)

diff --git a/README.adoc b/README.adoc
index 870ec6b..7275b01 100644
--- a/README.adoc
+++ b/README.adoc
@@ -27,7 +27,7 @@ readme's instructions.
 === Examples
 
 // examples: START
-Number of Examples: 57 (0 deprecated)
+Number of Examples: 58 (0 deprecated)
 
 [width="100%",cols="4,2,4",options="header"]
 |===
@@ -103,6 +103,8 @@ Number of Examples: 57 (0 deprecated)
 
 | link:resilience4j/README.adoc[Resilience4j] (resilience4j) | EIP | An 
example showing how to use Resilience4j EIP as circuit breaker in Camel routes
 
+| link:saga/readme.adoc[Saga] (saga) | EIP | This example shows how to work 
with a simple Apache Camel application using Spring Boot and Narayana LRA 
Coordinator to manage distributed actions implementing SAGA pattern
+
 | link:fhir/readme.adoc[Fhir] (fhir) | Health Care | An example showing how to 
work with Camel, FHIR and Spring Boot
 
 | link:fhir-auth-tx/readme.adoc[Fhir Auth Tx] (fhir-auth-tx) | Health Care | 
An example showing how to work with Camel, FHIR Authorization, FHIR Transaction 
and Spring Boot
diff --git a/pom.xml b/pom.xml
index f919ded..343e60c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,6 +77,7 @@
                <module>routetemplate-xml</module>
                <module>route-reload</module>
                <module>routes-configuration</module>
+               <module>saga</module>
                <module>servicecall</module>
                <module>supervising-route-controller</module>
                <module>twitter-salesforce</module>
diff --git a/saga/doc-resources/compesate-diagram.png 
b/saga/doc-resources/compesate-diagram.png
new file mode 100644
index 0000000..6ea7633
Binary files /dev/null and b/saga/doc-resources/compesate-diagram.png differ
diff --git a/saga/doc-resources/logic-diagram.png 
b/saga/doc-resources/logic-diagram.png
new file mode 100644
index 0000000..30996ec
Binary files /dev/null and b/saga/doc-resources/logic-diagram.png differ
diff --git a/saga/doc-resources/tech-diagram.png 
b/saga/doc-resources/tech-diagram.png
new file mode 100644
index 0000000..1ae6c06
Binary files /dev/null and b/saga/doc-resources/tech-diagram.png differ
diff --git a/saga/install-ocp-ephemeral.sh b/saga/install-ocp-ephemeral.sh
new file mode 100755
index 0000000..50d9812
--- /dev/null
+++ b/saga/install-ocp-ephemeral.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+echo creating amq-broker instance
+oc create -f ocp-resources/amq-broker-ephemeral.yaml
+
+echo creating lra-coordinator instance
+oc create -f ocp-resources/lra-coordinator-ephemeral.yaml
+
+echo deploying services
+mvn clean package -Popenshift
diff --git a/saga/install-ocp.sh b/saga/install-ocp.sh
new file mode 100755
index 0000000..ee577c2
--- /dev/null
+++ b/saga/install-ocp.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+echo creating amq-broker instance
+oc create -f ocp-resources/amq-broker.yaml
+
+echo creating lra-coordinator instance
+oc create -f ocp-resources/lra-coordinator.yaml
+
+echo deploying services
+mvn clean package -Popenshift
diff --git a/saga/local-resources/docker-compose.yml 
b/saga/local-resources/docker-compose.yml
new file mode 100644
index 0000000..c5842e6
--- /dev/null
+++ b/saga/local-resources/docker-compose.yml
@@ -0,0 +1,14 @@
+version: "3.9"
+services:
+  lra-coordinator:
+    image: "docker.io/jbosstm/lra-coordinator:latest"
+    network_mode: "host"
+  amq-broker:
+    image: "registry.redhat.io/amq7/amq-broker-rhel8:7.10"
+    environment:
+      - AMQ_USER=admin
+      - AMQ_PASSWORD=admin
+      - AMQ_REQUIRE_LOGIN=true
+    ports:
+      - "8161:8161"
+      - "61616:61616"
diff --git a/saga/ocp-resources/amq-broker-ephemeral.yaml 
b/saga/ocp-resources/amq-broker-ephemeral.yaml
new file mode 100644
index 0000000..0bf8f54
--- /dev/null
+++ b/saga/ocp-resources/amq-broker-ephemeral.yaml
@@ -0,0 +1,116 @@
+apiVersion: apps.openshift.io/v1
+kind: List
+items:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: amq-broker
+      csbexample: saga
+    name: amq-broker
+  spec:
+    ports:
+    - name: amq-broker-console
+      port: 8161
+      protocol: TCP
+      targetPort: 8161
+    - name: amq-broker
+      port: 61616
+      protocol: TCP
+      targetPort: 61616
+    selector:
+      app: amq-broker
+      deploymentconfig: amq-broker
+    type: ClusterIP
+- apiVersion: image.openshift.io/v1
+  kind: ImageStream
+  metadata:
+    labels:
+      app: amq-broker
+      csbexample: saga
+    name: amq-broker
+  spec:
+    lookupPolicy:
+      local: true
+    tags:
+    - from:
+        kind: DockerImage
+        name: registry.redhat.io/amq7/amq-broker-rhel8:7.10
+      generation: 0
+      importPolicy: {}
+      name: "latest"
+      referencePolicy:
+        type: Source
+- apiVersion: apps.openshift.io/v1
+  kind: DeploymentConfig
+  metadata:
+    generation: 1
+    labels:
+      app: amq-broker
+      csbexample: saga
+    name: amq-broker
+  spec:
+    replicas: 1
+    selector:
+      app: amq-broker
+      deploymentconfig: amq-broker
+    strategy:
+      type: Recreate
+    template:
+      metadata:
+        labels:
+          app: amq-broker
+          csbexample: saga
+          deploymentconfig: amq-broker
+      spec:
+        containers:
+        - imagePullPolicy: IfNotPresent
+          image: "amq-broker:latest"
+          env:
+            - name: AMQ_USER
+              value: admin
+            - name: AMQ_PASSWORD
+              value: admin
+            - name: AMQ_REQUIRE_LOGIN
+              value: "true"
+          livenessProbe:
+            httpGet:
+              path: /
+              port: 8161
+              scheme: HTTP
+            initialDelaySeconds: 180
+          name: amq-broker
+          ports:
+          - containerPort: 8161
+            protocol: TCP
+          - containerPort: 61616
+            protocol: TCP
+          readinessProbe:
+            httpGet:
+              path: /
+              port: 8161
+              scheme: HTTP
+            initialDelaySeconds: 10
+    triggers:
+    - type: ConfigChange
+    - imageChangeParams:
+        automatic: true
+        containerNames:
+        - amq-broker
+        from:
+          kind: ImageStreamTag
+          name: "amq-broker:latest"
+      type: ImageChange
+- kind: Route
+  apiVersion: route.openshift.io/v1
+  metadata:
+    name: amq-broker-console
+    labels:
+      app: amq-broker
+      csbexample: saga
+  spec:
+    to:
+      kind: Service
+      name: amq-broker
+    port:
+      targetPort: amq-broker-console
diff --git a/saga/ocp-resources/amq-broker.yaml 
b/saga/ocp-resources/amq-broker.yaml
new file mode 100644
index 0000000..4bba17d
--- /dev/null
+++ b/saga/ocp-resources/amq-broker.yaml
@@ -0,0 +1,138 @@
+apiVersion: apps.openshift.io/v1
+kind: List
+items:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: amq-broker
+      csbexample: saga
+    name: amq-broker
+  spec:
+    ports:
+    - name: amq-broker-console
+      port: 8161
+      protocol: TCP
+      targetPort: 8161
+    - name: amq-broker
+      port: 61616
+      protocol: TCP
+      targetPort: 61616
+    selector:
+      app: amq-broker
+      deploymentconfig: amq-broker
+    type: ClusterIP
+- apiVersion: v1
+  kind: PersistentVolumeClaim
+  metadata:
+    labels:
+      app: amq-broker
+      csbexample: saga
+    name: amq-broker
+  spec:
+    accessModes:
+    - ReadWriteMany
+    resources:
+      requests:
+        storage: 600Mi
+- apiVersion: image.openshift.io/v1
+  kind: ImageStream
+  metadata:
+    labels:
+      app: amq-broker
+      csbexample: saga
+    name: amq-broker
+  spec:
+    lookupPolicy:
+      local: true
+    tags:
+    - from:
+        kind: DockerImage
+        name: registry.redhat.io/amq7/amq-broker-rhel8:7.10
+      generation: 0
+      importPolicy: {}
+      name: "latest"
+      referencePolicy:
+        type: Source
+- apiVersion: apps.openshift.io/v1
+  kind: DeploymentConfig
+  metadata:
+    generation: 1
+    labels:
+      app: amq-broker
+      csbexample: saga
+    name: amq-broker
+  spec:
+    replicas: 1
+    selector:
+      app: amq-broker
+      deploymentconfig: amq-broker
+    strategy:
+      type: Recreate
+    template:
+      metadata:
+        labels:
+          app: amq-broker
+          csbexample: saga
+          deploymentconfig: amq-broker
+      spec:
+        containers:
+        - imagePullPolicy: IfNotPresent
+          image: "amq-broker:latest"
+          env:
+            - name: AMQ_USER
+              value: admin
+            - name: AMQ_PASSWORD
+              value: admin
+            - name: AMQ_REQUIRE_LOGIN
+              value: "true"
+            - name: AMQ_DATA_DIR
+              value: /data
+          livenessProbe:
+            httpGet:
+              path: /
+              port: 8161
+              scheme: HTTP
+            initialDelaySeconds: 180
+          name: amq-broker
+          ports:
+          - containerPort: 8161
+            protocol: TCP
+          - containerPort: 61616
+            protocol: TCP
+          readinessProbe:
+            httpGet:
+              path: /
+              port: 8161
+              scheme: HTTP
+            initialDelaySeconds: 10
+          volumeMounts:
+          - mountPath: /data
+            name: amq-broker-data
+        volumes:
+        - name: amq-broker-data
+          persistentVolumeClaim:
+            claimName: amq-broker
+    triggers:
+    - type: ConfigChange
+    - imageChangeParams:
+        automatic: true
+        containerNames:
+        - amq-broker
+        from:
+          kind: ImageStreamTag
+          name: "amq-broker:latest"
+      type: ImageChange
+- kind: Route
+  apiVersion: route.openshift.io/v1
+  metadata:
+    name: amq-broker-console
+    labels:
+      app: amq-broker
+      csbexample: saga
+  spec:
+    to:
+      kind: Service
+      name: amq-broker
+    port:
+      targetPort: amq-broker-console
diff --git a/saga/ocp-resources/lra-coordinator-ephemeral.yaml 
b/saga/ocp-resources/lra-coordinator-ephemeral.yaml
new file mode 100644
index 0000000..195edd0
--- /dev/null
+++ b/saga/ocp-resources/lra-coordinator-ephemeral.yaml
@@ -0,0 +1,92 @@
+apiVersion: apps.openshift.io/v1
+kind: List
+items:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: lra-coordinator
+      csbexample: saga
+    name: lra-coordinator
+  spec:
+    ports:
+    - name: 8080-tcp
+      port: 8080
+      protocol: TCP
+      targetPort: 8080
+    selector:
+      app: lra-coordinator
+      deploymentconfig: lra-coordinator
+    type: ClusterIP
+- apiVersion: image.openshift.io/v1
+  kind: ImageStream
+  metadata:
+    labels:
+      app: lra-coordinator
+      csbexample: saga
+    name: lra-coordinator
+  spec:
+    lookupPolicy:
+      local: true
+    tags:
+    - from:
+        kind: DockerImage
+        name: docker.io/jbosstm/lra-coordinator:latest
+      generation: 0
+      importPolicy: {}
+      name: "latest"
+      referencePolicy:
+        type: Source
+- apiVersion: apps.openshift.io/v1
+  kind: DeploymentConfig
+  metadata:
+    generation: 1
+    labels:
+      app: lra-coordinator
+      csbexample: saga
+    name: lra-coordinator
+  spec:
+    replicas: 1
+    selector:
+      app: lra-coordinator
+      deploymentconfig: lra-coordinator
+    strategy:
+      type: Recreate
+    template:
+      metadata:
+        labels:
+          app: lra-coordinator
+          csbexample: saga
+          deploymentconfig: lra-coordinator
+      spec:
+        containers:
+        - imagePullPolicy: IfNotPresent
+          env:
+          - name: AB_JOLOKIA_OFF
+            value: "true"
+          livenessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 180
+          name: lra-coordinator
+          ports:
+          - containerPort: 8080
+            protocol: TCP
+          readinessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 10
+    triggers:
+    - type: ConfigChange
+    - imageChangeParams:
+        automatic: true
+        containerNames:
+        - lra-coordinator
+        from:
+          kind: ImageStreamTag
+          name: "lra-coordinator:latest"
+      type: ImageChange
diff --git a/saga/ocp-resources/lra-coordinator.yaml 
b/saga/ocp-resources/lra-coordinator.yaml
new file mode 100644
index 0000000..75582fc
--- /dev/null
+++ b/saga/ocp-resources/lra-coordinator.yaml
@@ -0,0 +1,112 @@
+apiVersion: apps.openshift.io/v1
+kind: List
+items:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: lra-coordinator
+      csbexample: saga
+    name: lra-coordinator
+  spec:
+    ports:
+    - name: 8080-tcp
+      port: 8080
+      protocol: TCP
+      targetPort: 8080
+    selector:
+      app: lra-coordinator
+      deploymentconfig: lra-coordinator
+    type: ClusterIP
+- apiVersion: v1
+  kind: PersistentVolumeClaim
+  metadata:
+    labels:
+      app: lra-coordinator
+      csbexample: saga
+    name: lra-coordinator
+  spec:
+    accessModes:
+    - ReadWriteMany
+    resources:
+      requests:
+        storage: 200Mi
+- apiVersion: image.openshift.io/v1
+  kind: ImageStream
+  metadata:
+    labels:
+      app: lra-coordinator
+      csbexample: saga
+    name: lra-coordinator
+  spec:
+    lookupPolicy:
+      local: true
+    tags:
+    - from:
+        kind: DockerImage
+        name: docker.io/jbosstm/lra-coordinator:latest
+      generation: 0
+      importPolicy: {}
+      name: "latest"
+      referencePolicy:
+        type: Source
+- apiVersion: apps.openshift.io/v1
+  kind: DeploymentConfig
+  metadata:
+    generation: 1
+    labels:
+      app: lra-coordinator
+      csbexample: saga
+    name: lra-coordinator
+  spec:
+    replicas: 1
+    selector:
+      app: lra-coordinator
+      deploymentconfig: lra-coordinator
+    strategy:
+      type: Recreate
+    template:
+      metadata:
+        labels:
+          app: lra-coordinator
+          csbexample: saga
+          deploymentconfig: lra-coordinator
+      spec:
+        containers:
+        - imagePullPolicy: IfNotPresent
+          env:
+          - name: AB_JOLOKIA_OFF
+            value: "true"
+          livenessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 180
+          name: lra-coordinator
+          ports:
+          - containerPort: 8080
+            protocol: TCP
+          readinessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 10
+          volumeMounts:
+          - mountPath: /data
+            name: lra-coordinator-data
+        volumes:
+        - name: lra-coordinator-data
+          persistentVolumeClaim:
+            claimName: lra-coordinator
+    triggers:
+    - type: ConfigChange
+    - imageChangeParams:
+        automatic: true
+        containerNames:
+        - lra-coordinator
+        from:
+          kind: ImageStreamTag
+          name: "lra-coordinator:latest"
+      type: ImageChange
diff --git a/saga/pom.xml b/saga/pom.xml
new file mode 100644
index 0000000..8a65367
--- /dev/null
+++ b/saga/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel.springboot.example</groupId>
+        <artifactId>examples</artifactId>
+        <version>3.18.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-example-spring-boot-saga</artifactId>
+    <name>Camel SB Examples :: Saga</name>
+    <description>This example shows how to work with a simple Apache Camel 
application using Spring Boot and Narayana LRA Coordinator to manage 
distributed actions implementing SAGA pattern</description>
+    <packaging>pom</packaging>
+
+    <properties>
+        <category>EIP</category>
+
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        
<jkube.generator.from>registry.access.redhat.com/ubi8/openjdk-11</jkube.generator.from>
+    </properties>
+
+    <modules>
+        <module>saga-app</module>
+        <module>saga-flight-service</module>
+        <module>saga-payment-service</module>
+        <module>saga-train-service</module>
+    </modules>
+
+    <dependencyManagement>
+
+        <dependencies>
+            <!-- Spring Boot BOM -->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot-version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- Camel BOM -->
+            <dependency>
+                <groupId>org.apache.camel.springboot</groupId>
+                <artifactId>camel-spring-boot-bom</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+
+    </dependencyManagement>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-undertow-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-servlet-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-activemq-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-timer-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-lra-starter</artifactId>
+        </dependency>
+
+        <!-- Camel -->
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- test -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-spring-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/saga/readme.adoc b/saga/readme.adoc
new file mode 100644
index 0000000..7d0fbe4
--- /dev/null
+++ b/saga/readme.adoc
@@ -0,0 +1,207 @@
+== Spring Boot and SAGA EIP Example
+
+This example shows how to work with Apache Camel Saga using Spring Boot and 
Narayana LRA Coordinator to manage long running actions
+
+=== How it works
+
+There are 4 services as participants of the Saga:
+
+- payment-service: it emulates a real payment transaction and it will be used 
by both flight-service and train-service
+- flight-service: it emulates the booking of a flight ticket and it uses the 
payment-service to execute a payment transaction
+- train-service: it emulates the reservation of a train seat and it uses the 
payment-service to execute a payment transaction
+- app: is the starting point and it emulates a user that starts the 
transaction to buy both flight and train tickets
+
+The starting point is a REST endpoint that creates a request for a new 
reservation
+and there is 15% probability that the payment service fails.
+
+==== Logical view
+
+image::doc-resources/logic-diagram.png[]
+
+==== Compensating a failure
+
+image::doc-resources/compesate-diagram.png[]
+
+==== Technical view
+
+image::doc-resources/tech-diagram.png[]
+
+The communication between services and LRA coordinator (blue connectors) is 
via HTTP protocol,
+so every service expose REST endpoints called by the LRA, moreover it calls 
LRA via REST endpoint
+
+The communication between services (red connectors) is via AMQ broker (using 
OPENWIRE protocol),
+implemented using Camel ActiveMQ component and RequestReply EIP
+obtaining a synchronous behavior using asynchronous protocol
+
+==== Analyzing logs
+
+In the logs there will be all the messages about the execution of the service.
+
+First the app starts the saga LRA, passing the id to the entry point REST
+
+[source,shell]
+----
+curl -X POST http://localhost:8084/api/saga?id=1
+----
+
+in the log
+
+[source]
+----
+Executing saga #1 with LRA 
http://localhost:8080/lra-coordinator/0_ffff7f000001_8aad_62d16f11_2
+----
+
+where the URL contains the id of the LRA and the number of the saga is the 
value of the parameter passed to the rest in the starting point
+
+We're expecting that if the payment is ok, the message in the payment service 
will be:
+
+[source]
+----
+Paying train for order #1
+
+Payment train done for order #1 with payment transaction xxxxx
+
+Payment flight done for order #1 with payment transaction xxxxx
+----
+
+the value of the payment transaction is the `JMSCorrelationID` used in the 
RequestReply EIP in the payment service
+
+If the random failure occurs, the log in the payment service will be
+
+[source]
+----
+Payment flight for saga #65 fails!
+
+Payment for order #65 has been cancelled
+----
+
+It means that the compensation for the payment has been called, so we expect 
that in the flight service there will be a log
+
+[source]
+----
+Flight purchase #65 has been cancelled due to payment failure
+----
+
+in the train service
+
+[source]
+----
+Train purchase #65 has been cancelled due to payment failure
+----
+
+in the app
+
+[source]
+----
+Transaction 
http://localhost:8080/lra-coordinator/0_ffff7f000001_8aad_62d16f11_74 has been 
cancelled due to flight or train failure
+----
+
+
+=== Running on Openshift cluster
+
+==== Requirements
+
+ - `oc` client installed 
(https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html[guide])
+ - already logged in into cluster (running `oc login`)
+ - destination project already created (running `oc new-project my-project`)
+
+==== Run installation script
+
+[source,shell]
+----
+# if the cluster is enabled to create Persistent Volume Claims
+./install-ocp.sh
+
+# otherwise in ephemeral mode
+./install-ocp-ephemeral.sh
+----
+
+===== Red Hat Developer Sandbox usage example
+
+Go to https://developers.redhat.com/developer-sandbox/get-started after login, 
click on `Start using your sandbox` button.
+
+Then login into the Openshift and copy the command login clicking on the link 
`Copy Login Command` in the OpenShift console (the command will be something 
similar to `oc login --token=sha256~xxxx 
--server=https://api.sandbox-xxxx.openshiftapps.com:6443`).
+
+Run that command on the terminal and then run the installation script 
`./install-ocp-ephemeral.sh`
+
+===== Check OCP generated resources
+
+it will generate all the necessary PODs:
+
+ - amq-broker
+ - lra-coordinator
+ - camel-example-spring-boot-saga-app
+ - camel-example-spring-boot-saga-flight
+ - camel-example-spring-boot-saga-payment
+ - camel-example-spring-boot-saga-train
+
+wait for all the pods to be ready:
+
+[source,shell]
+----
+# all running pods
+oc get pods -l csbexample=saga
+
+# only services
+oc get pods -l csbexample=saga -l provider=jkube
+----
+
+tail logs of the application:
+
+[source,shell]
+----
+oc logs -f deploymentconfig/camel-example-spring-boot-saga-payment
+----
+
+=== Running on local environment
+
+==== Requirements
+
+- `docker-compose` installed (https://docs.docker.com/compose/install/[guide])
+
+==== Run script to execute services locally
+
+[source,shell]
+----
+./run-local.sh
+----
+
+It will generate all the necessary Docker containers and java processes, logs 
are stored in the `.log` files, and process id in the `.pid` files
+
+==== Run script to stop services locally
+
+[source,shell]
+----
+./stop-local.sh
+----
+
+This command will kill the running processes, remove the PID files and stop 
the containers; the log files will be left
+
+=== Additional info
+
+https://github.com/nicolaferraro/camel-saga-quickstart[Based on quickstart]
+
+https://camel.apache.org/components/latest/eips/saga-eip.html[Camel Saga EIP]
+
+https://www.narayana.io/lra/index.html[Narayana LRA project]
+
+https://download.eclipse.org/microprofile/microprofile-lra-1.0/microprofile-lra-spec-1.0.html[Microprofile
 LRA specification]
+
+https://camel.apache.org/components/latest/activemq-component.html[Camel 
ActiveMQ component]
+
+https://camel.apache.org/components/latest/eips/requestReply-eip.html[Camel 
RequestReply EIP]
+
+=== Using Camel components
+
+Apache Camel provides 200+ components which you can use to integrate and route 
messages between many systems
+and data formats. To use any of these Camel components, add the component as a 
dependency to your project.
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/support.html[let us know].
+
+We also love contributors, so
+https://camel.apache.org/contributing.html[get involved] :-)
+
+The Camel riders!
diff --git a/saga/run-local.sh b/saga/run-local.sh
new file mode 100755
index 0000000..6a3e8fa
--- /dev/null
+++ b/saga/run-local.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+echo running amq broker and lra-coordinator
+docker-compose -f local-resources/docker-compose.yml up -d
+
+echo compiling project
+mvn clean package
+
+echo running payment service
+java -Dserver.port=8081 -jar saga-payment-service/target/*.jar > payment.log 
2>&1 &
+echo "$!" > payment.pid
+
+echo running flight service
+java -Dserver.port=8082 -jar saga-flight-service/target/*.jar > flight.log 
2>&1 &
+echo "$!" > flight.pid
+
+echo running train service
+java -Dserver.port=8083 -jar saga-train-service/target/*.jar > train.log 2>&1 &
+echo "$!" > train.pid
+
+echo running saga application
+java -Dserver.port=8084 -jar saga-app/target/*.jar > app.log 2>&1 &
+echo "$!" > app.pid
diff --git a/saga/saga-app/pom.xml b/saga/saga-app/pom.xml
new file mode 100644
index 0000000..c1c7238
--- /dev/null
+++ b/saga/saga-app/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               <artifactId>camel-example-spring-boot-saga</artifactId>
+               <version>3.18.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-saga-app</artifactId>
+       <name>Camel SB Examples :: Saga :: App</name>
+       <description>Main application starting SAGA</description>
+
+       <properties>
+               <category>EIP</category>
+
+               
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+       </properties>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <profiles>
+               <profile>
+                       <id>openshift</id>
+                       <activation>
+                               <property>
+                                       <name>openshift</name>
+                               </property>
+                       </activation>
+                       <build>
+                               <plugins>
+                                       <plugin>
+                                               
<artifactId>openshift-maven-plugin</artifactId>
+                                               
<groupId>org.eclipse.jkube</groupId>
+                                               <executions>
+                                                       <execution>
+                                                               <goals>
+                                                                       
<goal>resource</goal>
+                                                                       
<goal>build</goal>
+                                                                       
<goal>deploy</goal>
+                                                               </goals>
+                                                       </execution>
+                                               </executions>
+                                               <configuration>
+                                                       <resources>
+                                                               <labels>
+                                                                       <all>
+                                                                               
<property>
+                                                                               
        <name>csbexample</name>
+                                                                               
        <value>saga</value>
+                                                                               
</property>
+                                                                       </all>
+                                                               </labels>
+                                                       </resources>
+                                               </configuration>
+                                       </plugin>
+                               </plugins>
+                       </build>
+               </profile>
+       </profiles>
+
+</project>
diff --git 
a/saga/saga-app/src/main/java/org/apache/camel/example/saga/CamelSagaApplication.java
 
b/saga/saga-app/src/main/java/org/apache/camel/example/saga/CamelSagaApplication.java
new file mode 100644
index 0000000..80841b0
--- /dev/null
+++ 
b/saga/saga-app/src/main/java/org/apache/camel/example/saga/CamelSagaApplication.java
@@ -0,0 +1,39 @@
+/*
+ * 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.example.saga;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
+
+//CHECKSTYLE:OFF
+@SpringBootApplication
+@EnableAutoConfiguration(exclude = {
+        ArtemisAutoConfiguration.class,
+        JmsAutoConfiguration.class,
+        ActiveMQAutoConfiguration.class
+})
+public class CamelSagaApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(CamelSagaApplication.class, args);
+    }
+}
+// CHECKSTYLE:ON
diff --git 
a/saga/saga-app/src/main/java/org/apache/camel/example/saga/SagaRoute.java 
b/saga/saga-app/src/main/java/org/apache/camel/example/saga/SagaRoute.java
new file mode 100644
index 0000000..2f352b3
--- /dev/null
+++ b/saga/saga-app/src/main/java/org/apache/camel/example/saga/SagaRoute.java
@@ -0,0 +1,56 @@
+/*
+ * 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.example.saga;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaDefinition;
+import org.apache.camel.model.rest.RestParamType;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class SagaRoute extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+
+        rest().post("/saga")
+                
.param().type(RestParamType.query).name("id").dataType("int").required(true).endParam()
+                .to("direct:saga");
+
+        from("direct:saga")
+                .saga()
+                .compensation("direct:cancelOrder")
+                    .log("Executing saga #${header.id} with LRA 
${header.Long-Running-Action}")
+                    .setHeader("payFor", constant("train"))
+                    
.to("activemq:queue:{{example.services.train}}?exchangePattern=InOut" +
+                            "&replyTo={{example.services.train}}.reply")
+                    .log("train seat reserved for saga #${header.id} with 
payment transaction: ${body}")
+                    .setHeader("payFor", constant("flight"))
+                    
.to("activemq:queue:{{example.services.flight}}?exchangePattern=InOut" +
+                            "&replyTo={{example.services.flight}}.reply")
+                    .log("flight booked for saga #${header.id} with payment 
transaction: ${body}")
+                .setBody(header("Long-Running-Action"))
+                .end();
+
+        from("direct:cancelOrder")
+                .log("Transaction ${header.Long-Running-Action} has been 
cancelled due to flight or train failure");
+
+    }
+
+}
diff --git a/saga/saga-app/src/main/jkube/deployment.yml 
b/saga/saga-app/src/main/jkube/deployment.yml
new file mode 100644
index 0000000..addb54d
--- /dev/null
+++ b/saga/saga-app/src/main/jkube/deployment.yml
@@ -0,0 +1,11 @@
+spec:
+  template:
+    spec:
+      containers:
+        - env:
+            - name: CAMEL_LRA_COORDINATOR_URL
+              value: http://lra-coordinator:8080
+            - name: CAMEL_LRA_LOCAL_PARTICIPANT_URL
+              value: http://${project.artifactId}:8080/api
+            - name: CAMEL_COMPONENT_ACTIVEMQ_BROKER-URL
+              value: tcp://amq-broker:61616
diff --git a/saga/saga-app/src/main/resources/application.yml 
b/saga/saga-app/src/main/resources/application.yml
new file mode 100644
index 0000000..57b79ac
--- /dev/null
+++ b/saga/saga-app/src/main/resources/application.yml
@@ -0,0 +1,51 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+camel:
+  servlet:
+    mapping:
+      enabled: true
+      context-path: /api/*
+  component:
+    activemq:
+      use-pooled-connection: true
+      test-connection-on-startup: true
+      password: admin
+      username: admin
+      broker-url: tcp://localhost:61616
+      concurrent-consumers: 5
+  lra:
+    enabled: true
+    coordinator-url: http://localhost:8080
+    local-participant-url: http://localhost:${server.port}/api
+  service:
+    lra.enabled: true
+  springboot:
+    main-run-controller: true
+    name: Camel-saga
+example.services:
+  train: saga-train-service
+  flight: saga-flight-service
+logging:
+  level:
+    root: INFO
+    org.apache.camel: INFO
+    org.apache.camel.processor.errorhandler.DefaultErrorHandler: OFF
+    org.apache.camel.component.jms.EndpointMessageListener: OFF
+    org.apache.camel.component.jms.reply.QueueReplyManager: OFF
+    org.apache.camel.component.timer.TimerConsumer: OFF
+
diff --git a/saga/saga-flight-service/pom.xml b/saga/saga-flight-service/pom.xml
new file mode 100644
index 0000000..540a0f2
--- /dev/null
+++ b/saga/saga-flight-service/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               <artifactId>camel-example-spring-boot-saga</artifactId>
+               <version>3.18.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-saga-flight</artifactId>
+       <name>Camel SB Examples :: Saga :: Flight Service</name>
+       <description>Flight Service</description>
+
+       <properties>
+               <category>EIP</category>
+
+               
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+       </properties>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <profiles>
+               <profile>
+                       <id>openshift</id>
+                       <activation>
+                               <property>
+                                       <name>openshift</name>
+                               </property>
+                       </activation>
+                       <build>
+                               <plugins>
+                                       <plugin>
+                                               
<artifactId>openshift-maven-plugin</artifactId>
+                                               
<groupId>org.eclipse.jkube</groupId>
+                                               <executions>
+                                                       <execution>
+                                                               <goals>
+                                                                       
<goal>resource</goal>
+                                                                       
<goal>build</goal>
+                                                                       
<goal>deploy</goal>
+                                                               </goals>
+                                                       </execution>
+                                               </executions>
+                                               <configuration>
+                                                       <resources>
+                                                               <labels>
+                                                                       <all>
+                                                                               
<property>
+                                                                               
        <name>csbexample</name>
+                                                                               
        <value>saga</value>
+                                                                               
</property>
+                                                                       </all>
+                                                               </labels>
+                                                       </resources>
+                                               </configuration>
+                                       </plugin>
+                               </plugins>
+                       </build>
+               </profile>
+       </profiles>
+
+</project>
diff --git 
a/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/CamelSagaFlightService.java
 
b/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/CamelSagaFlightService.java
new file mode 100644
index 0000000..9eab5e2
--- /dev/null
+++ 
b/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/CamelSagaFlightService.java
@@ -0,0 +1,23 @@
+package org.apache.camel.example.saga;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
+
+//CHECKSTYLE:OFF
+@SpringBootApplication
+@EnableAutoConfiguration(exclude = {
+        ArtemisAutoConfiguration.class,
+        JmsAutoConfiguration.class,
+        ActiveMQAutoConfiguration.class
+})
+public class CamelSagaFlightService {
+
+    public static void main(String[] args) {
+        SpringApplication.run(CamelSagaFlightService.class, args);
+    }
+}
+// CHECKSTYLE:ON
diff --git 
a/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/FlightRoute.java
 
b/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/FlightRoute.java
new file mode 100644
index 0000000..27f9abc
--- /dev/null
+++ 
b/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/FlightRoute.java
@@ -0,0 +1,44 @@
+/*
+ * 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.example.saga;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class FlightRoute extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        from("activemq:queue:{{example.services.flight}}")
+            .saga()
+                .propagation(SagaPropagation.MANDATORY)
+                .option("id", header("id"))
+                .compensation("direct:cancelPurchase")
+                .log("Buying flight #${header.id}")
+                
.to("activemq:queue:{{example.services.payment}}?exchangePattern=InOut" +
+                        "&replyTo={{example.services.payment}}.flight.reply")
+                .log("Payment for flight #${header.id} done with transaction 
${body}")
+            .end();
+
+        from("direct:cancelPurchase")
+                .log("Flight purchase #${header.id} has been cancelled due to 
payment failure");
+    }
+
+}
diff --git a/saga/saga-flight-service/src/main/jkube/deployment.yml 
b/saga/saga-flight-service/src/main/jkube/deployment.yml
new file mode 100644
index 0000000..addb54d
--- /dev/null
+++ b/saga/saga-flight-service/src/main/jkube/deployment.yml
@@ -0,0 +1,11 @@
+spec:
+  template:
+    spec:
+      containers:
+        - env:
+            - name: CAMEL_LRA_COORDINATOR_URL
+              value: http://lra-coordinator:8080
+            - name: CAMEL_LRA_LOCAL_PARTICIPANT_URL
+              value: http://${project.artifactId}:8080/api
+            - name: CAMEL_COMPONENT_ACTIVEMQ_BROKER-URL
+              value: tcp://amq-broker:61616
diff --git a/saga/saga-flight-service/src/main/resources/application.yml 
b/saga/saga-flight-service/src/main/resources/application.yml
new file mode 100644
index 0000000..22fded3
--- /dev/null
+++ b/saga/saga-flight-service/src/main/resources/application.yml
@@ -0,0 +1,49 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+camel:
+  servlet:
+    mapping:
+      context-path: /api/*
+  component:
+    activemq:
+      use-pooled-connection: true
+      test-connection-on-startup: true
+      password: admin
+      username: admin
+      broker-url: tcp://localhost:61616
+      concurrent-consumers: 5
+  lra:
+    enabled: true
+    coordinator-url: http://localhost:8080
+    local-participant-url: http://localhost:${server.port}/api
+  service:
+    lra.enabled: true
+  springboot:
+    main-run-controller: true
+    name: Camel-flight
+example.services:
+  flight: saga-flight-service
+  payment: saga-payment-service
+logging:
+  level:
+    root: INFO
+    org.apache.camel: INFO
+    org.apache.camel.processor.errorhandler.DefaultErrorHandler: OFF
+    org.apache.camel.component.jms.EndpointMessageListener: OFF
+    org.apache.camel.component.jms.reply.QueueReplyManager: OFF
+
diff --git a/saga/saga-payment-service/pom.xml 
b/saga/saga-payment-service/pom.xml
new file mode 100644
index 0000000..888d008
--- /dev/null
+++ b/saga/saga-payment-service/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               <artifactId>camel-example-spring-boot-saga</artifactId>
+               <version>3.18.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-saga-payment</artifactId>
+       <name>Camel SB Examples :: Saga :: Payment Service</name>
+       <description>Payment Service</description>
+
+       <properties>
+               <category>EIP</category>
+
+               
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+       </properties>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <profiles>
+               <profile>
+                       <id>openshift</id>
+                       <activation>
+                               <property>
+                                       <name>openshift</name>
+                               </property>
+                       </activation>
+                       <build>
+                               <plugins>
+                                       <plugin>
+                                               
<artifactId>openshift-maven-plugin</artifactId>
+                                               
<groupId>org.eclipse.jkube</groupId>
+                                               <executions>
+                                                       <execution>
+                                                               <goals>
+                                                                       
<goal>resource</goal>
+                                                                       
<goal>build</goal>
+                                                                       
<goal>deploy</goal>
+                                                               </goals>
+                                                       </execution>
+                                               </executions>
+                                               <configuration>
+                                                       <resources>
+                                                               <labels>
+                                                                       <all>
+                                                                               
<property>
+                                                                               
        <name>csbexample</name>
+                                                                               
        <value>saga</value>
+                                                                               
</property>
+                                                                       </all>
+                                                               </labels>
+                                                       </resources>
+                                               </configuration>
+                                       </plugin>
+                               </plugins>
+                       </build>
+               </profile>
+       </profiles>
+
+</project>
diff --git 
a/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/CamelSagaPaymentService.java
 
b/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/CamelSagaPaymentService.java
new file mode 100644
index 0000000..648734a
--- /dev/null
+++ 
b/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/CamelSagaPaymentService.java
@@ -0,0 +1,23 @@
+package org.apache.camel.example.saga;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
+
+//CHECKSTYLE:OFF
+@SpringBootApplication
+@EnableAutoConfiguration(exclude = {
+        ArtemisAutoConfiguration.class,
+        JmsAutoConfiguration.class,
+        ActiveMQAutoConfiguration.class
+})
+public class CamelSagaPaymentService {
+
+    public static void main(String[] args) {
+        SpringApplication.run(CamelSagaPaymentService.class, args);
+    }
+}
+// CHECKSTYLE:ON
diff --git 
a/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/PaymentRoute.java
 
b/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/PaymentRoute.java
new file mode 100644
index 0000000..0b9e1a1
--- /dev/null
+++ 
b/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/PaymentRoute.java
@@ -0,0 +1,51 @@
+/*
+ * 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.example.saga;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class PaymentRoute extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+
+                from("activemq:queue:{{example.services.payment}}")
+                .routeId("payment-service")
+                .saga()
+                    .propagation(SagaPropagation.MANDATORY)
+                    .option("id", header("id"))
+                    .compensation("direct:cancelPayment")
+                    .log("Paying ${header.payFor} for order #${header.id}")
+                    .setBody(header("JMSCorrelationID"))
+                    .choice()
+                        .when(x -> Math.random() >= 0.85)
+                            .log("Payment ${header.payFor} for saga 
#${header.id} fails!")
+                            .throwException(new RuntimeException("Random 
failure during payment"))
+                        .endChoice()
+                    .end()
+                    .log("Payment ${header.payFor} done for order 
#${header.id} with payment transaction ${body}")
+                .end();
+
+        from("direct:cancelPayment")
+                .routeId("payment-cancel")
+                .log("Payment for order #${header.id} has been cancelled");
+    }
+}
diff --git a/saga/saga-payment-service/src/main/jkube/deployment.yml 
b/saga/saga-payment-service/src/main/jkube/deployment.yml
new file mode 100644
index 0000000..addb54d
--- /dev/null
+++ b/saga/saga-payment-service/src/main/jkube/deployment.yml
@@ -0,0 +1,11 @@
+spec:
+  template:
+    spec:
+      containers:
+        - env:
+            - name: CAMEL_LRA_COORDINATOR_URL
+              value: http://lra-coordinator:8080
+            - name: CAMEL_LRA_LOCAL_PARTICIPANT_URL
+              value: http://${project.artifactId}:8080/api
+            - name: CAMEL_COMPONENT_ACTIVEMQ_BROKER-URL
+              value: tcp://amq-broker:61616
diff --git a/saga/saga-payment-service/src/main/resources/application.yml 
b/saga/saga-payment-service/src/main/resources/application.yml
new file mode 100644
index 0000000..e0fe7eb
--- /dev/null
+++ b/saga/saga-payment-service/src/main/resources/application.yml
@@ -0,0 +1,49 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+camel:
+  servlet:
+    mapping:
+      enabled: true
+      context-path: /api/*
+  component:
+    activemq:
+      use-pooled-connection: true
+      test-connection-on-startup: true
+      password: admin
+      username: admin
+      broker-url: tcp://localhost:61616
+      concurrent-consumers: 5
+  lra:
+    enabled: true
+    coordinator-url: http://localhost:8080
+    local-participant-url: http://localhost:${server.port}/api
+  service:
+    lra.enabled: true
+  springboot:
+    main-run-controller: true
+    name: Camel-payment
+example.services:
+  payment: saga-payment-service
+logging:
+  level:
+    root: INFO
+    org.apache.camel: INFO
+    org.apache.camel.processor.errorhandler.DefaultErrorHandler: OFF
+    org.apache.camel.component.jms.EndpointMessageListener: OFF
+    org.apache.camel.component.jms.reply.QueueReplyManager: OFF
+
diff --git a/saga/saga-train-service/pom.xml b/saga/saga-train-service/pom.xml
new file mode 100644
index 0000000..ba6e78f
--- /dev/null
+++ b/saga/saga-train-service/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               <artifactId>camel-example-spring-boot-saga</artifactId>
+               <version>3.18.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-saga-train</artifactId>
+       <name>Camel SB Examples :: Saga :: Train Service</name>
+       <description>Train Service</description>
+
+       <properties>
+               <category>EIP</category>
+
+               
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+       </properties>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <profiles>
+               <profile>
+                       <id>openshift</id>
+                       <activation>
+                               <property>
+                                       <name>openshift</name>
+                               </property>
+                       </activation>
+                       <build>
+                               <plugins>
+                                       <plugin>
+                                               
<artifactId>openshift-maven-plugin</artifactId>
+                                               
<groupId>org.eclipse.jkube</groupId>
+                                               <executions>
+                                                       <execution>
+                                                               <goals>
+                                                                       
<goal>resource</goal>
+                                                                       
<goal>build</goal>
+                                                                       
<goal>deploy</goal>
+                                                               </goals>
+                                                       </execution>
+                                               </executions>
+                                               <configuration>
+                                                       <resources>
+                                                               <labels>
+                                                                       <all>
+                                                                               
<property>
+                                                                               
        <name>csbexample</name>
+                                                                               
        <value>saga</value>
+                                                                               
</property>
+                                                                       </all>
+                                                               </labels>
+                                                       </resources>
+                                               </configuration>
+                                       </plugin>
+                               </plugins>
+                       </build>
+               </profile>
+       </profiles>
+
+</project>
diff --git 
a/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/CamelSagaTrainService.java
 
b/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/CamelSagaTrainService.java
new file mode 100644
index 0000000..5f0c7f3
--- /dev/null
+++ 
b/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/CamelSagaTrainService.java
@@ -0,0 +1,23 @@
+package org.apache.camel.example.saga;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
+import 
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
+
+//CHECKSTYLE:OFF
+@SpringBootApplication
+@EnableAutoConfiguration(exclude = {
+        ArtemisAutoConfiguration.class,
+        JmsAutoConfiguration.class,
+        ActiveMQAutoConfiguration.class
+})
+public class CamelSagaTrainService {
+
+    public static void main(String[] args) {
+        SpringApplication.run(CamelSagaTrainService.class, args);
+    }
+}
+// CHECKSTYLE:ON
diff --git 
a/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/TrainRoute.java
 
b/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/TrainRoute.java
new file mode 100644
index 0000000..2e5b20d
--- /dev/null
+++ 
b/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/TrainRoute.java
@@ -0,0 +1,44 @@
+/*
+ * 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.example.saga;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class TrainRoute extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        from("activemq:queue:{{example.services.train}}")
+            .saga()
+                .propagation(SagaPropagation.MANDATORY)
+                .option("id", header("id"))
+                .compensation("direct:cancelPurchase")
+                .log("Buying train #${header.id}")
+                
.to("activemq:queue:{{example.services.payment}}?exchangePattern=InOut" +
+                        "&replyTo={{example.services.payment}}.train.reply")
+                .log("Payment for train #${header.id} done with transaction 
${body}")
+            .end();
+
+        from("direct:cancelPurchase")
+                .log("Train purchase #${header.id} has been cancelled due to 
payment failure");
+    }
+
+}
diff --git a/saga/saga-train-service/src/main/jkube/deployment.yml 
b/saga/saga-train-service/src/main/jkube/deployment.yml
new file mode 100644
index 0000000..addb54d
--- /dev/null
+++ b/saga/saga-train-service/src/main/jkube/deployment.yml
@@ -0,0 +1,11 @@
+spec:
+  template:
+    spec:
+      containers:
+        - env:
+            - name: CAMEL_LRA_COORDINATOR_URL
+              value: http://lra-coordinator:8080
+            - name: CAMEL_LRA_LOCAL_PARTICIPANT_URL
+              value: http://${project.artifactId}:8080/api
+            - name: CAMEL_COMPONENT_ACTIVEMQ_BROKER-URL
+              value: tcp://amq-broker:61616
diff --git a/saga/saga-train-service/src/main/resources/application.yml 
b/saga/saga-train-service/src/main/resources/application.yml
new file mode 100644
index 0000000..b8ae5e5
--- /dev/null
+++ b/saga/saga-train-service/src/main/resources/application.yml
@@ -0,0 +1,49 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+camel:
+  servlet:
+    mapping:
+      context-path: /api/*
+  component:
+    activemq:
+      use-pooled-connection: true
+      test-connection-on-startup: true
+      password: admin
+      username: admin
+      broker-url: tcp://localhost:61616
+      concurrent-consumers: 5
+  lra:
+    enabled: true
+    coordinator-url: http://localhost:8080
+    local-participant-url: http://localhost:${server.port}/api
+  service:
+    lra.enabled: true
+  springboot:
+    main-run-controller: true
+    name: Camel-train
+example.services:
+  train: saga-train-service
+  payment: saga-payment-service
+logging:
+  level:
+    root: INFO
+    org.apache.camel: INFO
+    org.apache.camel.processor.errorhandler.DefaultErrorHandler: OFF
+    org.apache.camel.component.jms.EndpointMessageListener: OFF
+    org.apache.camel.component.jms.reply.QueueReplyManager: OFF
+
diff --git a/saga/stop-local.sh b/saga/stop-local.sh
new file mode 100755
index 0000000..3940650
--- /dev/null
+++ b/saga/stop-local.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+echo stopping saga application
+kill -9 $(cat app.pid) && rm app.pid
+
+echo stopping flight service
+kill -9 $(cat flight.pid) && rm flight.pid
+
+echo stopping train service
+kill -9 $(cat train.pid) && rm train.pid
+
+echo stopping payment service
+kill -9 $(cat payment.pid) && rm payment.pid
+
+echo stopping amq broker and lra-coordinator
+docker-compose -f local-resources/docker-compose.yml stop

Reply via email to