You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2019/12/13 08:23:12 UTC

[camel-k] 01/02: Update to add the saga example

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

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 08661fffdbfe6aab8cbb53e55dd5b37f80add0bf
Author: Amos Feng <zf...@redhat.com>
AuthorDate: Fri Nov 29 13:53:28 2019 +0800

    Update to add the saga example
---
 examples/saga/Flight.java          |  48 ++++++++++++++++
 examples/saga/Payment.java         |  51 +++++++++++++++++
 examples/saga/Readme.md            |  18 ++++++
 examples/saga/Saga.java            |  41 ++++++++++++++
 examples/saga/Train.java           |  48 ++++++++++++++++
 examples/saga/lra-coordinator.yaml | 111 +++++++++++++++++++++++++++++++++++++
 6 files changed, 317 insertions(+)

diff --git a/examples/saga/Flight.java b/examples/saga/Flight.java
new file mode 100644
index 0000000..0810c3c
--- /dev/null
+++ b/examples/saga/Flight.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Flight extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://flight:8080");
+		getContext().addService(service);
+
+		rest("/api").post("/flight/buy")
+			.param().type(RestParamType.header).name("id").required(true).endParam()
+			.route()
+			.saga()
+				.propagation(SagaPropagation.MANDATORY)
+				.option("id", header("id"))
+				.compensation("direct:cancelPurchase")
+			.log("Buying flight #${header.id}")
+			.to("http://payment:8080/api/pay?bridgeEndpoint=true&type=flight")
+			.log("Payment for flight #${header.id} done");
+
+		from("direct:cancelPurchase")
+			.log("Flight purchase #${header.id} has been cancelled");
+	}
+}
diff --git a/examples/saga/Payment.java b/examples/saga/Payment.java
new file mode 100644
index 0000000..a4a866b
--- /dev/null
+++ b/examples/saga/Payment.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.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Payment extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://payment:8080");
+		getContext().addService(service);
+
+		rest("/api/").post("/pay")
+                    .param().type(RestParamType.query).name("type").required(true).endParam()
+                    .param().type(RestParamType.header).name("id").required(true).endParam()
+                    .route()
+                    .saga()
+                        .propagation(SagaPropagation.MANDATORY)
+                        .option("id", header("id"))
+                        .compensation("direct:cancelPayment")
+                    .log("Paying ${header.type} for order #${header.id}")
+                    .choice()
+                        .when(x -> Math.random() >= 0.85)
+                            .throwException(new RuntimeException("Random failure during payment"))
+                    .end();
+
+                from("direct:cancelPayment")
+                    .log("Payment #${header.id} has been cancelled");
+	}
+}
diff --git a/examples/saga/Readme.md b/examples/saga/Readme.md
new file mode 100644
index 0000000..275524f
--- /dev/null
+++ b/examples/saga/Readme.md
@@ -0,0 +1,18 @@
+# Saga example
+This example is from [camel-saga-quickstart](https://github.com/nicolaferraro/camel-saga-quickstart/) and could work with the camel-k.
+
+* Start the lra-coordinator
+```
+oc create -f lra-coordinator.yaml
+```
+* Start the three demo services
+```
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Flight.java
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Train.java
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Payment.java
+```
+* Start the saga application
+```
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Saga.java
+```
+Then you can use ```kamel log saga``` to check the output of the transactions.
\ No newline at end of file
diff --git a/examples/saga/Saga.java b/examples/saga/Saga.java
new file mode 100644
index 0000000..ff127b5
--- /dev/null
+++ b/examples/saga/Saga.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Saga extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://saga:8080");
+		getContext().addService(service);
+
+		from("timer:clock?period=5s")
+			.saga()
+			.setHeader("id", header(Exchange.TIMER_COUNTER))
+			.setHeader(Exchange.HTTP_METHOD, constant("POST"))
+			.log("Executing saga #${header.id}")
+			.to("http://train:8080/api/train/buy/seat")
+			.to("http://flight:8080/api/flight/buy");
+
+	}
+}
diff --git a/examples/saga/Train.java b/examples/saga/Train.java
new file mode 100644
index 0000000..2c71fc5
--- /dev/null
+++ b/examples/saga/Train.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Train extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://train:8080");
+		getContext().addService(service);
+
+		rest("/api/").post("/train/buy/seat")
+                    .param().type(RestParamType.header).name("id").required(true).endParam()
+                    .route()
+                    .saga()
+                        .propagation(SagaPropagation.SUPPORTS)
+                        .option("id", header("id"))
+                        .compensation("direct:cancelPurchase")
+                    .log("Buying train seat #${header.id}")
+                    .to("http://payment:8080/api/pay?bridgeEndpoint=true&type=train")
+                    .log("Payment for train #${header.id} done");
+
+               from("direct:cancelPurchase")
+                    .log("Train purchase #${header.id} has been cancelled");
+	}
+}
diff --git a/examples/saga/lra-coordinator.yaml b/examples/saga/lra-coordinator.yaml
new file mode 100644
index 0000000..328879e
--- /dev/null
+++ b/examples/saga/lra-coordinator.yaml
@@ -0,0 +1,111 @@
+apiVersion: v1
+kind: List
+items:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    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
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    accessModes:
+    - ReadWriteOnce
+    resources:
+      requests:
+        storage: 200Mi
+- apiVersion: v1
+  kind: ImageStream
+  metadata:
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    lookupPolicy:
+      local: true
+    tags:
+    - from:
+        kind: DockerImage
+        name: docker.io/jbosstm/lra-coordinator:5.8.2.Final
+      generation: 0
+      importPolicy: {}
+      name: "5.8.2.Final"
+      referencePolicy:
+        type: Source
+- apiVersion: v1
+  kind: DeploymentConfig
+  metadata:
+    generation: 1
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    replicas: 1
+    selector:
+      app: lra-coordinator
+      deploymentconfig: lra-coordinator
+    strategy:
+      type: Recreate
+    template:
+      metadata:
+        labels:
+          app: lra-coordinator
+          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:5.8.2.Final"
+      type: ImageChange
\ No newline at end of file