From d1e68c62d1dda4b3cafa80039b41e08f773fb8bb Mon Sep 17 00:00:00 2001 From: xingfudeshi Date: Thu, 21 Mar 2024 10:09:10 +0800 Subject: [PATCH] add dubbo-samples-seata --- at-sample/dubbo-samples-seata/README.md | 137 ++++++++++++++++++ .../dubbo-samples-seata-account/pom.xml | 93 ++++++++++++ .../seata/account/AccountApplication.java | 32 ++++ .../account/service/AccountServiceImpl.java | 48 ++++++ .../src/main/resources/application.yml | 53 +++++++ .../seata/AccountApplicationTests.java | 30 ++++ .../dubbo-samples-seata-api/pom.xml | 34 +++++ .../samples/seata/api/AccountService.java | 32 ++++ .../samples/seata/api/BusinessService.java | 43 ++++++ .../apache/dubbo/samples/seata/api/Order.java | 52 +++++++ .../dubbo/samples/seata/api/OrderService.java | 34 +++++ .../dubbo/samples/seata/api/StockService.java | 40 +++++ .../dubbo-samples-seata-business/pom.xml | 85 +++++++++++ .../seata/business/BusinessApplication.java | 32 ++++ .../business/controller/TestController.java | 50 +++++++ .../business/service/BusinessServiceImpl.java | 58 ++++++++ .../src/main/resources/application.yml | 43 ++++++ .../seata/business/BusinessApplicationIT.java | 42 ++++++ .../dubbo-samples-seata-order/pom.xml | 93 ++++++++++++ .../samples/seata/order/OrderApplication.java | 32 ++++ .../seata/order/service/OrderServiceImpl.java | 99 +++++++++++++ .../src/main/resources/application.yml | 53 +++++++ .../samples/seata/OrderApplicationTests.java | 30 ++++ .../dubbo-samples-seata-stock/pom.xml | 93 ++++++++++++ .../samples/seata/stock/StockApplication.java | 32 ++++ .../seata/stock/service/StockServiceImpl.java | 63 ++++++++ .../src/main/resources/application.yml | 53 +++++++ .../samples/seata/StockApplicationTests.java | 30 ++++ at-sample/dubbo-samples-seata/pom.xml | 94 ++++++++++++ .../script/db/dubbo_biz.sql | 51 +++++++ .../script/db/undo_log.sql | 29 ++++ 31 files changed, 1690 insertions(+) create mode 100644 at-sample/dubbo-samples-seata/README.md create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-account/pom.xml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/AccountApplication.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/service/AccountServiceImpl.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/resources/application.yml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/test/java/org/apache/dubbo/samples/seata/AccountApplicationTests.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-api/pom.xml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/AccountService.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/BusinessService.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/Order.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/OrderService.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/StockService.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-business/pom.xml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/BusinessApplication.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/controller/TestController.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/service/BusinessServiceImpl.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/resources/application.yml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/test/java/org/apache/dubbo/samples/seata/business/BusinessApplicationIT.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-order/pom.xml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/OrderApplication.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/service/OrderServiceImpl.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/resources/application.yml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/test/java/org/apache/dubbo/samples/seata/OrderApplicationTests.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/pom.xml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/StockApplication.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/service/StockServiceImpl.java create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/resources/application.yml create mode 100644 at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/test/java/org/apache/dubbo/samples/seata/StockApplicationTests.java create mode 100644 at-sample/dubbo-samples-seata/pom.xml create mode 100644 at-sample/dubbo-samples-seata/script/db/dubbo_biz.sql create mode 100644 at-sample/dubbo-samples-seata/script/db/undo_log.sql diff --git a/at-sample/dubbo-samples-seata/README.md b/at-sample/dubbo-samples-seata/README.md new file mode 100644 index 000000000..2a444f7e4 --- /dev/null +++ b/at-sample/dubbo-samples-seata/README.md @@ -0,0 +1,137 @@ + +在Dubbo中可以使用Seata来实现分布式事务功能 + +## 开始之前 +Apache Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 +在Dubbo中集成Seata实现分布式事务非常方便,只需简单几步即可完成,本文将带你快速体验。开始前,请先完成以下内容: +- 请克隆[seata-samples](https://github.com/apache/incubator-seata-samples)至本地并导入到开发工具中,并找到/at-sample/dubbo-samples-seata子项目。 +- 请下载最新版的[seata-server二进制包](https://seata.apache.org/zh-cn/unversioned/download/seata-server)至本地。 + + +### 步骤 1:建立数据库并初始化相关测试数据 +- 本文将使用MySQL 5.7 (更多支持的数据库可在文末查看附录)。 + 进入dubbo-samples-seata的script目录,找到dubbo_biz.sql和undo_log.sql两个数据库脚本文件,内容如下: + +undo_log.sql是Seata AT 模式需要 `UNDO_LOG` 表 +```sql +-- for AT mode you must to init this sql for you business database. the seata server not need it. +CREATE TABLE IF NOT EXISTS `undo_log` +( + `branch_id` BIGINT NOT NULL COMMENT 'branch transaction id', + `xid` VARCHAR(128) NOT NULL COMMENT 'global transaction id', + `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization', + `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', + `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', + `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', + `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', + UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) + ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table'; +ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`); + +``` +dubbo_biz.sql是示例业务表以及初始化数据 + +```sql +DROP TABLE IF EXISTS `stock_tbl`; +CREATE TABLE `stock_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY (`commodity_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `order_tbl`; +CREATE TABLE `order_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT 0, + `money` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `account_tbl`; +CREATE TABLE `account_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `money` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +---INITIALIZE THE ACCOUNT TABLE +INSERT INTO account_tbl(`user_id`,`money`) VALUES('ACC_001','1000'); +---INITIALIZE THE STOCK TABLE +INSERT INTO stock_tbl(`commodity_code`,`count`) VALUES('STOCK_001','100'); + +``` +#### 请依次执行以下操作: +* 1.1 创建seata数据库(实际业务场景中会使用不同的数据库,本文为了方便演示仅创建一个数据库,所有的表都在该数据库中创建) +* 1.2 执行undo_log.sql表中的脚本完成AT模式所需的undo_log表创建 +* 1.3 执行dubbo_biz.sql表中的脚本完成示例业务表创建以及测试数据的初始化 + +### 步骤 2:更新spring-boot应用配置中的数据库连接信息 + +请将以下3个子模块的数据库连接信息更新为你的信息,其他配置无需更改,至此,客户端的配置已经完毕。 + +* dubbo-samples-seata-account +* dubbo-samples-seata-order +* dubbo-samples-seata-stock +```yaml +url: jdbc:mysql://127.0.0.1:3306/seata?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useOldAliasMetadataBehavior=true +username: root +password: 123456 +``` + +### 步骤 3:启动Seata-Server +- 本文使用的是Seata-Server V2.0.0版本。 + +请将下载的Seata-Server二进制包解压,并进入bin目录,然后执行以下命令即可启动Seata-Server。 + +如果你是Mac OS 或者Linux操作系统,请执行: +``` +./seata-server.sh +``` +或者你是Windows操作系统,请执行: +``` +./seata-server.bat +``` + +### 步骤 4:启动示例 + +一切准备就绪,开始启动示例 + +#### 请依次启动以下子项目: +* 4.1 Account Service +* 4.2 Order Service +* 4.3 Stock Service +* 4.4 Business Service + +### 步骤 5:查看分布式事务执行结果 +通过访问以下链接,可以测试分布式事务成功提交流程: + +http://127.0.0.1:9999/test/commit?userId=ACC_001&commodityCode=STOCK_001&orderCount=1 + +**分布式事务成功提交时,业务表的数据将正常更新,请注意观察数据库表中的数据。** + +通过访问以下链接,可以测试分布式事务失败回滚流程: + +http://127.0.0.1:9999/test/rollback?userId=ACC_001&commodityCode=STOCK_001&orderCount=1 + +**分布式事务失败回滚时,业务表的数据将没有任何改变,请注意观察数据库表中的数据。** + +### 附录 +* 支持的事务模式:Seata目前支持AT、TCC、SAGA、XA等模式,详情请访问[Seata官网](https://seata.apache.org/zh-cn/docs/user/mode/at)进行了解 +* 支持的配置中心:Seata支持丰富的配置中心,如zookeeper、nacos、consul、apollo、etcd、file(本文使用此配置中心,无需第三方依赖,方便快速演示),详情请访问[Seata配置中心](https://seata.apache.org/zh-cn/docs/user/configuration/)进行了解 +* 支持的注册中心:Seata支持丰富的注册中心,如eureka、sofa、redis、zookeeper、nacos、consul、etcd、file(本文使用此注册中心,无需第三方依赖,方便快速演示),详情请访问[Seata注册中心](https://seata.apache.org/zh-cn/docs/user/registry/)进行了解 +* 支持的部署方式:直接部署、Docker、K8S、Helm等部署方式,详情请访问[Seata部署方式](https://seata.apache.org/zh-cn/docs/ops/deploy-guide-beginner)进行了解 +* 支持的API:Seata的API分为两大类:High-Level API 和 Low-Level API,详情请访问[Seata API](https://seata.apache.org/zh-cn/docs/user/api)进行了解 +* 支持的数据库:Seata支持MySQL、Oracle、PostgreSQL、TiDB、MariaDB等数据库,不同的事务模式会有差别,详情请访问[Seata支持的数据库](https://seata.apache.org/zh-cn/docs/user/datasource)进行了解 +* 支持ORM框架:Seata 虽然是保证数据一致性的组件,但对于 ORM 框架并没有特殊的要求,像主流的Mybatis,Mybatis-Plus,Spring Data JPA, Hibernate等都支持。这是因为ORM框架位于JDBC结构的上层,而 Seata 的 AT,XA 事务模式是对 JDBC 标准接口操作的拦截和增强。详情请访问[Seata支持的ORM框架](https://seata.apache.org/zh-cn/docs/user/ormframework)进行了解 +* 支持的微服务框架:Seata目前支持Dubbo、gRPC、hsf、http、motan、sofa等框架,同时seata提供了丰富的拓展机制,理论上可以支持任何微服务框架。详情请访问[Seata支持的微服务框架](https://seata.apache.org/zh-cn/docs/user/microservice)进行了解 +* SQL限制:Seata 事务目前支持 INSERT、UPDATE、DELETE 三类 DML 语法的部分功能,这些类型都是已经经过Seata开源社区的验证。SQL 的支持范围还在不断扩大,建议在本文限制的范围内使用。详情请访问[Seata SQL限制](https://seata.apache.org/zh-cn/docs/user/sqlreference/sql-restrictions)进行了解 diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/pom.xml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/pom.xml new file mode 100644 index 000000000..3d4f98cf2 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/pom.xml @@ -0,0 +1,93 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-samples-seata + 0.0.1-SNAPSHOT + + dubbo-samples-seata-account + dubbo-samples-seata-account + + + + org.springframework.boot + spring-boot-starter + + + org.apache.dubbo + dubbo-samples-seata-api + + + org.apache.dubbo + dubbo-spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.mysql + mysql-connector-j + + + org.springframework.boot + spring-boot-starter-jdbc + + + io.seata + seata-spring-boot-starter + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + org.apache.dubbo.samples.seata.account.AccountApplication + + + + repackage + + repackage + + + + + + + + diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/AccountApplication.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/AccountApplication.java new file mode 100644 index 000000000..89f9d6c1f --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/AccountApplication.java @@ -0,0 +1,32 @@ +/* + * 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.dubbo.samples.seata.account; + +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableDubbo +public class AccountApplication { + + public static void main(String[] args) { + SpringApplication.run(AccountApplication.class, args); + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/service/AccountServiceImpl.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/service/AccountServiceImpl.java new file mode 100644 index 000000000..f805bda71 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/java/org/apache/dubbo/samples/seata/account/service/AccountServiceImpl.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dubbo.samples.seata.account.service; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.samples.seata.api.AccountService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +@DubboService +public class AccountServiceImpl implements AccountService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); + + private final JdbcTemplate jdbcTemplate; + + public AccountServiceImpl(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public void debit(String userId, int money) { + LOGGER.info("Account Service ... xid: " + RootContext.getXID()); + LOGGER.info("Deducting balance SQL: update account_tbl set money = money - {} where user_id = {}", money, + userId); + + jdbcTemplate.update("update account_tbl set money = money - ? where user_id = ?", new Object[]{money, userId}); + LOGGER.info("Account Service End ... "); + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/resources/application.yml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/resources/application.yml new file mode 100644 index 000000000..19b54ed1e --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/main/resources/application.yml @@ -0,0 +1,53 @@ +# 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: AccountApplication + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${mysql.address:127.0.0.1}:${mysql.port:3306}/seata?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useOldAliasMetadataBehavior=true + username: root + password: helloworld + hikari: + connection-timeout: 30000 + idle-timeout: 600000 + max-lifetime: 1800000 + maximum-pool-size: 100 + minimum-idle: 10 + pool-name: HikaraPool-1 +dubbo: + application: + logger: slf4j + name: ${spring.application.name} + qos-enable: false + registry: + address: multicast://224.5.6.7:1234 + protocol: + port: 20881 + name: dubbo +seata: + enabled: true + application-id: dubbo-samples-seata + tx-service-group: default_tx_group + service: + vgroup-mapping: + default_tx_group: default + grouplist: + default: ${seata.address:127.0.0.1}:${seata.port:8091} + registry: + type: file + config: + type: file diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/test/java/org/apache/dubbo/samples/seata/AccountApplicationTests.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/test/java/org/apache/dubbo/samples/seata/AccountApplicationTests.java new file mode 100644 index 000000000..081753578 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-account/src/test/java/org/apache/dubbo/samples/seata/AccountApplicationTests.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.dubbo.samples.seata; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AccountApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/pom.xml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/pom.xml new file mode 100644 index 000000000..11eca3ad8 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-samples-seata + 0.0.1-SNAPSHOT + + dubbo-samples-seata-api + dubbo-samples-seata-api + + + com.fasterxml.jackson.core + jackson-databind + + + diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/AccountService.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/AccountService.java new file mode 100644 index 000000000..ed89fa4c1 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/AccountService.java @@ -0,0 +1,32 @@ +/* + * 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.dubbo.samples.seata.api; + +/** + * The interface Account service. + */ +public interface AccountService { + + /** + * debit + * + * @param userId + * @param money + */ + void debit(String userId, int money); +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/BusinessService.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/BusinessService.java new file mode 100644 index 000000000..6dd6cad2b --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/BusinessService.java @@ -0,0 +1,43 @@ +/* + * 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.dubbo.samples.seata.api; + +/** + * The interface Business service. + */ +public interface BusinessService { + + /** + * purchase commit + * + * @param userId + * @param commodityCode + * @param orderCount + */ + void purchaseCommit(String userId, String commodityCode, int orderCount); + + + /** + * purchase rollback + * + * @param userId + * @param commodityCode + * @param orderCount + */ + void purchaseRollback(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/Order.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/Order.java new file mode 100644 index 000000000..161a11b65 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/Order.java @@ -0,0 +1,52 @@ +/* + * 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.dubbo.samples.seata.api; + +import java.io.Serializable; + +/** + * The type Order. + */ +public class Order implements Serializable { + /** + * The Id. + */ + public long id; + /** + * The User id. + */ + public String userId; + /** + * The Commodity code. + */ + public String commodityCode; + /** + * The Count. + */ + public int count; + /** + * The Money. + */ + public int money; + + @Override + public String toString() { + return "Order{" + "id=" + id + ", userId='" + userId + '\'' + ", commodityCode='" + commodityCode + '\'' + + ", count=" + count + ", money=" + money + '}'; + } +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/OrderService.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/OrderService.java new file mode 100644 index 000000000..cbc43d73b --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/OrderService.java @@ -0,0 +1,34 @@ +/* + * 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.dubbo.samples.seata.api; + +/** + * The interface Order service. + */ +public interface OrderService { + /** + * create order + * + * @param userId + * @param commodityCode + * @param orderCount + * @return the created order + */ + Order create(String userId, String commodityCode, int orderCount); + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/StockService.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/StockService.java new file mode 100644 index 000000000..1233a3136 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-api/src/main/java/org/apache/dubbo/samples/seata/api/StockService.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.dubbo.samples.seata.api; + +/** + * The interface Stock service. + */ +public interface StockService { + + /** + * deduct + * + * @param commodityCode + * @param count + */ + void deduct(String commodityCode, int count); + + /** + * batch deduct + * + * @param commodityCode + * @param count + */ + void batchDeduct(String commodityCode, int count); +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/pom.xml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/pom.xml new file mode 100644 index 000000000..c0c9e9a45 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/pom.xml @@ -0,0 +1,85 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-samples-seata + 0.0.1-SNAPSHOT + + dubbo-samples-seata-business + dubbo-samples-seata-business + + + + org.springframework.boot + spring-boot-starter-web + + + org.apache.dubbo + dubbo-samples-seata-api + + + org.apache.dubbo + dubbo-spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + io.seata + seata-spring-boot-starter + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + org.apache.dubbo.samples.seata.business.BusinessApplication + + + + repackage + + repackage + + + + + + + + diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/BusinessApplication.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/BusinessApplication.java new file mode 100644 index 000000000..ac14d94c3 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/BusinessApplication.java @@ -0,0 +1,32 @@ +/* + * 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.dubbo.samples.seata.business; + +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableDubbo +public class BusinessApplication { + + public static void main(String[] args) { + SpringApplication.run(BusinessApplication.class, args); + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/controller/TestController.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/controller/TestController.java new file mode 100644 index 000000000..62f66a82f --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/controller/TestController.java @@ -0,0 +1,50 @@ +/* + * 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.dubbo.samples.seata.business.controller; + +import org.apache.dubbo.samples.seata.api.BusinessService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/test") +public class TestController { + private final BusinessService businessService; + + public TestController(BusinessService businessService) { + this.businessService = businessService; + } + + @GetMapping("/commit") + public String commit(@RequestParam String userId,@RequestParam String commodityCode,@RequestParam int orderCount){ + this.businessService.purchaseCommit(userId,commodityCode,orderCount); + return "commit"; + } + + @GetMapping("/rollback") + public String rollback(@RequestParam String userId,@RequestParam String commodityCode,@RequestParam int orderCount){ + try { + this.businessService.purchaseRollback(userId,commodityCode,orderCount); + return "commit"; + }catch (Exception e){ + return "rollback"; + } + } +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/service/BusinessServiceImpl.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/service/BusinessServiceImpl.java new file mode 100644 index 000000000..c57f5b46d --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/java/org/apache/dubbo/samples/seata/business/service/BusinessServiceImpl.java @@ -0,0 +1,58 @@ +/* + * 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.dubbo.samples.seata.business.service; + +import io.seata.core.context.RootContext; +import io.seata.spring.annotation.GlobalTransactional; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.samples.seata.api.BusinessService; +import org.apache.dubbo.samples.seata.api.OrderService; +import org.apache.dubbo.samples.seata.api.StockService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class BusinessServiceImpl implements BusinessService { + + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); + + @DubboReference(check = false) + private StockService stockService; + @DubboReference(check = false) + private OrderService orderService; + + @Override + @GlobalTransactional(timeoutMills = 300000, name = "dubbo-samples-seata") + public void purchaseCommit(String userId, String commodityCode, int orderCount) { + LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); + stockService.deduct(commodityCode, orderCount); + orderService.create(userId, commodityCode, orderCount); + } + + @Override + @GlobalTransactional(timeoutMills = 300000, name = "dubbo-samples-seata") + public void purchaseRollback(String userId, String commodityCode, int orderCount) { + LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); + stockService.deduct(commodityCode, orderCount); + orderService.create(userId, commodityCode, orderCount); + throw new RuntimeException("purchase rollback!"); + + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/resources/application.yml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/resources/application.yml new file mode 100644 index 000000000..d244dcdeb --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/main/resources/application.yml @@ -0,0 +1,43 @@ +# 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. +server: + port: 9999 +spring: + application: + name: BusinessApplication +dubbo: + application: + logger: slf4j + name: ${spring.application.name} + qos-enable: false + registry: + address: multicast://224.5.6.7:1234 + protocol: + port: 20882 + name: dubbo +seata: + enabled: true + application-id: dubbo-samples-seata + tx-service-group: default_tx_group + service: + vgroup-mapping: + default_tx_group: default + grouplist: + default: ${seata.address:127.0.0.1}:${seata.port:8091} + registry: + type: file + config: + type: file diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/test/java/org/apache/dubbo/samples/seata/business/BusinessApplicationIT.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/test/java/org/apache/dubbo/samples/seata/business/BusinessApplicationIT.java new file mode 100644 index 000000000..a706519b2 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-business/src/test/java/org/apache/dubbo/samples/seata/business/BusinessApplicationIT.java @@ -0,0 +1,42 @@ +/* + * 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.dubbo.samples.seata.business; + +import org.apache.dubbo.samples.seata.api.BusinessService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class BusinessApplicationIT { + + @Autowired + private BusinessService businessService; + + @Test + void testRollback() { + Assertions.assertThrows(RuntimeException.class, () -> businessService.purchaseRollback("ACC_001", "STOCK_001", 1)); + } + + @Test + void testCommit() { + Assertions.assertDoesNotThrow(() -> businessService.purchaseCommit("ACC_001", "STOCK_001", 1)); + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/pom.xml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/pom.xml new file mode 100644 index 000000000..3d929a9be --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/pom.xml @@ -0,0 +1,93 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-samples-seata + 0.0.1-SNAPSHOT + + dubbo-samples-seata-order + dubbo-samples-seata-order + + + + org.springframework.boot + spring-boot-starter + + + org.apache.dubbo + dubbo-samples-seata-api + + + org.apache.dubbo + dubbo-spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.mysql + mysql-connector-j + + + org.springframework.boot + spring-boot-starter-jdbc + + + io.seata + seata-spring-boot-starter + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + org.apache.dubbo.samples.seata.order.OrderApplication + + + + repackage + + repackage + + + + + + + + diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/OrderApplication.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/OrderApplication.java new file mode 100644 index 000000000..df6ebff47 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/OrderApplication.java @@ -0,0 +1,32 @@ +/* + * 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.dubbo.samples.seata.order; + +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableDubbo +public class OrderApplication { + + public static void main(String[] args) { + SpringApplication.run(OrderApplication.class, args); + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/service/OrderServiceImpl.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/service/OrderServiceImpl.java new file mode 100644 index 000000000..61b69e255 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/java/org/apache/dubbo/samples/seata/order/service/OrderServiceImpl.java @@ -0,0 +1,99 @@ +/* + * 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.dubbo.samples.seata.order.service; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.samples.seata.api.AccountService; +import org.apache.dubbo.samples.seata.api.Order; +import org.apache.dubbo.samples.seata.api.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +@DubboService +public class OrderServiceImpl implements OrderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); + + @DubboReference(check = false) + private AccountService accountService; + + private final JdbcTemplate jdbcTemplate; + + public OrderServiceImpl(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public Order create(String userId, String commodityCode, int orderCount) { + LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID()); + + // 计算订单金额 + int orderMoney = calculate(commodityCode, orderCount); + + // 从账户余额扣款 + accountService.debit(userId, orderMoney); + + final Order order = new Order(); + order.userId = userId; + order.commodityCode = commodityCode; + order.count = orderCount; + order.money = orderMoney; + + KeyHolder keyHolder = new GeneratedKeyHolder(); + + LOGGER.info( + "Order Service SQL: insert into order_tbl (user_id, commodity_code, count, money) values ({}, {}, {}, {})", + userId, commodityCode, orderCount, orderMoney); + + jdbcTemplate.update(new PreparedStatementCreator() { + + @Override + public PreparedStatement createPreparedStatement(Connection con) throws SQLException { + PreparedStatement pst = con.prepareStatement( + "insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)", + PreparedStatement.RETURN_GENERATED_KEYS); + pst.setObject(1, order.userId); + pst.setObject(2, order.commodityCode); + pst.setObject(3, order.count); + pst.setObject(4, order.money); + return pst; + } + }, keyHolder); + + order.id = keyHolder.getKey().longValue(); + + LOGGER.info("Order Service End ... Created " + order); + + return order; + } + + private int calculate(String commodityId, int orderCount) { + return 200 * orderCount; + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/resources/application.yml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/resources/application.yml new file mode 100644 index 000000000..519afebfc --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/main/resources/application.yml @@ -0,0 +1,53 @@ +# 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: OrderApplication + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${mysql.address:127.0.0.1}:${mysql.port:3306}/seata?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useOldAliasMetadataBehavior=true + username: root + password: helloworld + hikari: + connection-timeout: 30000 + idle-timeout: 600000 + max-lifetime: 1800000 + maximum-pool-size: 100 + minimum-idle: 10 + pool-name: HikaraPool-1 +dubbo: + application: + logger: slf4j + name: ${spring.application.name} + qos-enable: false + registry: + address: multicast://224.5.6.7:1234 + protocol: + port: 20883 + name: dubbo +seata: + enabled: true + application-id: dubbo-samples-seata + tx-service-group: default_tx_group + service: + vgroup-mapping: + default_tx_group: default + grouplist: + default: ${seata.address:127.0.0.1}:${seata.port:8091} + registry: + type: file + config: + type: file diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/test/java/org/apache/dubbo/samples/seata/OrderApplicationTests.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/test/java/org/apache/dubbo/samples/seata/OrderApplicationTests.java new file mode 100644 index 000000000..ff77b07f3 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-order/src/test/java/org/apache/dubbo/samples/seata/OrderApplicationTests.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.dubbo.samples.seata; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class OrderApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/pom.xml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/pom.xml new file mode 100644 index 000000000..37fe39bc8 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/pom.xml @@ -0,0 +1,93 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-samples-seata + 0.0.1-SNAPSHOT + + dubbo-samples-seata-stock + dubbo-samples-seata-stock + + + + org.springframework.boot + spring-boot-starter + + + org.apache.dubbo + dubbo-samples-seata-api + + + org.apache.dubbo + dubbo-spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.mysql + mysql-connector-j + + + org.springframework.boot + spring-boot-starter-jdbc + + + io.seata + seata-spring-boot-starter + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + org.apache.dubbo.samples.seata.stock.StockApplication + + + + repackage + + repackage + + + + + + + + diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/StockApplication.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/StockApplication.java new file mode 100644 index 000000000..02c7f0063 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/StockApplication.java @@ -0,0 +1,32 @@ +/* + * 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.dubbo.samples.seata.stock; + +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableDubbo +public class StockApplication { + + public static void main(String[] args) { + SpringApplication.run(StockApplication.class, args); + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/service/StockServiceImpl.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/service/StockServiceImpl.java new file mode 100644 index 000000000..126c735b0 --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/java/org/apache/dubbo/samples/seata/stock/service/StockServiceImpl.java @@ -0,0 +1,63 @@ +/* + * 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.dubbo.samples.seata.stock.service; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.samples.seata.api.StockService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +@DubboService +public class StockServiceImpl implements StockService { + + private static final Logger LOGGER = LoggerFactory.getLogger(StockService.class); + + private final JdbcTemplate jdbcTemplate; + + public StockServiceImpl(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public void deduct(String commodityCode, int count) { + LOGGER.info("Stock Service Begin ... xid: " + RootContext.getXID()); + LOGGER.info("Deducting inventory SQL: update stock_tbl set count = count - {} where commodity_code = {}", count, + commodityCode); + + jdbcTemplate.update("update stock_tbl set count = count - ? where commodity_code = ?", + new Object[]{count, commodityCode}); + LOGGER.info("Stock Service End ... "); + + } + + @Override + public void batchDeduct(String commodityCode, int count) { + LOGGER.info("Stock Service Begin ... xid: " + RootContext.getXID()); + LOGGER.info("Deducting inventory SQL: update stock_tbl set count = count - {} where commodity_code = {}", count, + commodityCode); + + jdbcTemplate.batchUpdate( + "update stock_tbl set count = count - " + count + " where commodity_code = '" + commodityCode + "'", + "update stock_tbl set count = count - " + count + " where commodity_code = '" + commodityCode + "'"); + LOGGER.info("Stock Service End ... "); + + } + +} diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/resources/application.yml b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/resources/application.yml new file mode 100644 index 000000000..617df9e8a --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/main/resources/application.yml @@ -0,0 +1,53 @@ +# 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: StockApplication + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${mysql.address:127.0.0.1}:${mysql.port:3306}/seata?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useOldAliasMetadataBehavior=true + username: root + password: helloworld + hikari: + connection-timeout: 30000 + idle-timeout: 600000 + max-lifetime: 1800000 + maximum-pool-size: 100 + minimum-idle: 10 + pool-name: HikaraPool-1 +dubbo: + application: + logger: slf4j + name: ${spring.application.name} + qos-enable: false + registry: + address: multicast://224.5.6.7:1234 + protocol: + port: 20884 + name: dubbo +seata: + enabled: true + application-id: dubbo-samples-seata + tx-service-group: default_tx_group + service: + vgroup-mapping: + default_tx_group: default + grouplist: + default: ${seata.address:127.0.0.1}:${seata.port:8091} + registry: + type: file + config: + type: file diff --git a/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/test/java/org/apache/dubbo/samples/seata/StockApplicationTests.java b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/test/java/org/apache/dubbo/samples/seata/StockApplicationTests.java new file mode 100644 index 000000000..fda34638f --- /dev/null +++ b/at-sample/dubbo-samples-seata/dubbo-samples-seata-stock/src/test/java/org/apache/dubbo/samples/seata/StockApplicationTests.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.dubbo.samples.seata; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class StockApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/at-sample/dubbo-samples-seata/pom.xml b/at-sample/dubbo-samples-seata/pom.xml new file mode 100644 index 000000000..cab4df7b2 --- /dev/null +++ b/at-sample/dubbo-samples-seata/pom.xml @@ -0,0 +1,94 @@ + + + + 4.0.0 + org.apache.dubbo + dubbo-samples-seata + 0.0.1-SNAPSHOT + pom + dubbo-samples-seata + dubbo samples seata + + 1.8 + 1.8 + UTF-8 + UTF-8 + 3.2.10 + 2.7.10 + + + + dubbo-samples-seata-api + dubbo-samples-seata-account + dubbo-samples-seata-stock + dubbo-samples-seata-order + dubbo-samples-seata-business + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.apache.dubbo + dubbo-bom + ${dubbo.version} + pom + import + + + org.apache.dubbo + dubbo-samples-seata-api + 0.0.1-SNAPSHOT + + + org.apache.dubbo + dubbo-samples-seata-account + 0.0.1-SNAPSHOT + + + org.apache.dubbo + dubbo-samples-seata-order + 0.0.1-SNAPSHOT + + + org.apache.dubbo + dubbo-samples-seata-stock + 0.0.1-SNAPSHOT + + + org.apache.dubbo + dubbo-samples-seata-business + 0.0.1-SNAPSHOT + + + io.seata + seata-spring-boot-starter + 2.0.0 + + + + + + diff --git a/at-sample/dubbo-samples-seata/script/db/dubbo_biz.sql b/at-sample/dubbo-samples-seata/script/db/dubbo_biz.sql new file mode 100644 index 000000000..5ce0ffc83 --- /dev/null +++ b/at-sample/dubbo-samples-seata/script/db/dubbo_biz.sql @@ -0,0 +1,51 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +DROP TABLE IF EXISTS `stock_tbl`; +CREATE TABLE `stock_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY (`commodity_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `order_tbl`; +CREATE TABLE `order_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT 0, + `money` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `account_tbl`; +CREATE TABLE `account_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `money` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO account_tbl(`user_id`,`money`) VALUES('ACC_001','1000'); +INSERT INTO stock_tbl(`commodity_code`,`count`) VALUES('STOCK_001','100'); diff --git a/at-sample/dubbo-samples-seata/script/db/undo_log.sql b/at-sample/dubbo-samples-seata/script/db/undo_log.sql new file mode 100644 index 000000000..90435d295 --- /dev/null +++ b/at-sample/dubbo-samples-seata/script/db/undo_log.sql @@ -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. +-- + +CREATE TABLE IF NOT EXISTS `undo_log` +( + `branch_id` BIGINT NOT NULL COMMENT 'branch transaction id', + `xid` VARCHAR(128) NOT NULL COMMENT 'global transaction id', + `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization', + `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', + `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', + `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', + `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', + UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) + ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table'; +ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);