WillemJiang closed pull request #289: [SCB-820] Demo of TCC model.
URL: https://github.com/apache/incubator-servicecomb-saga/pull/289
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/saga-demo/pom.xml b/saga-demo/pom.xml
index cff708a2..614dfa6d 100644
--- a/saga-demo/pom.xml
+++ b/saga-demo/pom.xml
@@ -35,6 +35,7 @@
<module>saga-servicecomb-demo</module>
<module>dependency-free-transaction-demo</module>
<module>conditional-transaction-demo</module>
+ <module>tcc-spring-demo</module>
</modules>
<dependencyManagement>
diff --git a/saga-demo/tcc-spring-demo/README.md
b/saga-demo/tcc-spring-demo/README.md
new file mode 100644
index 00000000..05024938
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/README.md
@@ -0,0 +1,145 @@
+# Booking Demo
+This demo simulates a booking application including three services:
+* booking
+* car
+* hotel
+
+## Prerequisites
+You will need:
+1. [JDK 1.8][jdk]
+2. [Maven 3.x][maven]
+3. [Docker][docker]
+4. [Docker compose][docker_compose]
+5. [alpha server][alpha_server]
+
+[jdk]:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
+[maven]: https://maven.apache.org/install.html
+[docker]: https://www.docker.com/get-docker
+[docker_compose]: https://docs.docker.com/compose/install/
+[alpha_server]:
https://github.com/apache/incubator-servicecomb-saga/tree/master/alpha
+
+## Running Demo
+You can run the demo using either docker compose or executable files.
+### via docker compose
+1. run the following command to create docker images in saga project root
folder.
+ ```
+ mvn clean package -DskipTests -Pdocker -Pdemo
+ ```
+
+2. start the whole application up(including alpha server and three demo
services)
+ ```
+ ./saga-demo.sh up
+ ```
+
+ **Note:** If you prefer to use MySQL as alpha's backend database, you need
to try the following steps instead:
+ 1. add dependency of `mysql-connector-java` in `alpha/alpha-server/pom.xml`
+ ```xml
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+ ```
+ 2. remove alpha server's docker image
+ ```bash
+ docker rmi -f $(docker images | grep alpha-server | awk '{print $3}')
+ ```
+ 3. re-generate saga's docker images
+ ```bash
+ mvn package -DskipTests -Pdocker -Pdemo
+ ```
+ 4. start application up in `saga-demo/booking` with the following command
+ ```
+ ./saga-demo.sh up-mysql
+ ```
+
+ **Note:** If you want start alpha server and demon services separately, you
can try the following steps:
+ 1. start alpha server
+ ```bash
+ ./saga-demo.sh up-alpha
+ ```
+ 2. when alpha server started complatelly, then start the demo services
+ ```bash
+ ./saga-demo.sh up-demo
+ ```
+
+3. stop application
+ ```
+ ./saga-demo.sh down
+ ```
+
+### via executable files
+1. run the following command to generate executable alpha server jar in
`alpha/alpha-server/target/saga/alpha-server-${saga_version}-exec.jar`.
+ ```
+ mvn clean package -DskipTests -Pdemo
+ ```
+
+2. follow the instructions in the [How to
run](https://github.com/apache/incubator-servicecomb-saga/blob/master/docs/user_guide.md#how-to-run)
section in User Guide to run postgreSQL and alpha server.
+
+3. start application up
+ 1. start hotel service. The executable jar file should be in
`saga-demo/booking/hotel/target/saga`.
+ ```bash
+ java -Dserver.port=8081 -Dalpha.cluster.address=${alpha_address}:8080 -jar
hotel-${saga_version}-exec.jar
+ ```
+
+ 2. start car service. The executable jar file should be in
`saga-demo/booking/car/target/saga`.
+ ```bash
+ java -Dserver.port=8082 -Dalpha.cluster.address=${alpha_address}:8080 -jar
car-${saga_version}-exec.jar
+ ```
+
+ 3. start booking service. The executable jar file should be in
`saga-demo/booking/booking/target/saga`.
+ ```bash
+ java -Dserver.port=8083 -Dalpha.cluster.address=${alpha_address}:8080
-Dcar.service.address=${host_address}:8082
-Dhotel.service.address=${host_address}:8081 -jar
booking-${saga_version}-exec.jar
+ ```
+
+## User Requests by command line tools
+1. Booking 2 rooms and 2 cars, this booking will be OK.
+```
+curl -X POST http://${host_address}:8083/booking/test/2/2
+```
+Check the hotel booking status with
+```
+curl http://${host_address}:8081/bookings
+```
+Check the car booking status with
+```
+curl http://${host_address}:8082/bookings
+
+```
+
+2. Booking 3 rooms and 2 cars, this booking will cause the hotel order failed
and trigger the compensate operation with car booking.
+```
+curl -X POST http://${host_address}:8083/booking/test/3/2
+```
+Check the hotel booking status with
+```
+curl http://${host_address}:8081/bookings
+```
+Check the car booking status with
+```
+curl http://${host_address}:8082/bookings
+```
+The second car booking will be marked with **cancel:true**
+
+## User Requests by html page
+
+Open a browser with URL http://127.0.0.1:8083, You will get a html page. You
can use this page to invoke test cases, and then get results.
+
+**Note** transactions and compensations implemented by services must be
idempotent.
+
+## Debugging
+
+To debug the services of the demo, just add debug parameter to JVM through the
environment field in docker-compose configs. Let's take alpha-server as an
example:
+
+```yaml
+alpha:
+ image: "alpha-server:${TAG}"
+ environment:
+ - JAVA_OPTS=-Dspring.profiles.active=prd
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
+ ports:
+ - "6006:5005"
+...
+```
+
+We append the debug parameter
`-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005` to the
JAVA_OPTS environment variable, the Java process inside the container will
listen on port 5005. With the port forwarding rule `6006:5005`, when
alpha-server is ready, we can connect to port 6006 on the host and start
debugging alpha-server.
+
+If you're using [IntelliJ](https://www.jetbrains.com/idea/), open the saga
project, create a new debug configuration with template 'Remote', fill "Host"
and "Port" input with "localhost" and "6006", then select "alpha" in the
drop-down list of "Use classpath of module". When alpha-server is running, hit
shift+f9 to debug the remote application.
diff --git a/saga-demo/tcc-spring-demo/docker-compose-alpha.yaml
b/saga-demo/tcc-spring-demo/docker-compose-alpha.yaml
new file mode 100644
index 00000000..a664c238
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/docker-compose-alpha.yaml
@@ -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.
+## ---------------------------------------------------------------------------
+
+version: '2.1'
+
+services:
+ database:
+ image: "postgres"
+ hostname: postgres
+ environment:
+ - POSTGRES_DB=saga
+ - POSTGRES_USER=saga
+ - POSTGRES_PASSWORD=password
+ healthcheck:
+ test: ["CMD-SHELL", "nc -z localhost 5432 &> /dev/null; echo $$?"]
+ interval: 30s
+ timeout: 10s
+ retries: 5
+
+ alpha:
+ image: "alpha-server:${TAG}"
+ hostname: alpha-server
+ links:
+ - "database:postgresql.servicecomb.io"
+ environment:
+ - JAVA_OPTS=-Dspring.profiles.active=prd
+ healthcheck:
+ test: ["CMD-SHELL", "nc -z localhost 8080 &> /dev/null; echo $$?"]
+ interval: 30s
+ timeout: 10s
+ retries: 5
+ depends_on:
+ database:
+ condition: service_healthy
diff --git a/saga-demo/tcc-spring-demo/docker-compose-demo.yaml
b/saga-demo/tcc-spring-demo/docker-compose-demo.yaml
new file mode 100644
index 00000000..2fcf1a1c
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/docker-compose-demo.yaml
@@ -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.
+## ---------------------------------------------------------------------------
+
+version: '2.1'
+
+services:
+ hotel:
+ image: "hotel:${TAG}"
+ hostname: hotel
+ external_links:
+ - "alpha:alpha-server.servicecomb.io"
+ ports:
+ - "8081:8080"
+
+ car:
+ image: "car:${TAG}"
+ hostname: car
+ external_links:
+ - "alpha:alpha-server.servicecomb.io"
+ ports:
+ - "8082:8080"
+
+ booking:
+ image: "booking:${TAG}"
+ hostname: booking
+ external_links:
+ - "alpha:alpha-server.servicecomb.io"
+ - "hotel:hotel.servicecomb.io"
+ - "car:car.servicecomb.io"
+ ports:
+ - "8083:8080"
+ depends_on:
+ - hotel
+ - car
diff --git a/saga-demo/tcc-spring-demo/docker-compose.mysql.yaml
b/saga-demo/tcc-spring-demo/docker-compose.mysql.yaml
new file mode 100644
index 00000000..43f3b5e8
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/docker-compose.mysql.yaml
@@ -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.
+## ---------------------------------------------------------------------------
+
+version: '2.1'
+
+services:
+ database:
+ image: "mysql/mysql-server:5.7"
+ hostname: mysql
+ environment:
+ - MYSQL_ROOT_PASSWORD=password
+ - MYSQL_DATABASE=saga
+ - MYSQL_USER=saga
+ - MYSQL_PASSWORD=password
+ healthcheck:
+ test: ["CMD-SHELL", "nc -z localhost 3306 &> /dev/null; echo $$?"]
+ interval: 30s
+ timeout: 10s
+ retries: 5
+
+ alpha:
+ links:
+ - "database:mysql.servicecomb.io"
+ environment:
+ - JAVA_OPTS=-Dspring.profiles.active=mysql
diff --git a/saga-demo/tcc-spring-demo/docker-compose.yaml
b/saga-demo/tcc-spring-demo/docker-compose.yaml
new file mode 100644
index 00000000..38e48f12
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/docker-compose.yaml
@@ -0,0 +1,83 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+version: '2.1'
+
+services:
+ database:
+ image: "postgres"
+ hostname: postgres
+ environment:
+ - POSTGRES_DB=saga
+ - POSTGRES_USER=saga
+ - POSTGRES_PASSWORD=password
+ healthcheck:
+ test: ["CMD-SHELL", "nc -z localhost 5432 &> /dev/null; echo $$?"]
+ interval: 30s
+ timeout: 10s
+ retries: 5
+
+ alpha:
+ image: "alpha-server:${TAG}"
+ hostname: alpha-server
+ links:
+ - "database:postgresql.servicecomb.io"
+ environment:
+ - JAVA_OPTS=-Dspring.profiles.active=prd
+ healthcheck:
+ test: ["CMD-SHELL", "nc -z localhost 8080 &> /dev/null; echo $$?"]
+ interval: 30s
+ timeout: 10s
+ retries: 5
+ depends_on:
+ database:
+ condition: service_healthy
+
+ hotel:
+ image: "hotel:${TAG}"
+ hostname: hotel
+ links:
+ - "alpha:alpha-server.servicecomb.io"
+ ports:
+ - "8081:8080"
+ depends_on:
+ alpha:
+ condition: service_healthy
+
+ car:
+ image: "car:${TAG}"
+ hostname: car
+ links:
+ - "alpha:alpha-server.servicecomb.io"
+ ports:
+ - "8082:8080"
+ depends_on:
+ alpha:
+ condition: service_healthy
+
+ booking:
+ image: "booking:${TAG}"
+ hostname: booking
+ links:
+ - "alpha:alpha-server.servicecomb.io"
+ - "hotel:hotel.servicecomb.io"
+ - "car:car.servicecomb.io"
+ ports:
+ - "8083:8080"
+ depends_on:
+ - hotel
+ - car
diff --git a/saga-demo/tcc-spring-demo/inventory/pom.xml
b/saga-demo/tcc-spring-demo/inventory/pom.xml
new file mode 100644
index 00000000..aed29e47
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/inventory/pom.xml
@@ -0,0 +1,112 @@
+<?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">
+ <parent>
+ <artifactId>saga-spring-demo</artifactId>
+ <groupId>org.apache.servicecomb.saga.demo</groupId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>Tcc-Inventory</artifactId>
+ <name>Saga::Demo::Tcc-Spring-Demo::Tcc-Inventory</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb.saga</groupId>
+ <artifactId>omega-spring-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb.saga</groupId>
+ <artifactId>omega-transport-resttemplate</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- mixin plugin configurations declared in another pom,
+ just like importing dependencies managed in another pom -->
+ <plugin>
+ <groupId>com.github.odavid.maven.plugins</groupId>
+ <artifactId>mixin-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <file>
+ <exists>/var/run/docker.sock</exists>
+ </file>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.commonjava.maven.plugins</groupId>
+ <artifactId>directory-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>demo</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/InventoryService.java
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/InventoryService.java
new file mode 100644
index 00000000..f5c36d7c
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/InventoryService.java
@@ -0,0 +1,68 @@
+/*
+ * 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.servicecomb.saga.demo.pack.inventory;
+
+import java.util.Objects;
+import org.apache.servicecomb.saga.omega.transaction.annotations.Participate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class InventoryService {
+
+ private ProductDao productDao;
+
+ /**
+ * Find the product with specific product Id.
+ *
+ * @param productId Product ID
+ * @param requiredCount Required product count
+ * @return return the reserved count, 0 if nothing is available. returns
negative value if
+ * insufficient.
+ */
+ @Participate(confirmMethod = "confirm", cancelMethod = "cancel")
+ public Integer reserve(Long productId, int requiredCount) {
+ Product product = productDao.findOne(productId);
+ if (Objects.isNull(product)) {
+ throw new IllegalArgumentException("Product not exists at all");
+ }
+
+ // if it is sufficient
+ if (product.getInStock() > requiredCount) {
+ product.setInStock(product.getInStock() - requiredCount);
+ productDao.save(product);
+ return requiredCount;
+ } else {
+ return product.getInStock() - requiredCount;
+ }
+ }
+
+ public void confirm(Long productId, int requiredCount) {
+ // empty body
+ }
+
+ public void cancel(Long productId, int requiredCount) {
+ Product product = productDao.findOne(productId);
+ product.setInStock(product.getInStock() + requiredCount);
+ productDao.save(product);
+ }
+
+ @Autowired
+ public void setProductDao(ProductDao productDao) {
+ this.productDao = productDao;
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/Product.java
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/Product.java
new file mode 100644
index 00000000..9ddc7e4a
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/Product.java
@@ -0,0 +1,72 @@
+/*
+ * 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.servicecomb.saga.demo.pack.inventory;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "t_product")
+public class Product implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String name;
+
+ /**
+ * Total count in stock
+ */
+ private Integer inStock;
+
+ Product() {
+ }
+
+ Product(String name, Integer inStock) {
+ this.name = name;
+ this.inStock = inStock;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getInStock() {
+ return inStock;
+ }
+
+ public void setInStock(Integer inStock) {
+ this.inStock = inStock;
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductController.java
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductController.java
new file mode 100644
index 00000000..dbf187a1
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductController.java
@@ -0,0 +1,91 @@
+/*
+ * 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.servicecomb.saga.demo.pack.inventory;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Controller
+@RequestMapping("/product")
+public class ProductController {
+
+ private InventoryService inventoryService;
+
+ @PostMapping("/product")
+ public Response updateInventory(@RequestParam("productId") Long productId,
+ @RequestParam("requiredCount") Integer requiredCount) {
+ return new Response(0, "OK",
+ ImmutableList.of(inventoryService.reserve(productId, requiredCount)));
+ }
+
+ @ExceptionHandler
+ public Response exceptionHandler(Exception e) {
+ return new Response(-1, e.getMessage(),
+ ImmutableList.of(e.getStackTrace()));
+ }
+
+ @Autowired
+ public void setInventoryService(
+ InventoryService inventoryService) {
+ this.inventoryService = inventoryService;
+ }
+}
+
+class Response {
+
+ private int code;
+
+ private String message;
+
+ private List<Object> objects;
+
+ Response(int code, String message, List<Object> objects) {
+ this.code = code;
+ this.message = message;
+ this.objects = objects;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public List<Object> getObjects() {
+ return objects;
+ }
+
+ public void setObjects(List<Object> objects) {
+ this.objects = objects;
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductDao.java
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductDao.java
new file mode 100644
index 00000000..42bcd4b6
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductDao.java
@@ -0,0 +1,23 @@
+/*
+ * 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.servicecomb.saga.demo.pack.inventory;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface ProductDao extends JpaRepository<Product, Long> {
+
+}
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/TccInventoryApplication.java
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/TccInventoryApplication.java
new file mode 100644
index 00000000..92c415c3
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/TccInventoryApplication.java
@@ -0,0 +1,40 @@
+/*
+ * 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.servicecomb.saga.demo.pack.inventory;
+
+import org.apache.servicecomb.saga.omega.spring.EnableOmega;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+@EnableOmega
+public class TccInventoryApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(TccInventoryApplication.class, args);
+ }
+
+ @Bean
+ CommandLineRunner kickOff(ProductDao productDao) {
+ return args -> {
+ productDao.save(new Product("Bottled water", 100));
+ };
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/main/resources/application.yaml
b/saga-demo/tcc-spring-demo/inventory/src/main/resources/application.yaml
new file mode 100644
index 00000000..98b79a6d
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/inventory/src/main/resources/application.yaml
@@ -0,0 +1,37 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+spring:
+ application:
+ name: inventory
+ datasource:
+ url: jdbc:h2:mem:inventory-test
+ h2:
+ console:
+ enabled: true
+ jpa:
+ show-sql: true
+ generate-ddl: true
+ hibernate:
+ ddl-auto: create-drop
+ naming:
+ physical-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+alpha:
+ cluster:
+ address: ${alpha-server.servicecomb.io:localhost}:8080
+server:
+ port: 10020
\ No newline at end of file
diff --git a/saga-demo/tcc-spring-demo/inventory/src/main/resources/log4j2.xml
b/saga-demo/tcc-spring-demo/inventory/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..cae04cb9
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/inventory/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?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.
+ -->
+
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} -
%msg%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <AsyncRoot level="info">
+ <AppenderRef ref="Console"/>
+ </AsyncRoot>
+ </Loggers>
+</Configuration>
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/test/java/org/apache/servicecomb/saga/demo/pack/inventory/InventoryServiceTest.java
b/saga-demo/tcc-spring-demo/inventory/src/test/java/org/apache/servicecomb/saga/demo/pack/inventory/InventoryServiceTest.java
new file mode 100644
index 00000000..b8d51c62
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/inventory/src/test/java/org/apache/servicecomb/saga/demo/pack/inventory/InventoryServiceTest.java
@@ -0,0 +1,28 @@
+package org.apache.servicecomb.saga.demo.pack.inventory;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@SpringBootTest
+@RunWith(SpringJUnit4ClassRunner.class)
+public class InventoryServiceTest {
+
+ private InventoryService inventoryService;
+
+ @Test
+ public void reserve() {
+ Integer count = inventoryService.reserve(1L, 10);
+ assertThat(count).isNotNull().isEqualTo(10);
+ }
+
+ @Autowired
+ public void setInventoryService(InventoryService inventoryService) {
+ this.inventoryService = inventoryService;
+ }
+}
\ No newline at end of file
diff --git
a/saga-demo/tcc-spring-demo/inventory/src/test/resources/application.yaml
b/saga-demo/tcc-spring-demo/inventory/src/test/resources/application.yaml
new file mode 100644
index 00000000..c8e3e326
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/inventory/src/test/resources/application.yaml
@@ -0,0 +1,37 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+spring:
+ application:
+ name: inventory
+ datasource:
+ url: jdbc:h2:mem:inventory-test
+ h2:
+ console:
+ enabled: true
+ jpa:
+ show-sql: true
+ generate-ddl: true
+ hibernate:
+ ddl-auto: create-drop
+ naming:
+ physical-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+alpha:
+ cluster:
+ address: alpha-server.servicecomb.io:8080
+server:
+ port: 10020
\ No newline at end of file
diff --git a/saga-demo/tcc-spring-demo/ordering/pom.xml
b/saga-demo/tcc-spring-demo/ordering/pom.xml
new file mode 100644
index 00000000..6cbbba10
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/ordering/pom.xml
@@ -0,0 +1,108 @@
+<?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">
+ <parent>
+ <artifactId>saga-spring-demo</artifactId>
+ <groupId>org.apache.servicecomb.saga.demo</groupId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>Tcc-Ordering</artifactId>
+ <name>Saga::Demo::Tcc-Spring-Demo::Tcc-Ordering</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb.saga</groupId>
+ <artifactId>omega-spring-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb.saga</groupId>
+ <artifactId>omega-transport-resttemplate</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- mixin plugin configurations declared in another pom,
+ just like importing dependencies managed in another pom -->
+ <plugin>
+ <groupId>com.github.odavid.maven.plugins</groupId>
+ <artifactId>mixin-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <file>
+ <exists>/var/run/docker.sock</exists>
+ </file>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.commonjava.maven.plugins</groupId>
+ <artifactId>directory-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>demo</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git
a/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/OrderingController.java
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/OrderingController.java
new file mode 100644
index 00000000..a17f8b77
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/OrderingController.java
@@ -0,0 +1,62 @@
+/*
+ * 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.servicecomb.saga.demo.pack.ordering;
+
+
+import java.math.BigDecimal;
+import org.apache.servicecomb.saga.omega.context.annotations.TccStart;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.client.RestTemplate;
+
+@Controller
+@RequestMapping("/ordering")
+public class OrderingController {
+
+ private RestTemplate restTemplate;
+
+ private PurchaseOrderDao purchaseOrderDao;
+
+ @TccStart
+ @PostMapping("/{productId}")
+ public String ordering(
+ @RequestParam("requiredCount") Integer requiredCount) {
+ // place an order
+ purchaseOrderDao.save(new PurchaseOrder("Foo", BigDecimal.TEN));
+ // try to reserve some product
+
+ // create a purchase order and do the payment
+
+ // create delivery order
+
+ return "";
+ }
+
+ @Autowired
+ public void setRestTemplate(RestTemplate restTemplate) {
+ this.restTemplate = restTemplate;
+ }
+
+ @Autowired
+ public void setPurchaseOrderDao(
+ PurchaseOrderDao purchaseOrderDao) {
+ this.purchaseOrderDao = purchaseOrderDao;
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/PurchaseOrder.java
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/PurchaseOrder.java
new file mode 100644
index 00000000..8b4d7197
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/PurchaseOrder.java
@@ -0,0 +1,70 @@
+/*
+ * 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.servicecomb.saga.demo.pack.ordering;
+
+import java.math.BigDecimal;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "t_order")
+public class PurchaseOrder {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String username;
+
+ private BigDecimal amount;
+
+ public PurchaseOrder() {
+ this("", BigDecimal.ZERO);
+ }
+
+ public PurchaseOrder(String username, BigDecimal amount) {
+ this.username = username;
+ this.amount = amount;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/PurchaseOrderDao.java
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/PurchaseOrderDao.java
new file mode 100644
index 00000000..9f52a760
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/PurchaseOrderDao.java
@@ -0,0 +1,23 @@
+/*
+ * 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.servicecomb.saga.demo.pack.ordering;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface PurchaseOrderDao extends JpaRepository<PurchaseOrder, Long> {
+
+}
diff --git
a/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/TccOrderingApplication.java
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/TccOrderingApplication.java
new file mode 100644
index 00000000..a4000fee
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/TccOrderingApplication.java
@@ -0,0 +1,30 @@
+/*
+ * 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.servicecomb.saga.demo.pack.ordering;
+
+import org.apache.servicecomb.saga.omega.spring.EnableOmega;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableOmega
+public class TccOrderingApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(TccOrderingApplication.class, args);
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/ordering/src/main/resources/application.yaml
b/saga-demo/tcc-spring-demo/ordering/src/main/resources/application.yaml
new file mode 100644
index 00000000..57785f5c
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/ordering/src/main/resources/application.yaml
@@ -0,0 +1,37 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+spring:
+ application:
+ name: ordering
+ datasource:
+ url: jdbc:h2:mem:ordering-test
+ h2:
+ console:
+ enabled: true
+ jpa:
+ show-sql: true
+ generate-ddl: true
+ hibernate:
+ ddl-auto: create-drop
+ naming:
+ physical-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+alpha:
+ cluster:
+ address: alpha-server.servicecomb.io:8080
+server:
+ port: 10010
\ No newline at end of file
diff --git a/saga-demo/tcc-spring-demo/ordering/src/main/resources/log4j2.xml
b/saga-demo/tcc-spring-demo/ordering/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..cae04cb9
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/ordering/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?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.
+ -->
+
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} -
%msg%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <AsyncRoot level="info">
+ <AppenderRef ref="Console"/>
+ </AsyncRoot>
+ </Loggers>
+</Configuration>
diff --git
a/saga-demo/tcc-spring-demo/ordering/src/main/resources/static/index.html
b/saga-demo/tcc-spring-demo/ordering/src/main/resources/static/index.html
new file mode 100644
index 00000000..894667f0
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/ordering/src/main/resources/static/index.html
@@ -0,0 +1,91 @@
+<!--
+ ~ 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.
+ -->
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Saga-booking-demo</title>
+
+ <script type="text/javascript"
src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
+
+ <script type="text/javascript">
+ function testCase1() {
+ $.post("http://127.0.0.1:8083/booking/test/2/2", function(data) {
+ var msg = data;
+ $("#booking_result_1").html(msg);
+ });
+ }
+
+ function testCase2() {
+ $.post("http://127.0.0.1:8083/booking/test/3/2", function(data) {
+ var msg = data;
+ $("#booking_result_2").html(msg);
+ })
+ .fail(function(data) {
+ alert("The transaction is failed");
+ $("#booking_result_2").html("<li>" + JSON.stringify(data) +
"</li>");
+ });
+ }
+
+ function room_booking_result() {
+ $.get("http://127.0.0.1:8081/bookings", function(data) {
+ var msg = "<li>" + JSON.stringify(data) + "</li>";
+ $("#room_list").html(msg);
+ });
+ }
+
+ function car_booking_result() {
+ $.get("http://127.0.0.1:8082/bookings", function(data) {
+ var msg = "<li>" + JSON.stringify(data) + "</li>";
+ $("#car_list").html(msg);
+ });
+ }
+ </script>
+</head>
+<body>
+<p>Test cases of Sage booking demo:</p>
+<p>Case 1. <a href="javascript:void(0);" onclick="testCase1();">[Booking 2
rooms and 2 cars, will done successfully]</a> </p>
+<p>
+ Booking result: <span id="booking_result_1">###</span><br>
+</p>
+<br>
+<p>Case 2. <a href="javascript:void(0);" onclick="testCase2();">[Booking 3
rooms and 2 cars, hotel order service will failed.]</a> </p>
+<p>
+ Booking result: <span id="booking_result_2">###</span><br>
+</p>
+<br>
+<p><a href="javascript:void(0);" onclick="room_booking_result();">[Query the
room booking result]</a> </p>
+<p>
+ Room booking list:<br>
+<ul>
+ <li id="room_list">
+ #Name, Amount, Confirm status, Cancel Status
+ </li>
+</ul>
+</p>
+<br>
+<p><a href="javascript:void(0);" onclick="car_booking_result();">[Query the
car booking result]</a> </p>
+<p>
+ Car booking list:<br>
+<ul>
+ <li id="car_list">
+ #Name, Amount, Confirm status, Cancel Status
+ </li>
+</ul>
+</p>
+</body>
+</html>
diff --git a/saga-demo/tcc-spring-demo/payment/pom.xml
b/saga-demo/tcc-spring-demo/payment/pom.xml
new file mode 100644
index 00000000..e950acc1
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/payment/pom.xml
@@ -0,0 +1,106 @@
+<?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">
+ <parent>
+ <artifactId>saga-spring-demo</artifactId>
+ <groupId>org.apache.servicecomb.saga.demo</groupId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>Tcc-Payment</artifactId>
+ <name>Saga::Demo::Tcc-Spring-Demo::Tcc-Payment</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb.saga</groupId>
+ <artifactId>omega-spring-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb.saga</groupId>
+ <artifactId>omega-transport-resttemplate</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- mixin plugin configurations declared in another pom,
+ just like importing dependencies managed in another pom -->
+ <plugin>
+ <groupId>com.github.odavid.maven.plugins</groupId>
+ <artifactId>mixin-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <file>
+ <exists>/var/run/docker.sock</exists>
+ </file>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.commonjava.maven.plugins</groupId>
+ <artifactId>directory-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>demo</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git
a/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/Account.java
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/Account.java
new file mode 100644
index 00000000..159453f3
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/Account.java
@@ -0,0 +1,90 @@
+/*
+ * 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.servicecomb.saga.demo.pack.payment;
+
+import java.math.BigDecimal;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "t_account")
+public class Account {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Column(nullable = false, unique = true)
+ private String username;
+
+ @Column(nullable = false)
+ private BigDecimal balance;
+
+ @Column(nullable = false)
+ private BigDecimal reservedAmount;
+
+ public Account() {
+ this(null, BigDecimal.ZERO, BigDecimal.ZERO);
+ }
+
+ public Account(String username) {
+ this(username, BigDecimal.ZERO, BigDecimal.ZERO);
+ }
+
+ public Account(String username, BigDecimal balance, BigDecimal
reservedAmount) {
+ this.username = username;
+ this.balance = balance;
+ this.reservedAmount = reservedAmount;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public BigDecimal getBalance() {
+ return balance;
+ }
+
+ public void setBalance(BigDecimal balance) {
+ this.balance = balance;
+ }
+
+ public BigDecimal getReservedAmount() {
+ return reservedAmount;
+ }
+
+ public void setReservedAmount(BigDecimal reservedAmount) {
+ this.reservedAmount = reservedAmount;
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/AccountDao.java
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/AccountDao.java
new file mode 100644
index 00000000..4be494c6
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/AccountDao.java
@@ -0,0 +1,28 @@
+/*
+ * 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.servicecomb.saga.demo.pack.payment;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface AccountDao extends JpaRepository<Account, Long> {
+
+ /**
+ * @param username username
+ * @return the account specified by username
+ */
+ public Account findByUsername(String username);
+}
diff --git
a/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/PaymentController.java
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/PaymentController.java
new file mode 100644
index 00000000..8b11c996
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/PaymentController.java
@@ -0,0 +1,24 @@
+/*
+ * 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.servicecomb.saga.demo.pack.payment;
+
+import org.springframework.stereotype.Controller;
+
+@Controller
+public class PaymentController {
+
+}
diff --git
a/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/PaymentService.java
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/PaymentService.java
new file mode 100644
index 00000000..6e587485
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/PaymentService.java
@@ -0,0 +1,89 @@
+/*
+ * 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.servicecomb.saga.demo.pack.payment;
+
+import java.math.BigDecimal;
+import org.apache.servicecomb.saga.omega.transaction.annotations.Participate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class PaymentService {
+
+ private AccountDao accountDao;
+
+ @Transactional
+ @Participate(confirmMethod = "confirm", cancelMethod = "cancel")
+ public BigDecimal execute(String username, BigDecimal amount) {
+ Account account = accountDao.findByUsername(username);
+
+ if (account.getBalance()
+ .subtract(account.getReservedAmount())
+ .compareTo(amount) > 0) {
+
+ account.setReservedAmount(account.getReservedAmount().add(amount));
+ accountDao.save(account);
+ return amount;
+ } else {
+ throw new AccountException("Insufficient funds");
+ }
+ }
+
+ @Transactional
+ public void confirm(String username, BigDecimal amount) {
+ Account account = accountDao.findByUsername(username);
+ account.setReservedAmount(account.getReservedAmount().subtract(amount));
+ account.setBalance(account.getBalance().subtract(amount));
+ accountDao.save(account);
+ }
+
+ @Transactional
+ public void cancel(String username, BigDecimal amount) {
+ Account account = accountDao.findByUsername(username);
+ account.setReservedAmount(account.getReservedAmount().subtract(amount));
+ accountDao.save(account);
+ }
+
+ @Autowired
+ public void setAccountDao(AccountDao accountDao) {
+ this.accountDao = accountDao;
+ }
+}
+
+class AccountException extends RuntimeException {
+
+ public AccountException() {
+ }
+
+ public AccountException(String message) {
+ super(message);
+ }
+
+ public AccountException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public AccountException(Throwable cause) {
+ super(cause);
+ }
+
+ public AccountException(String message, Throwable cause, boolean
enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
\ No newline at end of file
diff --git
a/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/TccPaymentApplication.java
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/TccPaymentApplication.java
new file mode 100644
index 00000000..9c5d7950
--- /dev/null
+++
b/saga-demo/tcc-spring-demo/payment/src/main/java/org/apache/servicecomb/saga/demo/pack/payment/TccPaymentApplication.java
@@ -0,0 +1,30 @@
+/*
+ * 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.servicecomb.saga.demo.pack.payment;
+
+import org.apache.servicecomb.saga.omega.spring.EnableOmega;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableOmega
+public class TccPaymentApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(TccPaymentApplication.class, args);
+ }
+}
diff --git
a/saga-demo/tcc-spring-demo/payment/src/main/resources/application.yaml
b/saga-demo/tcc-spring-demo/payment/src/main/resources/application.yaml
new file mode 100644
index 00000000..7fe65b3e
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/payment/src/main/resources/application.yaml
@@ -0,0 +1,37 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+spring:
+ application:
+ name: payment
+ datasource:
+ url: jdbc:h2:mem:payment-test
+ h2:
+ console:
+ enabled: true
+ jpa:
+ show-sql: true
+ generate-ddl: true
+ hibernate:
+ ddl-auto: create-drop
+ naming:
+ physical-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+alpha:
+ cluster:
+ address: alpha-server.servicecomb.io:8080
+server:
+ port: 10030
\ No newline at end of file
diff --git a/saga-demo/tcc-spring-demo/payment/src/main/resources/log4j2.xml
b/saga-demo/tcc-spring-demo/payment/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..cae04cb9
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/payment/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?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.
+ -->
+
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} -
%msg%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <AsyncRoot level="info">
+ <AppenderRef ref="Console"/>
+ </AsyncRoot>
+ </Loggers>
+</Configuration>
diff --git a/saga-demo/tcc-spring-demo/pom.xml
b/saga-demo/tcc-spring-demo/pom.xml
new file mode 100644
index 00000000..a020802b
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/pom.xml
@@ -0,0 +1,47 @@
+<?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">
+ <parent>
+ <artifactId>saga-demo</artifactId>
+ <groupId>org.apache.servicecomb.saga.demo</groupId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>tcc-spring-demo</artifactId>
+ <name>Saga::Demo::Tcc-Spring-Demo</name>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>ordering</module>
+ <module>payment</module>
+ <module>inventory</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-tcnative-boringssl-static</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/saga-demo/tcc-spring-demo/saga-demo.sh
b/saga-demo/tcc-spring-demo/saga-demo.sh
new file mode 100644
index 00000000..2b3cf475
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/saga-demo.sh
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+
+# 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.
+
+service=saga-demo
+
+show_usage() {
+ echo "Usage: $0 {up|up-alpha|up-demo|up-mysql|down}" >&2
+}
+
+fetch_version() {
+ version="$(printf 'VER\t${project.version}' | mvn help:evaluate | grep
'^VER' | cut -f2)"
+}
+
+if [[ -z $1 ]]; then
+ show_usage
+ exit 2
+fi
+
+case $1 in
+ up)
+ fetch_version
+ echo "Starting ${service}:${version}"
+ TAG=$version docker-compose up
+ exit $?
+ ;;
+
+ up-alpha)
+ fetch_version
+ echo "Starting ${service}:${version}"
+ TAG=$version docker-compose -f docker-compose-alpha.yaml up
+ exit $?
+ ;;
+
+ up-demo)
+ fetch_version
+ echo "Starting ${service}:${version}"
+ TAG=$version docker-compose -f docker-compose-demo.yaml up
+ exit $?
+ ;;
+
+ up-mysql)
+ fetch_version
+ echo "Starting ${service}:${version}"
+ TAG=$version docker-compose -f docker-compose.yaml -f
docker-compose.mysql.yaml up
+ exit $?
+ ;;
+
+ down)
+ fetch_version
+ echo "Stopping ${service}:${version}"
+ TAG=$version docker-compose down
+ exit $?
+ ;;
+
+ *)
+ show_usage
+ exit 2
+ ;;
+esac
+
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services