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

ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git

commit 534ad26d223c9faed41600c504abb802a7074b35
Author: imlijinting <[email protected]>
AuthorDate: Mon Sep 3 00:19:42 2018 +0800

    [SCB-820] Added Tcc Demo
---
 saga-demo/pom.xml                                  |   1 +
 saga-demo/tcc-spring-demo/README.md                | 145 +++++++++++++++++++++
 .../tcc-spring-demo/docker-compose-alpha.yaml      |  48 +++++++
 saga-demo/tcc-spring-demo/docker-compose-demo.yaml |  48 +++++++
 .../tcc-spring-demo/docker-compose.mysql.yaml      |  39 ++++++
 saga-demo/tcc-spring-demo/docker-compose.yaml      |  83 ++++++++++++
 saga-demo/tcc-spring-demo/inventory/pom.xml        | 112 ++++++++++++++++
 .../saga/demo/pack/inventory/InventoryService.java |  54 ++++++++
 .../saga/demo/pack/inventory/Product.java          |  85 ++++++++++++
 .../demo/pack/inventory/ProductController.java     |  75 +++++++++++
 .../saga/demo/pack/inventory/ProductDao.java       |   7 +
 .../pack/inventory/TccInventoryApplication.java    |  40 ++++++
 .../inventory/src/main/resources/application.yaml  |  37 ++++++
 .../inventory/src/main/resources/log4j2.xml        |  30 +++++
 .../demo/pack/inventory/InventoryServiceTest.java  |  28 ++++
 .../inventory/src/test/resources/application.yaml  |  37 ++++++
 saga-demo/tcc-spring-demo/ordering/pom.xml         | 108 +++++++++++++++
 .../demo/pack/ordering/OrderingController.java     |  26 ++++
 .../demo/pack/ordering/TccOrderingApplication.java |  30 +++++
 .../ordering/src/main/resources/application.yaml   |  29 +++++
 .../ordering/src/main/resources/log4j2.xml         |  30 +++++
 .../ordering/src/main/resources/static/index.html  |  91 +++++++++++++
 saga-demo/tcc-spring-demo/payment/pom.xml          | 106 +++++++++++++++
 .../demo/pack/payment/TccPaymentApplication.java   |  30 +++++
 .../payment/src/main/resources/application.yaml    |  29 +++++
 .../payment/src/main/resources/log4j2.xml          |  30 +++++
 saga-demo/tcc-spring-demo/pom.xml                  |  47 +++++++
 saga-demo/tcc-spring-demo/saga-demo.sh             |  74 +++++++++++
 28 files changed, 1499 insertions(+)

diff --git a/saga-demo/pom.xml b/saga-demo/pom.xml
index cff708a..614dfa6 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 0000000..0502493
--- /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 0000000..a664c23
--- /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 0000000..2fcf1a1
--- /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 0000000..43f3b5e
--- /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 0000000..38e48f1
--- /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 0000000..aed29e4
--- /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 0000000..57279e8
--- /dev/null
+++ 
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/InventoryService.java
@@ -0,0 +1,54 @@
+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.
+   */
+  @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.getAvailable() > requiredCount) {
+      product.setReserved(product.getReserved() + requiredCount); // reserve 
some product in stock
+      productDao.save(product);
+      return requiredCount;
+    } else {
+      return product.getAvailable() - requiredCount;
+    }
+  }
+
+  public void confirm(Long productId, int requiredCount) {
+    Product product = productDao.findOne(productId);
+    product.setInStock(product.getInStock() - requiredCount); // actually 
reduce the in stock count
+    product.setReserved(product.getReserved() - requiredCount); // and remove 
the reserved count
+    productDao.save(product);
+  }
+
+  public void cancel(Long productId, int requiredCount) {
+    Product product = productDao.findOne(productId);
+    product.setReserved(product.getReserved() - requiredCount); // remove the 
reserved count
+    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 0000000..2fbc707
--- /dev/null
+++ 
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/Product.java
@@ -0,0 +1,85 @@
+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;
+import org.hibernate.annotations.Formula;
+
+@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;
+
+  /**
+   * reserved count
+   */
+  private Integer reserved;
+
+  Product() {
+  }
+
+  Product(String name, Integer inStock, Integer reserved) {
+    this.name = name;
+    this.inStock = inStock;
+    this.reserved = reserved;
+  }
+
+  /**
+   * Available in stock
+   */
+  @Formula("in_Stock - reserved")
+  private Integer available;
+
+  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;
+  }
+
+  public Integer getReserved() {
+    return reserved;
+  }
+
+  public void setReserved(Integer reserved) {
+    this.reserved = reserved;
+  }
+
+  public Integer getAvailable() {
+    return available;
+  }
+
+  public void setAvailable(Integer available) {
+    this.available = available;
+  }
+}
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 0000000..def42a8
--- /dev/null
+++ 
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductController.java
@@ -0,0 +1,75 @@
+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 0000000..0b96353
--- /dev/null
+++ 
b/saga-demo/tcc-spring-demo/inventory/src/main/java/org/apache/servicecomb/saga/demo/pack/inventory/ProductDao.java
@@ -0,0 +1,7 @@
+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 0000000..909e8c0
--- /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 kickStart(ProductDao productDao) {
+    return args -> {
+      productDao.save(new Product("Bottled water", 100, 20));
+    };
+  }
+}
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 0000000..c8e3e32
--- /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: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 0000000..cae04cb
--- /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 0000000..b8d51c6
--- /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 0000000..c8e3e32
--- /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 0000000..6cbbba1
--- /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 0000000..39aacc1
--- /dev/null
+++ 
b/saga-demo/tcc-spring-demo/ordering/src/main/java/org/apache/servicecomb/saga/demo/pack/ordering/OrderingController.java
@@ -0,0 +1,26 @@
+package org.apache.servicecomb.saga.demo.pack.ordering;
+
+
+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;
+
+@Controller
+@RequestMapping("/ordering")
+public class OrderingController {
+
+  @PostMapping("/{productId}")
+  public String ordering(
+      @RequestParam("requiredCount") Integer requiredCount) {
+    // place an order
+
+    // try to reserve some product
+
+    // create a purchase order and do the payment
+
+    // create delivery order
+
+    return "";
+  }
+}
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 0000000..a4000fe
--- /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 0000000..d2c82e0
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/ordering/src/main/resources/application.yaml
@@ -0,0 +1,29 @@
+## ---------------------------------------------------------------------------
+## 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
+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 0000000..cae04cb
--- /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 0000000..894667f
--- /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 0000000..e950acc
--- /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/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 0000000..9c5d795
--- /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 0000000..1838533
--- /dev/null
+++ b/saga-demo/tcc-spring-demo/payment/src/main/resources/application.yaml
@@ -0,0 +1,29 @@
+## ---------------------------------------------------------------------------
+## 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: hotel
+  datasource:
+    url: jdbc:h2:mem:payment-test
+  h2:
+    console:
+      enabled: true
+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 0000000..cae04cb
--- /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 0000000..a020802
--- /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 0000000..2b3cf47
--- /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
+

Reply via email to