diff --git a/.gitignore b/.gitignore index 8902b03dd..3c090b4cf 100644 --- a/.gitignore +++ b/.gitignore @@ -61,4 +61,5 @@ Thumbs.db */.idea/ */.mvn/ +*/**/.mvn/ */target/ diff --git a/README.md b/README.md index 1f9e93dde..c7f8c5938 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,34 @@ - - -# Seata Samples - -Samples for Seata. This project contains several sub-projects, each of which is an example of integration with other -projects. - -[![Build Status](https://travis-ci.org/seata/seata-samples.svg?branch=master)](https://travis-ci.org/seata/seata-samples) -![license](https://img.shields.io/github/license/seata/seata-samples.svg) - -> Friendly note: because the project depends on too much, all Maven modules are commented out by default. -> -> You can modify [`pom.xml`](https://github.com/seata/seata-samples/blob/master/pom.xml). - -## Related repository - -* [Seata](https://github.com/seata/seata) - The Seata core project - -## Sub-projects - -* [springcloud-seata-sharding-jdbc-mybatis-plus-samples](https://github.com/wilbur-ltf/seata-samples/tree/master/springcloud-seata-sharding-jdbc-mybatis-plus-samples)Easy to understand, high availability,Integration example of [Spring Cloud](https://github.com/spring-cloud),[Seata](https://github.com/seata/seata),[ShardingJdbc](https://github.com/apache/shardingsphere),[MyBatisPlus](https://github.com/baomidou/mybatis-plus). -* [spring-cloud-alibaba-samples](https://github.com/seata/seata-samples/tree/master/spring-cloud-alibaba-samples) - - Spring Cloud Alibaba + Nacos + Dubbo + OpenFeign + Sentinel + Seata -* [dubbo](https://github.com/seata/seata-samples/tree/master/dubbo) - Integration example - of [Seata](https://github.com/seata/seata) and [Apache Dubbo](https://github.com/apache/dubbo) -* [springboot](https://github.com/seata/seata-samples/tree/master/springboot) - Integration example - of [Seata](https://github.com/seata/seata) and [Spring Boot](https://github.com/spring-projects/spring-boot/) -* [nacos](https://github.com/seata/seata-samples/tree/master/nacos) - Integration example - of [Seata](https://github.com/alibaba/fescar)、 [Apache Dubbo](https://github.com/apache/dubbo) - and [Alibaba Nacos](https://github.com/alibaba/nacos/) -* [springboot-dubbo-seata](https://github.com/seata/seata-samples/tree/master/springboot-dubbo-seata) - Integration - example of [Seata](https://github.com/seata/seata)、 [Apache Dubbo](https://github.com/apache/dubbo) - and [Spring Boot](https://github.com/spring-projects/spring-boot/) -* [nutzboot-dubbo-seata](https://github.com/seata/seata-samples/tree/master/nutzboot-dubbo-fescar) - Integration example - of [Seata](https://github.com/seata/seata)、 [Apache Dubbo](https://github.com/apache/dubbo) - and [NutzBoot](https://github.com/nutzam/nutzboot/) -* [springcloud-jpa-seata](https://github.com/seata/seata-samples/tree/master/springcloud-jpa-seata) - Integration - example of [Seata](https://github.com/Seata) and [Spring Cloud](https://github.com/spring-cloud) and JPA -* [spring-boot-multiple-datasource](./multiple-datasource) - Integration example of [Seata](https://github.com/Seata) - and [Spring Boot](https://github.com/spring-projects/spring-boot/) with multiple datasource and MyBatis -* [springboot-mybatis](https://github.com/seata/seata-samples/tree/master/springboot-mybatis) - Integration example - of [Seata](https://github.com/Seata) and [Spring Boot](https://github.com/spring-projects/spring-boot/) - and [Mybatis](https://github.com/mybatis/mybatis-3) -* [api](https://github.com/seata/seata-samples/tree/master/api) - Non-Spring environment uses api to build Seata - distributed transactions -* [spring-boot-multiple-datasource-mybatis-plus](./multiple-datasource-mybatis-plus) - Integration example - of [Seata](https://github.com/Seata) and [Spring Boot](https://github.com/spring-projects/spring-boot/) with multiple - datasource and [MyBatisPlus](https://github.com/baomidou/mybatis-plus) -* [springcloud-nacos-seata](https://github.com/seata/seata-samples/tree/master/springcloud-nacos-seata) - Integration - example of [Seata](https://github.com/Seata) and [Spring Cloud](https://github.com/spring-cloud) - and [Alibaba Nacos](https://github.com/alibaba/nacos/) -* [saga](https://github.com/seata/seata-samples/tree/master/saga) - Saga mode distributed transaction demo projects -* [dubbo-multiple-datasource-mybatis-plus](https://github.com/seata/seata-samples/tree/master/dubbo-multiple-datasource-mybatis-plus) Integration example of [Seata](https://github.com/Seata) and [Spring Boot](https://github.com/spring-projects/spring-boot/) [Apache Dubbo](https://github.com/apache/dubbo) with [dynamic](https://github.com/baomidou/dynamic-datasource-spring-boot-starter) multiple datasource and [MyBatisPlus](https://github.com/baomidou/mybatis-plus) and [Alibaba Nacos](https://github.com/alibaba/nacos/) - -## Guide - -- [Quick integration with Spring Cloud](./doc/quick-integration-with-spring-cloud.md) +# samples code specification + +## Directory Structure + +The first and second levels are more of a directory + +Top level: seata-samples + +Second layer: at-sample, tcc-sample, saga-sample, xa-sample + +Third floor, The third layer is the specific sample and the naming convention is as follows: + +## naming + +naming with framework: spring-nacos-seata, springboot-naocs-zk-seata ... + +## dependency + +pom: The dependencies of each sample should be independent and should not depend on the dependencies of the parent pom of seata samples. + + + +# samples transaction model +https://seata.apache.org/docs/user/quickstart/ + +## start sequence + +1、account + +2、storage + +3、order + +4、business \ No newline at end of file diff --git a/api/pom.xml b/api/pom.xml deleted file mode 100644 index f24eaee20..000000000 --- a/api/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - seata-samples - io.seata - 1.1.0 - - 4.0.0 - seata-samples-api - jar - seata-samples-api ${project.version} - - - - io.seata - seata-all - - - com.alibaba - druid - - - mysql - mysql-connector-java - ${mysql-connector.version} - - - com.fasterxml.jackson.core - jackson-databind - - - - \ No newline at end of file diff --git a/api/src/main/java/io/seata/samples/api/Bussiness.java b/api/src/main/java/io/seata/samples/api/Bussiness.java deleted file mode 100644 index b130ad9a9..000000000 --- a/api/src/main/java/io/seata/samples/api/Bussiness.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api; - -import java.sql.SQLException; -import java.util.concurrent.TimeUnit; - -import io.seata.core.exception.TransactionException; -import io.seata.rm.RMClient; -import io.seata.samples.api.service.AccountService; -import io.seata.samples.api.service.OrderService; -import io.seata.samples.api.service.StockService; -import io.seata.samples.api.service.impl.AccountServiceImpl; -import io.seata.samples.api.service.impl.OrderServiceImpl; -import io.seata.samples.api.service.impl.StockServiceImpl; -import io.seata.tm.TMClient; -import io.seata.tm.api.GlobalTransaction; -import io.seata.tm.api.GlobalTransactionContext; - -/** - * The type Bussiness. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 使用api 构建 单体应用多数据源分布式事务 非spring环境 - */ -public class Bussiness { - - /** - * The entry point of application. - * - * @param args the input arguments - * @throws SQLException the sql exception - * @throws TransactionException the transaction exception - */ - public static void main(String[] args) throws SQLException, TransactionException, InterruptedException { - - String userId = "U100001"; - String commodityCode = "C00321"; - int commodityCount = 100; - int money = 999; - AccountService accountService = new AccountServiceImpl(); - StockService stockService = new StockServiceImpl(); - OrderService orderService = new OrderServiceImpl(); - orderService.setAccountService(accountService); - - //reset data - accountService.reset(userId, String.valueOf(money)); - stockService.reset(commodityCode, String.valueOf(commodityCount)); - orderService.reset(null, null); - - //init seata; only once - String applicationId = "api"; - String txServiceGroup = "my_test_tx_group"; - TMClient.init(applicationId, txServiceGroup); - RMClient.init(applicationId, txServiceGroup); - - //trx - GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate(); - try { - tx.begin(60000, "testBiz"); - System.out.println("begin trx, xid is " + tx.getXid()); - - //biz operate 3 dataSources - //set >=5 will be rollback(200*5>999) else will be commit - int opCount = 5; - stockService.deduct(commodityCode, opCount); - orderService.create(userId, commodityCode, opCount); - - //check data if negative - boolean needCommit = ((StockServiceImpl)stockService).validNegativeCheck("count", commodityCode) - && ((AccountServiceImpl)accountService).validNegativeCheck("money", userId); - - //if data negative rollback else commit - if (needCommit) { - tx.commit(); - } else { - System.out.println("rollback trx, cause: data negative, xid is " + tx.getXid()); - tx.rollback(); - } - } catch (Exception exx) { - System.out.println("rollback trx, cause: " + exx.getMessage() + " , xid is " + tx.getXid()); - tx.rollback(); - throw exx; - } - TimeUnit.SECONDS.sleep(10); - - } -} diff --git a/api/src/main/java/io/seata/samples/api/service/AbstractDataCheck.java b/api/src/main/java/io/seata/samples/api/service/AbstractDataCheck.java deleted file mode 100644 index 1f447bd04..000000000 --- a/api/src/main/java/io/seata/samples/api/service/AbstractDataCheck.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service; - -import java.sql.SQLException; - -/** - * The type Abstract data check. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public abstract class AbstractDataCheck { - - /** - * Valid negative check boolean. - * - * @param field the field - * @param id the id - * @return the boolean - */ - public boolean validNegativeCheck(String field, String id) throws SQLException { - return doNegativeCheck(field, id) >= 0; - } - - /** - * Do negative check int. - * - * @param field the field - * @param id the id - * @return the int - * @throws SQLException the sql exception - */ - public abstract int doNegativeCheck(String field, String id) throws SQLException; -} diff --git a/api/src/main/java/io/seata/samples/api/service/AccountService.java b/api/src/main/java/io/seata/samples/api/service/AccountService.java deleted file mode 100644 index 2a0cafa12..000000000 --- a/api/src/main/java/io/seata/samples/api/service/AccountService.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service; - -import java.sql.SQLException; - -/** - * The interface Account service. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public interface AccountService extends DataResetService { - /** - * Reduce. - * - * @param userId the user id - * @param money the money - * @throws SQLException the sql exception - */ - void reduce(String userId, int money) throws SQLException; -} diff --git a/api/src/main/java/io/seata/samples/api/service/DataResetService.java b/api/src/main/java/io/seata/samples/api/service/DataResetService.java deleted file mode 100644 index decaf5f6c..000000000 --- a/api/src/main/java/io/seata/samples/api/service/DataResetService.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service; - -import java.sql.SQLException; - -/** - * The interface Data reset service. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public interface DataResetService { - /** - * Reset. - * - * @param key the key - * @param value the value - * @throws SQLException the sql exception - */ - void reset(String key, String value) throws SQLException; -} diff --git a/api/src/main/java/io/seata/samples/api/service/OrderService.java b/api/src/main/java/io/seata/samples/api/service/OrderService.java deleted file mode 100644 index 2bdfd0af1..000000000 --- a/api/src/main/java/io/seata/samples/api/service/OrderService.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service; - -import java.sql.SQLException; - -/** - * The interface Order service. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public interface OrderService extends DataResetService { - /** - * Sets account service. - * - * @param accountService the account service - */ - void setAccountService(AccountService accountService); - - /** - * Create. - * - * @param userId the user id - * @param commodityCode the commodity code - * @param count the count - * @throws SQLException the sql exception - */ - void create(String userId, String commodityCode, Integer count) throws SQLException; -} diff --git a/api/src/main/java/io/seata/samples/api/service/StockService.java b/api/src/main/java/io/seata/samples/api/service/StockService.java deleted file mode 100644 index d2e04746e..000000000 --- a/api/src/main/java/io/seata/samples/api/service/StockService.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service; - -import java.sql.SQLException; - -/** - * The interface Stock service. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public interface StockService extends DataResetService { - /** - * Deduct. - * - * @param commodityCode the commodity code - * @param count the count - * @throws SQLException the sql exception - */ - void deduct(String commodityCode, int count) throws SQLException; -} diff --git a/api/src/main/java/io/seata/samples/api/service/impl/AccountServiceImpl.java b/api/src/main/java/io/seata/samples/api/service/impl/AccountServiceImpl.java deleted file mode 100644 index ff633e970..000000000 --- a/api/src/main/java/io/seata/samples/api/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service.impl; - -import java.sql.SQLException; - -import io.seata.samples.api.service.AbstractDataCheck; -import io.seata.samples.api.service.AccountService; -import io.seata.samples.api.utils.DataSourceUtil; - -/** - * The type Account service. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public class AccountServiceImpl extends AbstractDataCheck implements AccountService { - - /** - * The constant DB_KEY. - */ - public static final String DB_KEY = "account"; - - @Override - public void reduce(String userId, int money) throws SQLException { - String sql = "update account_tbl set money = money - " + money + " where user_id = '" + userId + "'"; - DataSourceUtil.executeUpdate(DB_KEY, sql); - } - - @Override - public int doNegativeCheck(String field, String id) throws SQLException { - String checkSql = "select " + field + " from account_tbl where user_id='" + id + "'"; - String result = DataSourceUtil.getSingleResult(DB_KEY, checkSql); - return Integer.parseInt(result); - } - - @Override - public void reset(String key, String value) throws SQLException { - String deleteSql = "delete from account_tbl where user_id = '" + key + "'"; - String insertSql = "insert into account_tbl(user_id, money) values ('" + key + "', " + value + ")"; - DataSourceUtil.executeUpdate(DB_KEY, deleteSql); - DataSourceUtil.executeUpdate(DB_KEY, insertSql); - } -} diff --git a/api/src/main/java/io/seata/samples/api/service/impl/OrderServiceImpl.java b/api/src/main/java/io/seata/samples/api/service/impl/OrderServiceImpl.java deleted file mode 100644 index 164998b21..000000000 --- a/api/src/main/java/io/seata/samples/api/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service.impl; - -import java.sql.SQLException; - -import io.seata.samples.api.service.AccountService; -import io.seata.samples.api.service.OrderService; -import io.seata.samples.api.utils.DataSourceUtil; - -/** - * The type Order service. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public class OrderServiceImpl implements OrderService { - - /** - * The constant DB_KEY. - */ - public static final String DB_KEY = "order"; - private AccountService accountService; - - @Override - public void setAccountService(AccountService accountService) { - this.accountService = accountService; - } - - @Override - public void create(String userId, String commodityCode, Integer count) throws SQLException { - int money = count * 200; - String sql = "insert into order_tbl (user_id, commodity_code, count, money) values ('" + userId + "','" - + commodityCode + "'," + count + "," + money + ")"; - DataSourceUtil.executeUpdate(DB_KEY, sql); - accountService.reduce(userId, money); - - } - - @Override - public void reset(String key, String value) throws SQLException { - String deleteSql = "delete from order_tbl"; - DataSourceUtil.executeUpdate(DB_KEY, deleteSql); - } -} diff --git a/api/src/main/java/io/seata/samples/api/service/impl/StockServiceImpl.java b/api/src/main/java/io/seata/samples/api/service/impl/StockServiceImpl.java deleted file mode 100644 index 6c8c67fa6..000000000 --- a/api/src/main/java/io/seata/samples/api/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.service.impl; - -import java.sql.SQLException; - -import io.seata.samples.api.service.AbstractDataCheck; -import io.seata.samples.api.service.StockService; -import io.seata.samples.api.utils.DataSourceUtil; - -/** - * The type Stock service. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public class StockServiceImpl extends AbstractDataCheck implements StockService { - /** - * The constant DB_KEY. - */ - public static final String DB_KEY = "stock"; - - @Override - public void deduct(String commodityCode, int count) throws SQLException { - String sql = "update stock_tbl set count = count - " + count + " where commodity_code = '" + commodityCode - + "'"; - DataSourceUtil.executeUpdate(DB_KEY, sql); - } - - @Override - public void reset(String key, String value) throws SQLException { - String deleteSql = "delete from stock_tbl where commodity_code = '" + key + "'"; - String insertSql = "insert into stock_tbl(commodity_code, count) values ('" + key + "', " + value + ")"; - DataSourceUtil.executeUpdate(DB_KEY, deleteSql); - DataSourceUtil.executeUpdate(DB_KEY, insertSql); - } - - @Override - public int doNegativeCheck(String field, String id) throws SQLException { - String checkSql = "select " + field + " from stock_tbl where commodity_code='" + id + "'"; - String result = DataSourceUtil.getSingleResult(DB_KEY, checkSql); - return Integer.parseInt(result); - } -} diff --git a/api/src/main/java/io/seata/samples/api/utils/DataSourceUtil.java b/api/src/main/java/io/seata/samples/api/utils/DataSourceUtil.java deleted file mode 100644 index fbc8295b5..000000000 --- a/api/src/main/java/io/seata/samples/api/utils/DataSourceUtil.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.utils; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.sql.DataSource; - -import com.alibaba.druid.pool.DruidDataSource; - -import io.seata.rm.datasource.DataSourceProxy; - -/** - * The type Data source util. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public class DataSourceUtil { - - /** - * The constant JDBC_PRO_PATH. - */ - public static final String JDBC_PRO_PATH = "jdbc.properties"; - /** - * The constant DATA_SOURCE_MAP. - */ - public static final ConcurrentMap DATA_SOURCE_MAP = new ConcurrentHashMap<>(); - - /** - * Gets data source. - * - * @param name the name - * @return the data source - */ - public static DataSource getDataSource(String name) { - String driverKey = "jdbc." + name + ".driver"; - String urlKey = "jdbc." + name + ".url"; - String userNameKey = "jdbc." + name + ".username"; - String pwdKey = "jdbc." + name + ".password"; - DataSource dataSource = new DruidDataSource(); - ((DruidDataSource)dataSource).setDriverClassName(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, driverKey)); - ((DruidDataSource)dataSource).setUrl(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, urlKey)); - ((DruidDataSource)dataSource).setUsername(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, userNameKey)); - ((DruidDataSource)dataSource).setPassword(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, pwdKey)); - return new DataSourceProxy(dataSource); - } - - /** - * Gets connection. - * - * @param name the name - * @return the connection - * @throws SQLException the sql exception - */ - public static Connection getConnection(String name) throws SQLException { - return DATA_SOURCE_MAP.computeIfAbsent(name, s -> getDataSource(name)).getConnection(); - } - - /** - * Execute update int. - * - * @param name the name - * @param sql the sql - * @return the int - * @throws SQLException the sql exception - */ - public static int executeUpdate(String name, String sql) throws SQLException { - Connection connection = null; - Statement statement = null; - int result = 0; - try { - connection = getConnection(name); - statement = connection.createStatement(); - result = statement.executeUpdate(sql); - - } catch (SQLException exx) { - //todo - throw exx; - } finally { - try { - if (statement != null) { - statement.close(); - } - if (connection != null) { - connection.close(); - } - } catch (SQLException exx) { - } - } - return result; - } - - /** - * Gets single result. - * - * @param name the name - * @param sql the sql - * @return the single result - * @throws SQLException the sql exception - */ - public static String getSingleResult(String name, String sql) throws SQLException { - Connection connection = null; - Statement statement = null; - String result = null; - try { - connection = getConnection(name); - statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery(sql); - resultSet.next(); - result = resultSet.getString(1); - } catch (SQLException exx) { - //todo - throw exx; - } finally { - try { - if (statement != null) { - statement.close(); - } - if (connection != null) { - connection.close(); - } - } catch (SQLException exx) { - } - } - return result; - } -} diff --git a/api/src/main/java/io/seata/samples/api/utils/PropertiesUtil.java b/api/src/main/java/io/seata/samples/api/utils/PropertiesUtil.java deleted file mode 100644 index 383bed6fb..000000000 --- a/api/src/main/java/io/seata/samples/api/utils/PropertiesUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.api.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -/** - * The type Properties util. - * - * @author jimin.jm @alibaba-inc.com - * @date 2019 /08/21 - */ -public class PropertiesUtil { - - /** - * Gets propertie value. - * - * @param path the path - * @param key the key - * @return the propertie value - */ - public static String getPropertieValue(String path, String key) { - return getPropertieValue(path, key, null); - - } - - /** - * Gets propertie value. - * - * @param path the path - * @param key the key - * @param defaultValue the default value - * @return the propertie value - */ - public static String getPropertieValue(String path, String key, String defaultValue) { - Properties properties = new Properties(); - InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream(path); - try { - properties.load(in); - } catch (IOException ignore) { - } - String value = properties.getProperty(key); - return value == null ? defaultValue : value; - } -} - diff --git a/api/src/main/resources/all.sql b/api/src/main/resources/all.sql deleted file mode 100644 index b6ae6fb9f..000000000 --- a/api/src/main/resources/all.sql +++ /dev/null @@ -1,41 +0,0 @@ -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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - -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` (`commodity_code`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - -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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - -CREATE TABLE `undo_log` -( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `branch_id` bigint(20) NOT NULL, - `xid` varchar(100) NOT NULL, - `context` varchar(128) NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int(11) NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - `ext` varchar(100) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/api/src/main/resources/file.conf b/api/src/main/resources/file.conf deleted file mode 100644 index c960c460a..000000000 --- a/api/src/main/resources/file.conf +++ /dev/null @@ -1,10 +0,0 @@ -service { - #vgroup->rgroup - vgroupMapping.my_test_tx_group = "default" - #only support single node - default.grouplist = "127.0.0.1:8091" - #degrade current not support - enableDegrade = false - #disable - disable = false -} diff --git a/api/src/main/resources/jdbc.properties b/api/src/main/resources/jdbc.properties deleted file mode 100644 index 81563eda5..000000000 --- a/api/src/main/resources/jdbc.properties +++ /dev/null @@ -1,14 +0,0 @@ -jdbc.account.url=jdbc:mysql://rm-2zetd9474ydd1g5955o.mysql.rds.aliyuncs.com:3306/fescar?useSSL=false&serverTimezone=UTC -jdbc.account.username=workshop -jdbc.account.password=Workshop123 -jdbc.account.driver=com.mysql.jdbc.Driver -# stock db config -jdbc.stock.url=jdbc:mysql://rm-2zetd9474ydd1g5955o.mysql.rds.aliyuncs.com:3306/fescar?useSSL=false&serverTimezone=UTC -jdbc.stock.username=workshop -jdbc.stock.password=Workshop123 -jdbc.stock.driver=com.mysql.jdbc.Driver -# order db config -jdbc.order.url=jdbc:mysql://rm-2zetd9474ydd1g5955o.mysql.rds.aliyuncs.com:3306/fescar?useSSL=false&serverTimezone=UTC -jdbc.order.username=workshop -jdbc.order.password=Workshop123 -jdbc.order.driver=com.mysql.jdbc.Driver \ No newline at end of file diff --git a/api/src/main/resources/registry.conf b/api/src/main/resources/registry.conf deleted file mode 100644 index c640e3a63..000000000 --- a/api/src/main/resources/registry.conf +++ /dev/null @@ -1,82 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "file" - - nacos { - serverAddr = "localhost" - namespace = "" - cluster = "default" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - password = "" - cluster = "default" - timeout = "0" - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig - type = "file" - - nacos { - serverAddr = "localhost" - namespace = "" - group = "SEATA_GROUP" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - app.id = "seata-server" - apollo.meta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/at-sample/at-api/pom.xml b/at-sample/at-api/pom.xml new file mode 100644 index 000000000..77cbdcd14 --- /dev/null +++ b/at-sample/at-api/pom.xml @@ -0,0 +1,79 @@ + + + + 4.0.0 + org.apache.seata + at-api + 2.0.0 + + + UTF-8 + UTF-8 + 1.8 + 1.8 + + + + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + + + + org.slf4j + jcl-over-slf4j + 1.7.32 + + + org.slf4j + log4j-over-slf4j + 1.7.32 + + + + + io.seata + seata-all + 2.0.0 + + + + com.fasterxml.jackson.core + jackson-databind + 2.13.5 + + + + mysql + mysql-connector-java + 5.1.42 + + + \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/BusinessService.java b/at-sample/at-api/src/main/java/org/apache/seata/api/BusinessService.java new file mode 100644 index 000000000..e1e7cb566 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/BusinessService.java @@ -0,0 +1,121 @@ +/* + * 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.seata.api; + +import io.seata.core.exception.TransactionException; +import io.seata.core.rpc.netty.RmNettyRemotingClient; +import io.seata.rm.RMClient; +import io.seata.tm.TMClient; +import io.seata.tm.api.GlobalTransaction; +import io.seata.tm.api.GlobalTransactionContext; +import org.apache.seata.api.service.OrderService; +import org.apache.seata.api.service.impl.AccountServiceImpl; +import org.apache.seata.api.service.impl.OrderServiceImpl; +import org.apache.seata.api.service.impl.StorageServiceImpl; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.sql.SQLException; +import java.util.concurrent.TimeUnit; + +/** + * The type Bussiness. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 使用api 构建 单体应用多数据源分布式事务 非spring环境 + */ +public class BusinessService { + + /** + * The entry point of application. + * + * @param args the input arguments + * @throws SQLException the sql exception + * @throws TransactionException the transaction exception + * @throws InterruptedException the interrupted exception + */ + public static void main(String[] args) throws SQLException, TransactionException, InterruptedException { + // init tm client and rm client, only once + String applicationId = "api"; + String txServiceGroup = "my_test_tx_group"; + TMClient.init(applicationId, txServiceGroup); + RMClient.init(applicationId, txServiceGroup); + + RmNettyRemotingClient rmNettyRemotingClient = RmNettyRemotingClient.getInstance(); + Class rmRemoteClass = rmNettyRemotingClient.getClass(); + ReflectionUtils.doWithFields(rmRemoteClass, field -> { + if (field.getName().equals("clientChannelManager")) { + field.setAccessible(true); + //channelManger + Object o = field.get(rmNettyRemotingClient); + Method reconnect; + try { + reconnect = o.getClass().getDeclaredMethod("reconnect", String.class); + reconnect.setAccessible(true); + reconnect.invoke(o, "default_tx_group"); + } catch (Exception e) { + throw new RuntimeException("reconnect failed!", e); + } + } + }); + + String userId = "U100001"; + String commodityCode = "C00321"; + int commodityCount = 100; + int money = 999; + AccountServiceImpl accountService = new AccountServiceImpl(); + StorageServiceImpl stockService = new StorageServiceImpl(); + OrderService orderService = new OrderServiceImpl(); + orderService.setAccountService(accountService); + + //reset data + accountService.reset(userId, String.valueOf(money)); + stockService.reset(commodityCode, String.valueOf(commodityCount)); + orderService.reset(null, null); + + //trx + GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate(); + try { + tx.begin(60000, "testBiz"); + System.out.println("begin trx, xid is " + tx.getXid()); + + //biz operate 3 dataSources + //set >=5 will be rollback(200*5>999) else will be commit + int opCount = 5; + stockService.deduct(commodityCode, opCount); + orderService.create(userId, commodityCode, opCount); + + //check data if negative + boolean needCommit = stockService.validNegativeCheck("count", commodityCode) + && accountService.validNegativeCheck("money", userId); + + //if data negative rollback else commit + if (needCommit) { + tx.commit(); + } else { + System.out.println("rollback trx, cause: data negative, xid is " + tx.getXid()); + tx.rollback(); + } + } catch (Exception exx) { + System.out.println("rollback trx, cause: " + exx.getMessage() + " , xid is " + tx.getXid()); + tx.rollback(); + throw exx; + } + TimeUnit.SECONDS.sleep(10); + + } +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/AbstractDataCheck.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/AbstractDataCheck.java new file mode 100644 index 000000000..8d75609a5 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/AbstractDataCheck.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.api.service; + +import java.sql.SQLException; + +/** + * The type Abstract data check. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public abstract class AbstractDataCheck { + + /** + * Valid negative check boolean. + * + * @param field the field + * @param id the id + * @return the boolean + */ + public boolean validNegativeCheck(String field, String id) throws SQLException { + return doNegativeCheck(field, id) >= 0; + } + + /** + * Do negative check int. + * + * @param field the field + * @param id the id + * @return the int + * @throws SQLException the sql exception + */ + public abstract int doNegativeCheck(String field, String id) throws SQLException; +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/AccountService.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/AccountService.java new file mode 100644 index 000000000..6a03c2112 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/AccountService.java @@ -0,0 +1,36 @@ +/* + * 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.seata.api.service; + +import java.sql.SQLException; + +/** + * The interface Account service. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public interface AccountService extends DataResetService { + /** + * Reduce. + * + * @param userId the user id + * @param money the money + * @throws SQLException the sql exception + */ + void reduce(String userId, int money) throws SQLException; +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/DataResetService.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/DataResetService.java new file mode 100644 index 000000000..afcf98ddf --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/DataResetService.java @@ -0,0 +1,36 @@ +/* + * 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.seata.api.service; + +import java.sql.SQLException; + +/** + * The interface Data reset service. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public interface DataResetService { + /** + * Reset. + * + * @param key the key + * @param value the value + * @throws SQLException the sql exception + */ + void reset(String key, String value) throws SQLException; +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/OrderService.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/OrderService.java new file mode 100644 index 000000000..b1437d33f --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/OrderService.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.api.service; + +import java.sql.SQLException; + +/** + * The interface Order service. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public interface OrderService extends DataResetService { + /** + * Sets account service. + * + * @param accountService the account service + */ + void setAccountService(AccountService accountService); + + /** + * Create. + * + * @param userId the user id + * @param commodityCode the commodity code + * @param count the count + * @throws SQLException the sql exception + */ + void create(String userId, String commodityCode, Integer count) throws SQLException; +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/StorageService.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/StorageService.java new file mode 100644 index 000000000..5d7617e11 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/StorageService.java @@ -0,0 +1,36 @@ +/* + * 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.seata.api.service; + +import java.sql.SQLException; + +/** + * The interface Stock service. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public interface StorageService extends DataResetService { + /** + * Deduct. + * + * @param commodityCode the commodity code + * @param count the count + * @throws SQLException the sql exception + */ + void deduct(String commodityCode, int count) throws SQLException; +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/AccountServiceImpl.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/AccountServiceImpl.java new file mode 100644 index 000000000..ce614fc78 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/AccountServiceImpl.java @@ -0,0 +1,59 @@ +/* + * 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.seata.api.service.impl; + +import org.apache.seata.api.service.AbstractDataCheck; +import org.apache.seata.api.service.AccountService; +import org.apache.seata.api.utils.DataSourceUtil; + +import java.sql.SQLException; + + +/** + * The type Account service. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public class AccountServiceImpl extends AbstractDataCheck implements AccountService { + + /** + * The constant DB_KEY. + */ + public static final String DB_KEY = "account"; + + @Override + public void reduce(String userId, int money) throws SQLException { + String sql = "update account_tbl set money = money - " + money + " where user_id = '" + userId + "'"; + DataSourceUtil.executeUpdate(DB_KEY, sql); + } + + @Override + public int doNegativeCheck(String field, String id) throws SQLException { + String checkSql = "select " + field + " from account_tbl where user_id='" + id + "'"; + String result = DataSourceUtil.getSingleResult(DB_KEY, checkSql); + return Integer.parseInt(result); + } + + @Override + public void reset(String key, String value) throws SQLException { + String deleteSql = "delete from account_tbl where user_id = '" + key + "'"; + String insertSql = "insert into account_tbl(user_id, money) values ('" + key + "', " + value + ")"; + DataSourceUtil.executeUpdate(DB_KEY, deleteSql); + DataSourceUtil.executeUpdate(DB_KEY, insertSql); + } +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/OrderServiceImpl.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..d66fce2cf --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/OrderServiceImpl.java @@ -0,0 +1,60 @@ +/* + * 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.seata.api.service.impl; + +import org.apache.seata.api.service.AccountService; +import org.apache.seata.api.service.OrderService; +import org.apache.seata.api.utils.DataSourceUtil; + +import java.sql.SQLException; + + +/** + * The type Order service. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public class OrderServiceImpl implements OrderService { + + /** + * The constant DB_KEY. + */ + public static final String DB_KEY = "order"; + private AccountService accountService; + + @Override + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + + @Override + public void create(String userId, String commodityCode, Integer count) throws SQLException { + int money = count * 200; + String sql = "insert into order_tbl (user_id, commodity_code, count, money) values ('" + userId + "','" + + commodityCode + "'," + count + "," + money + ")"; + DataSourceUtil.executeUpdate(DB_KEY, sql); + accountService.reduce(userId, money); + + } + + @Override + public void reset(String key, String value) throws SQLException { + String deleteSql = "delete from order_tbl"; + DataSourceUtil.executeUpdate(DB_KEY, deleteSql); + } +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/StorageServiceImpl.java b/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/StorageServiceImpl.java new file mode 100644 index 000000000..280038ef1 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/service/impl/StorageServiceImpl.java @@ -0,0 +1,60 @@ +/* + * 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.seata.api.service.impl; + +import org.apache.seata.api.service.AbstractDataCheck; +import org.apache.seata.api.service.StorageService; +import org.apache.seata.api.utils.DataSourceUtil; + +import java.sql.SQLException; + + + +/** + * The type Stock service. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public class StorageServiceImpl extends AbstractDataCheck implements StorageService { + /** + * The constant DB_KEY. + */ + public static final String DB_KEY = "stock"; + + @Override + public void deduct(String commodityCode, int count) throws SQLException { + String sql = "update stock_tbl set count = count - " + count + " where commodity_code = '" + commodityCode + + "'"; + DataSourceUtil.executeUpdate(DB_KEY, sql); + } + + @Override + public void reset(String key, String value) throws SQLException { + String deleteSql = "delete from stock_tbl where commodity_code = '" + key + "'"; + String insertSql = "insert into stock_tbl(commodity_code, count) values ('" + key + "', " + value + ")"; + DataSourceUtil.executeUpdate(DB_KEY, deleteSql); + DataSourceUtil.executeUpdate(DB_KEY, insertSql); + } + + @Override + public int doNegativeCheck(String field, String id) throws SQLException { + String checkSql = "select " + field + " from stock_tbl where commodity_code='" + id + "'"; + String result = DataSourceUtil.getSingleResult(DB_KEY, checkSql); + return Integer.parseInt(result); + } +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/utils/DataSourceUtil.java b/at-sample/at-api/src/main/java/org/apache/seata/api/utils/DataSourceUtil.java new file mode 100644 index 000000000..6e4d647e3 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/utils/DataSourceUtil.java @@ -0,0 +1,139 @@ +/* + * 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.seata.api.utils; + +import com.alibaba.druid.pool.DruidDataSource; +import io.seata.rm.datasource.DataSourceProxy; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * The type Data source util. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public class DataSourceUtil { + + /** + * The constant JDBC_PRO_PATH. + */ + public static final String JDBC_PRO_PATH = "jdbc.properties"; + /** + * The constant DATA_SOURCE_MAP. + */ + public static final ConcurrentMap DATA_SOURCE_MAP = new ConcurrentHashMap<>(); + + /** + * Gets data source. + * + * @param name the name + * @return the data source + */ + public static DataSource getDataSource(String name) { + String driverKey = "jdbc." + name + ".driver"; + String urlKey = "jdbc." + name + ".url"; + String userNameKey = "jdbc." + name + ".username"; + String pwdKey = "jdbc." + name + ".password"; + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setDriverClassName(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, driverKey)); + dataSource.setUrl(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, urlKey)); + dataSource.setUsername(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, userNameKey)); + dataSource.setPassword(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, pwdKey)); + return new DataSourceProxy(dataSource); + } + + /** + * Gets connection. + * + * @param name the name + * @return the connection + * @throws SQLException the sql exception + */ + public static Connection getConnection(String name) throws SQLException { + return DATA_SOURCE_MAP.computeIfAbsent(name, s -> getDataSource(name)).getConnection(); + } + + /** + * Execute update int. + * + * @param name the name + * @param sql the sql + * @return the int + * @throws SQLException the sql exception + */ + public static int executeUpdate(String name, String sql) throws SQLException { + Connection connection = null; + Statement statement = null; + int result; + try { + connection = getConnection(name); + statement = connection.createStatement(); + result = statement.executeUpdate(sql); + + } finally { + try { + if (statement != null) { + statement.close(); + } + if (connection != null) { + connection.close(); + } + } catch (SQLException ignore) { + } + } + return result; + } + + /** + * Gets single result. + * + * @param name the name + * @param sql the sql + * @return the single result + * @throws SQLException the sql exception + */ + public static String getSingleResult(String name, String sql) throws SQLException { + Connection connection = null; + Statement statement = null; + String result; + try { + connection = getConnection(name); + statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(sql); + resultSet.next(); + result = resultSet.getString(1); + } finally { + try { + if (statement != null) { + statement.close(); + } + if (connection != null) { + connection.close(); + } + } catch (SQLException ignore) { + } + } + return result; + } +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/java/org/apache/seata/api/utils/PropertiesUtil.java b/at-sample/at-api/src/main/java/org/apache/seata/api/utils/PropertiesUtil.java new file mode 100644 index 000000000..da78b71d6 --- /dev/null +++ b/at-sample/at-api/src/main/java/org/apache/seata/api/utils/PropertiesUtil.java @@ -0,0 +1,61 @@ +/* + * 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.seata.api.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * The type Properties util. + * + * @author jimin.jm @alibaba-inc.com + * @date 2019 /08/21 + */ +public class PropertiesUtil { + + /** + * Gets propertie value. + * + * @param path the path + * @param key the key + * @return the propertie value + */ + public static String getPropertieValue(String path, String key) { + return getPropertieValue(path, key, null); + + } + + /** + * Gets propertie value. + * + * @param path the path + * @param key the key + * @param defaultValue the default value + * @return the propertie value + */ + public static String getPropertieValue(String path, String key, String defaultValue) { + Properties properties = new Properties(); + InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream(path); + try { + properties.load(in); + } catch (IOException ignore) { + } + String value = properties.getProperty(key); + return value == null ? defaultValue : value; + } +} \ No newline at end of file diff --git a/at-sample/at-api/src/main/resources/all.sql b/at-sample/at-api/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/at-api/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/at-api/src/main/resources/file.conf b/at-sample/at-api/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/at-api/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/at-api/src/main/resources/jdbc.properties b/at-sample/at-api/src/main/resources/jdbc.properties new file mode 100644 index 000000000..060fd963e --- /dev/null +++ b/at-sample/at-api/src/main/resources/jdbc.properties @@ -0,0 +1,14 @@ +jdbc.account.url=jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&serverTimezone=UTC +jdbc.account.username=root +jdbc.account.password=123456 +jdbc.account.driver=com.mysql.jdbc.Driver +# stock db config +jdbc.stock.url=jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&serverTimezone=UTC +jdbc.stock.username=root +jdbc.stock.password=123456 +jdbc.stock.driver=com.mysql.jdbc.Driver +# order db config +jdbc.order.url=jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&serverTimezone=UTC +jdbc.order.username=root +jdbc.order.password=123456 +jdbc.order.driver=com.mysql.jdbc.Driver \ No newline at end of file diff --git a/at-sample/at-api/src/main/resources/registry.conf b/at-sample/at-api/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/at-api/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/spring-dubbo-seata/pom.xml b/at-sample/spring-dubbo-seata/pom.xml new file mode 100644 index 000000000..563e247fc --- /dev/null +++ b/at-sample/spring-dubbo-seata/pom.xml @@ -0,0 +1,104 @@ + + + + 4.0.0 + + org.apache.seata + spring-dubbo-seata + 2.0.0 + + + UTF-8 + UTF-8 + 1.8 + 1.8 + + + + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + + + + org.slf4j + jcl-over-slf4j + 1.7.32 + + + org.slf4j + log4j-over-slf4j + 1.7.32 + + + + + io.seata + seata-all + 2.0.0 + + + + org.springframework + spring-jdbc + 5.3.20 + + + + com.fasterxml.jackson.core + jackson-databind + 2.13.5 + + + + mysql + mysql-connector-java + 5.1.42 + + + + org.apache.dubbo + dubbo + 3.1.2 + + + + org.apache.dubbo + dubbo-remoting-zookeeper-curator5 + 3.1.2 + + + org.apache.curator + curator-x-discovery + 5.1.0 + + + + \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/DubboAccountServiceStarter.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/DubboAccountServiceStarter.java new file mode 100644 index 000000000..4a39311dd --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/DubboAccountServiceStarter.java @@ -0,0 +1,47 @@ +/* + * 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.seata.account; + +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + + +@EnableAutoDataSourceProxy +@EnableDubbo(scanBasePackages = {"org.apache.seata.account"}) +@ComponentScan(basePackages = {"org.apache.seata.account"}) +public class DubboAccountServiceStarter { + + /** + * Enable PropertySource placeHolder + */ + @Bean + public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + public static void main(String[] args) throws InterruptedException { + new AnnotationConfigApplicationContext(DubboAccountServiceStarter.class); + + //keep run + Thread.currentThread().join(); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/DataSourceConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/DataSourceConfiguration.java new file mode 100644 index 000000000..038ceee82 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/DataSourceConfiguration.java @@ -0,0 +1,60 @@ +/* + * 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.seata.account.config; + +import com.alibaba.druid.pool.DruidDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; + +/** + * DataSource Configuration + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DataSourceConfiguration { + + + @Value("${spring.datasource.account.driverClassName}") + private String driverClassName; + @Value("${spring.datasource.account.url}") + private String url; + @Value("${spring.datasource.account.username}") + private String userName; + @Value("${spring.datasource.account.password}") + private String password; + + @Bean + public DataSource accountDataSource() { + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setUsername(userName); + druidDataSource.setPassword(password); + druidDataSource.setUrl(url); + druidDataSource.setDriverClassName(driverClassName); + return druidDataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(@Qualifier("accountDataSource") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/DubboConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/DubboConfiguration.java new file mode 100644 index 000000000..e1039b756 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/DubboConfiguration.java @@ -0,0 +1,59 @@ +/* + * 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.seata.account.config; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * @author wangte + * Create At 2024/1/20 + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DubboConfiguration { + + @Value("${spring.account.application.name}") + private String applicationName; + + @Bean + public ApplicationConfig applicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(applicationName); + applicationConfig.setQosEnable(false); + return applicationConfig; + } + + @Bean + public RegistryConfig registryConfig() { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setAddress("zookeeper://localhost:2181"); + return registryConfig; + } + + @Bean + public ProtocolConfig protocolConfig() { + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.setName("dubbo"); + protocolConfig.setPort(20881); + return protocolConfig; + } +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/SeataConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/SeataConfiguration.java new file mode 100644 index 000000000..ec448c5f3 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/config/SeataConfiguration.java @@ -0,0 +1,45 @@ +/* + * 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.seata.account.config; + +import io.seata.spring.annotation.GlobalTransactionScanner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Seata Config + */ +@Configuration +@PropertySource("classpath:application.properties") +public class SeataConfiguration { + + @Value("${spring.account.application.name}") + private String applicationName; + + /** + * 注册一个StatViewServlet + * + * @return global transaction scanner + */ + @Bean + public GlobalTransactionScanner globalTransactionScanner() { + return new GlobalTransactionScanner(applicationName, "my_test_tx_group"); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/service/AccountService.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/service/AccountService.java new file mode 100644 index 000000000..3c297f44e --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/service/AccountService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.account.service; + +public interface AccountService { + + /** + * 余额扣款 + * + * @param userId 用户ID + * @param money 扣款金额 + */ + void debit(String userId, int money); +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/service/impl/AccountServiceImpl.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/service/impl/AccountServiceImpl.java new file mode 100644 index 000000000..7d4f8b365 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/account/service/impl/AccountServiceImpl.java @@ -0,0 +1,46 @@ +/* + * 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.seata.account.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.seata.account.service.AccountService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.annotation.Resource; + +@DubboService +public class AccountServiceImpl implements AccountService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); + + @Resource + private 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 ... "); + } + +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/DubboBusinessServiceTester.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/DubboBusinessServiceTester.java new file mode 100644 index 000000000..cb7ec2383 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/DubboBusinessServiceTester.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.business; + +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.apache.seata.business.service.BusinessService; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + +@EnableAutoDataSourceProxy +@EnableDubbo +@ComponentScan(basePackages = {"org.apache.seata.business"}) +public class DubboBusinessServiceTester { + + /** + * Enable PropertySource placeHolder + */ + @Bean + public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + public static void main(String[] args) throws InterruptedException { + AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(DubboBusinessServiceTester.class); + + BusinessService businessService = annotationConfigApplicationContext.getBean(BusinessService.class); + Thread thread = new Thread(() -> businessService.purchase("U100001", "C00321", 2)); + thread.start(); + + //keep run + Thread.currentThread().join(); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/config/DubboConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/config/DubboConfiguration.java new file mode 100644 index 000000000..2a7708d6d --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/config/DubboConfiguration.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.business.config; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * @author wangte + * Create At 2024/1/20 + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DubboConfiguration { + + @Value("${spring.business.application.name}") + private String applicationName; + + @Bean + public ApplicationConfig applicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(applicationName); + applicationConfig.setQosEnable(false); + return applicationConfig; + } + + @Bean + public RegistryConfig registryConfig() { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setAddress("zookeeper://localhost:2181"); + return registryConfig; + } +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/config/SeataConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/config/SeataConfiguration.java new file mode 100644 index 000000000..31ee831c2 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/config/SeataConfiguration.java @@ -0,0 +1,45 @@ +/* + * 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.seata.business.config; + +import io.seata.spring.annotation.GlobalTransactionScanner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Seata Config + */ +@Configuration +@PropertySource("classpath:application.properties") +public class SeataConfiguration { + + @Value("${spring.business.application.name}") + private String applicationName; + + /** + * 注册一个StatViewServlet + * + * @return global transaction scanner + */ + @Bean + public GlobalTransactionScanner globalTransactionScanner() { + return new GlobalTransactionScanner(applicationName, "my_test_tx_group"); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/service/BusinessService.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/service/BusinessService.java new file mode 100644 index 000000000..e5e7e9734 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/service/BusinessService.java @@ -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. + */ +package org.apache.seata.business.service; + +public interface BusinessService { + + /** + * 用户订购商品 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void purchase(String userId, String commodityCode, int orderCount); +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/service/impl/BusinessServiceImpl.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/service/impl/BusinessServiceImpl.java new file mode 100644 index 000000000..ad1d6302a --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/business/service/impl/BusinessServiceImpl.java @@ -0,0 +1,54 @@ +/* + * 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.seata.business.service.impl; + +import io.seata.core.context.RootContext; +import io.seata.spring.annotation.GlobalTransactional; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.seata.business.service.BusinessService; +import org.apache.seata.order.service.OrderService; +import org.apache.seata.storage.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.Random; + +@Service +public class BusinessServiceImpl implements BusinessService { + + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); + + @DubboReference + private StorageService storageService; + @DubboReference + private OrderService orderService; + private final Random random = new Random(); + + @Override + @GlobalTransactional(timeoutMills = 300000, name = "spring-dubbo-tx") + public void purchase(String userId, String commodityCode, int orderCount) { + LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); + storageService.deduct(commodityCode, orderCount); + // just test batch update + //stockService.batchDeduct(commodityCode, orderCount); + orderService.create(userId, commodityCode, orderCount); + if (random.nextBoolean()) { + throw new RuntimeException("random exception mock!"); + } + } +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/DubboOrderServiceStarter.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/DubboOrderServiceStarter.java new file mode 100644 index 000000000..6e5d68e22 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/DubboOrderServiceStarter.java @@ -0,0 +1,47 @@ +/* + * 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.seata.order; + +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + + +@EnableAutoDataSourceProxy +@EnableDubbo +@ComponentScan(basePackages = {"org.apache.seata.order"}) +public class DubboOrderServiceStarter { + + /** + * Enable PropertySource placeHolder + */ + @Bean + public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + public static void main(String[] args) throws InterruptedException { + new AnnotationConfigApplicationContext(DubboOrderServiceStarter.class); + + //keep run + Thread.currentThread().join(); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/DataSourceConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/DataSourceConfiguration.java new file mode 100644 index 000000000..712324cff --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/DataSourceConfiguration.java @@ -0,0 +1,60 @@ +/* + * 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.seata.order.config; + +import com.alibaba.druid.pool.DruidDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; + +/** + * DataSource Configuration + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DataSourceConfiguration { + + + @Value("${spring.datasource.order.driverClassName}") + private String driverClassName; + @Value("${spring.datasource.order.url}") + private String url; + @Value("${spring.datasource.order.username}") + private String userName; + @Value("${spring.datasource.order.password}") + private String password; + + @Bean + public DataSource orderDataSource() { + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setUsername(userName); + druidDataSource.setPassword(password); + druidDataSource.setUrl(url); + druidDataSource.setDriverClassName(driverClassName); + return druidDataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(@Qualifier("orderDataSource") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/DubboConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/DubboConfiguration.java new file mode 100644 index 000000000..440ea161d --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/DubboConfiguration.java @@ -0,0 +1,59 @@ +/* + * 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.seata.order.config; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * @author wangte + * Create At 2024/1/20 + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DubboConfiguration { + + @Value("${spring.order.application.name}") + private String applicationName; + + + @Bean + public ApplicationConfig applicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(applicationName); + applicationConfig.setQosEnable(false); + return applicationConfig; + } + @Bean + public RegistryConfig registryConfig() { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setAddress("zookeeper://localhost:2181"); + return registryConfig; + } + + @Bean + public ProtocolConfig protocolConfig() { + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.setName("dubbo"); + protocolConfig.setPort(20883); + return protocolConfig; + } +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/SeataConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/SeataConfiguration.java new file mode 100644 index 000000000..77ac8004a --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/config/SeataConfiguration.java @@ -0,0 +1,45 @@ +/* + * 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.seata.order.config; + +import io.seata.spring.annotation.GlobalTransactionScanner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Seata Config + */ +@Configuration +@PropertySource("classpath:application.properties") +public class SeataConfiguration { + + @Value("${spring.order.application.name}") + private String applicationName; + + /** + * 注册一个StatViewServlet + * + * @return global transaction scanner + */ + @Bean + public GlobalTransactionScanner globalTransactionScanner() { + return new GlobalTransactionScanner(applicationName, "my_test_tx_group"); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/service/OrderService.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/service/OrderService.java new file mode 100644 index 000000000..8afe45deb --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/service/OrderService.java @@ -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. + */ +package org.apache.seata.order.service; + +public interface OrderService { + + /** + * 创建订单 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void create(String userId, String commodityCode, int orderCount); +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/service/impl/OrderServiceImpl.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..0abef9006 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/order/service/impl/OrderServiceImpl.java @@ -0,0 +1,79 @@ +/* + * 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.seata.order.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.seata.account.service.AccountService; +import org.apache.seata.order.service.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; + +import javax.annotation.Resource; +import java.sql.PreparedStatement; +import java.util.Objects; + +@DubboService +public class OrderServiceImpl implements OrderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); + + @Resource + private JdbcTemplate jdbcTemplate; + + @DubboReference + private AccountService accountService; + + @Override + public void create(String userId, String commodityCode, int orderCount) { + LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID()); + + // 计算订单金额 + int orderMoney = calculate(commodityCode, orderCount); + + // 从账户余额扣款 + accountService.debit(userId, orderMoney); + + LOGGER.info( + "Order Service SQL: insert into order_tbl (user_id, commodity_code, count, money) values ({}, {}, {}, {})", + userId, commodityCode, orderCount, orderMoney); + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update(con -> { + PreparedStatement pst = con.prepareStatement( + "insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)", + PreparedStatement.RETURN_GENERATED_KEYS); + pst.setObject(1, userId); + pst.setObject(2, commodityCode); + pst.setObject(3, orderCount); + pst.setObject(4, orderMoney); + return pst; + }, keyHolder); + + + LOGGER.info("Order Service End ... Created " + Objects.requireNonNull(keyHolder.getKey()).longValue()); + } + + private int calculate(String commodityId, int orderCount) { + return 200 * orderCount; + } + +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/DubboStorageServiceStarter.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/DubboStorageServiceStarter.java new file mode 100644 index 000000000..1090841f5 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/DubboStorageServiceStarter.java @@ -0,0 +1,47 @@ +/* + * 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.seata.storage; + +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + + +@EnableAutoDataSourceProxy +@EnableDubbo +@ComponentScan(basePackages = {"org.apache.seata.storage"}) +public class DubboStorageServiceStarter { + + /** + * Enable PropertySource placeHolder + */ + @Bean + public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + public static void main(String[] args) throws InterruptedException { + new AnnotationConfigApplicationContext(DubboStorageServiceStarter.class); + + //keep run + Thread.currentThread().join(); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/DataSourceConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/DataSourceConfiguration.java new file mode 100644 index 000000000..58a4a8a72 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/DataSourceConfiguration.java @@ -0,0 +1,60 @@ +/* + * 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.seata.storage.config; + +import com.alibaba.druid.pool.DruidDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; + +/** + * DataSource Configuration + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DataSourceConfiguration { + + + @Value("${spring.datasource.stock.driverClassName}") + private String driverClassName; + @Value("${spring.datasource.stock.url}") + private String url; + @Value("${spring.datasource.stock.username}") + private String userName; + @Value("${spring.datasource.stock.password}") + private String password; + + @Bean + public DataSource storageDataSource() { + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setUsername(userName); + druidDataSource.setPassword(password); + druidDataSource.setUrl(url); + druidDataSource.setDriverClassName(driverClassName); + return druidDataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(@Qualifier("storageDataSource") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/DubboConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/DubboConfiguration.java new file mode 100644 index 000000000..e2a6e13c0 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/DubboConfiguration.java @@ -0,0 +1,59 @@ +/* + * 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.seata.storage.config; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * @author wangte + * Create At 2024/1/20 + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DubboConfiguration { + + @Value("${spring.storage.application.name}") + private String applicationName; + + @Bean + public ApplicationConfig applicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(applicationName); + applicationConfig.setQosEnable(false); + return applicationConfig; + } + + @Bean + public RegistryConfig registryConfig() { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setAddress("zookeeper://localhost:2181"); + return registryConfig; + } + + @Bean + public ProtocolConfig protocolConfig() { + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.setName("dubbo"); + protocolConfig.setPort(20882); + return protocolConfig; + } +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/SeataConfiguration.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/SeataConfiguration.java new file mode 100644 index 000000000..e624111a9 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/config/SeataConfiguration.java @@ -0,0 +1,45 @@ +/* + * 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.seata.storage.config; + +import io.seata.spring.annotation.GlobalTransactionScanner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Seata Config + */ +@Configuration +@PropertySource("classpath:application.properties") +public class SeataConfiguration { + + @Value("${spring.storage.application.name}") + private String applicationName; + + /** + * 注册一个StatViewServlet + * + * @return global transaction scanner + */ + @Bean + public GlobalTransactionScanner globalTransactionScanner() { + return new GlobalTransactionScanner(applicationName, "my_test_tx_group"); + } + +} diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/service/StorageService.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/service/StorageService.java new file mode 100644 index 000000000..1358830e8 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/service/StorageService.java @@ -0,0 +1,36 @@ +/* + * 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.seata.storage.service; + +public interface StorageService { + + /** + * 扣减库存 + * + * @param commodityCode 商品编号 + * @param count 扣减数量 + */ + void deduct(String commodityCode, int count); + + /** + * 批量扣减 + * + * @param commodityCode + * @param count + */ + void batchDeduct(String commodityCode, int count); +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/service/impl/StorageServiceImpl.java b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/service/impl/StorageServiceImpl.java new file mode 100644 index 000000000..fca6ae8cb --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/java/org/apache/seata/storage/service/impl/StorageServiceImpl.java @@ -0,0 +1,61 @@ +/* + * 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.seata.storage.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.seata.storage.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.annotation.Resource; + +@DubboService +public class StorageServiceImpl implements StorageService { + + private static final Logger LOGGER = LoggerFactory.getLogger(StorageService.class); + + @Resource + private 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 ... "); + + } + +} \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/resources/all.sql b/at-sample/spring-dubbo-seata/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/spring-dubbo-seata/src/main/resources/application.properties b/at-sample/spring-dubbo-seata/src/main/resources/application.properties new file mode 100644 index 000000000..b8d7fc9f0 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/resources/application.properties @@ -0,0 +1,18 @@ +spring.account.application.name=account-service +spring.storage.application.name=storage-service +spring.order.application.name=order-service +spring.business.application.name=business-service +spring.datasource.account.url=jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&serverTimezone=UTC +spring.datasource.account.username=root +spring.datasource.account.password=123456 +spring.datasource.account.driverClassName=com.mysql.jdbc.Driver +# stock db config +spring.datasource.stock.url=jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&serverTimezone=UTC +spring.datasource.stock.username=root +spring.datasource.stock.password=123456 +spring.datasource.stock.driverClassName=com.mysql.jdbc.Driver +# order db config +spring.datasource.order.url=jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&serverTimezone=UTC +spring.datasource.order.username=root +spring.datasource.order.password=123456 +spring.datasource.order.driverClassName=com.mysql.jdbc.Driver diff --git a/at-sample/spring-dubbo-seata/src/main/resources/file.conf b/at-sample/spring-dubbo-seata/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/spring-dubbo-seata/src/main/resources/registry.conf b/at-sample/spring-dubbo-seata/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/spring-dubbo-seata/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/spring-seata/pom.xml b/at-sample/spring-seata/pom.xml new file mode 100644 index 000000000..e5ad7d916 --- /dev/null +++ b/at-sample/spring-seata/pom.xml @@ -0,0 +1,86 @@ + + + + 4.0.0 + + org.apache.seata + spring-seata + 2.0.0 + + + UTF-8 + UTF-8 + 1.8 + 1.8 + + + + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + + + + org.slf4j + jcl-over-slf4j + 1.7.32 + + + org.slf4j + log4j-over-slf4j + 1.7.32 + + + + + io.seata + seata-all + 2.0.0 + + + + org.springframework + spring-jdbc + 5.3.20 + + + + com.fasterxml.jackson.core + jackson-databind + 2.13.5 + + + + mysql + mysql-connector-java + 5.1.42 + + + \ No newline at end of file diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/BusinessServiceTester.java b/at-sample/spring-seata/src/main/java/org/apache/seata/BusinessServiceTester.java new file mode 100644 index 000000000..9729e4abd --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/BusinessServiceTester.java @@ -0,0 +1,57 @@ +/* + * 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.seata; + +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; +import org.apache.seata.service.BusinessService; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + +/** + * @author wangte + * Create At 2024/1/20 + */ +@ComponentScan +@Configuration +@EnableAutoDataSourceProxy +public class BusinessServiceTester { + + /** + * Enable PropertySource placeHolder + */ + @Bean + public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + public static void main(String[] args) throws Exception { + AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(BusinessServiceTester.class); + + BusinessService businessService = annotationConfigApplicationContext.getBean(BusinessService.class); + + Thread thread = new Thread(() -> businessService.purchase("U100001", "C00321", 2)); + thread.start(); + thread.join(); + + //keep run + Thread.currentThread().join(); + } + +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/config/DataSourceConfiguration.java b/at-sample/spring-seata/src/main/java/org/apache/seata/config/DataSourceConfiguration.java new file mode 100644 index 000000000..7d6687c4c --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/config/DataSourceConfiguration.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.seata.provider.config; + +import com.alibaba.druid.pool.DruidDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; + +/** + * DataSource Configuration + */ +@Configuration +@PropertySource("classpath:application.properties") +public class DataSourceConfiguration { + + @Value("${spring.datasource.driverClassName}") + private String driverClassName; + @Value("${spring.datasource.url}") + private String url; + @Value("${spring.datasource.username}") + private String userName; + @Value("${spring.datasource.password}") + private String password; + + @Bean + public DataSource dataSource() { + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setUsername(userName); + druidDataSource.setPassword(password); + druidDataSource.setUrl(url); + druidDataSource.setDriverClassName(driverClassName); + return druidDataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/config/SeataConfiguration.java b/at-sample/spring-seata/src/main/java/org/apache/seata/config/SeataConfiguration.java new file mode 100644 index 000000000..029f876ae --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/config/SeataConfiguration.java @@ -0,0 +1,45 @@ +/* + * 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.seata.provider.config; + +import io.seata.spring.annotation.GlobalTransactionScanner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Seata Config + */ +@Configuration +@PropertySource("classpath:application.properties") +public class SeataConfiguration { + + @Value("${spring.application.name}") + private String applicationId; + + /** + * 注册一个StatViewServlet + * + * @return global transaction scanner + */ + @Bean + public GlobalTransactionScanner globalTransactionScanner() { + return new GlobalTransactionScanner(applicationId, "my_test_tx_group"); + } + +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/AccountService.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/AccountService.java new file mode 100644 index 000000000..2e8a75daa --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/AccountService.java @@ -0,0 +1,31 @@ +/* + * 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.seata.service; + +/** + * The interface Account service. + */ +public interface AccountService { + + /** + * 余额扣款 + * + * @param userId 用户ID + * @param money 扣款金额 + */ + void debit(String userId, int money); +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/BusinessService.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/BusinessService.java new file mode 100644 index 000000000..c6f16f415 --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/BusinessService.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.seata.service; + +/** + * The interface Business service. + */ +public interface BusinessService { + + /** + * 用户订购商品 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void purchase(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/OrderService.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/OrderService.java new file mode 100644 index 000000000..a360ca920 --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/OrderService.java @@ -0,0 +1,33 @@ +/* + * 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.seata.service; + + +/** + * The interface Order service. + */ +public interface OrderService { + + /** + * 创建订单 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void create(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/StorageService.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/StorageService.java new file mode 100644 index 000000000..0f68fad94 --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/StorageService.java @@ -0,0 +1,31 @@ +/* + * 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.seata.service; + +/** + * The interface Stock service. + */ +public interface StorageService { + + /** + * 扣减库存 + * + * @param commodityCode 商品编号 + * @param count 扣减数量 + */ + void deduct(String commodityCode, int count); +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java new file mode 100644 index 000000000..ab3482aeb --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.service.AccountService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * The type Account service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class AccountServiceImpl implements AccountService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); + + @Resource + private 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 = ?", money, userId); + LOGGER.info("Account Service End ... "); + } +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java new file mode 100644 index 000000000..a18e5aa88 --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java @@ -0,0 +1,60 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import io.seata.spring.annotation.GlobalTransactional; + +import org.apache.seata.service.BusinessService; +import org.apache.seata.service.OrderService; +import org.apache.seata.service.StorageService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Random; + +/** + * The type Business service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class BusinessServiceImpl implements BusinessService { + + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); + + @Resource + private StorageService storageService; + @Resource + private OrderService orderService; + private final Random random = new Random(); + + @Override + @GlobalTransactional(timeoutMills = 300000, name = "spring-seata-tx") + public void purchase(String userId, String commodityCode, int orderCount) { + LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); + storageService.deduct(commodityCode, orderCount); + orderService.create(userId, commodityCode, orderCount); + if (random.nextBoolean()) { + throw new RuntimeException("random exception mock!"); + } + } + +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..7aede43d7 --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java @@ -0,0 +1,84 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.service.AccountService; +import org.apache.seata.service.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.sql.PreparedStatement; +import java.util.Objects; + +/** + * The type Order service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class OrderServiceImpl implements OrderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); + + @Resource + private AccountService accountService; + @Resource + private JdbcTemplate jdbcTemplate; + + @Override + public void create(String userId, String commodityCode, int orderCount) { + LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID()); + + // 计算订单金额 + int orderMoney = calculate(commodityCode, orderCount); + + // 从账户余额扣款 + accountService.debit(userId, 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(con -> { + PreparedStatement pst = con.prepareStatement( + "insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)", + PreparedStatement.RETURN_GENERATED_KEYS); + pst.setObject(1, userId); + pst.setObject(2, commodityCode); + pst.setObject(3, orderCount); + pst.setObject(4, orderMoney); + return pst; + }, keyHolder); + + + LOGGER.info("Order Service End ... Created " + Objects.requireNonNull(keyHolder.getKey()).longValue()); + } + + private int calculate(String commodityId, int orderCount) { + return 200 * orderCount; + } + +} diff --git a/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java new file mode 100644 index 000000000..8ee0cc42d --- /dev/null +++ b/at-sample/spring-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * The type Stock service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class StorageServiceImpl implements StorageService { + + private static final Logger LOGGER = LoggerFactory.getLogger(StorageService.class); + + @Resource + private 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 ... "); + + } + +} diff --git a/at-sample/spring-seata/src/main/resources/all.sql b/at-sample/spring-seata/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/spring-seata/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/spring-seata/src/main/resources/application.properties b/at-sample/spring-seata/src/main/resources/application.properties new file mode 100644 index 000000000..7aea7ea1f --- /dev/null +++ b/at-sample/spring-seata/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.application.name=spring-seata +spring.datasource.driverClassName=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata?userSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=root +spring.datasource.password=123456 \ No newline at end of file diff --git a/at-sample/spring-seata/src/main/resources/file.conf b/at-sample/spring-seata/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/spring-seata/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/spring-seata/src/main/resources/registry.conf b/at-sample/spring-seata/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/spring-seata/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/springboot-dubbo-seata/pom.xml b/at-sample/springboot-dubbo-seata/pom.xml new file mode 100644 index 000000000..a5987d339 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/pom.xml @@ -0,0 +1,47 @@ + + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.0 + + + org.apache.seata + springboot-dubbo-seata + 2.0.0 + springboot-dubbo-seata + springboot-dubbo-seata + pom + + + springboot-dubbo-seata-common + springboot-dubbo-seata-storage + springboot-dubbo-seata-account + springboot-dubbo-seata-order + springboot-dubbo-seata-business + + + + 8 + + diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/pom.xml b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/pom.xml new file mode 100644 index 000000000..0c303112e --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/pom.xml @@ -0,0 +1,123 @@ + + + + 4.0.0 + + org.apache.seata + springboot-dubbo-seata + 2.0.0 + + springboot-dubbo-seata-account + 2.0.0 + springboot-dubbo-seata-account + springboot-dubbo-seata-account + + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + + + + org.slf4j + jcl-over-slf4j + 1.7.32 + + + org.slf4j + log4j-over-slf4j + 1.7.32 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.seata + seata-spring-boot-starter + 2.0.0 + + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.apache.dubbo + dubbo-spring-boot-starter + 3.1.2 + + + org.apache.dubbo + dubbo-remoting-zookeeper-curator5 + 3.1.2 + + + org.apache.curator + curator-x-discovery + 5.1.0 + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + mysql + mysql-connector-java + 5.1.42 + + + + org.apache.seata + springboot-dubbo-seata-common + 2.0.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/java/org/apache/seata/SpringbootDubboSeataAccountApplication.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/java/org/apache/seata/SpringbootDubboSeataAccountApplication.java new file mode 100644 index 000000000..27ad4bb66 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/java/org/apache/seata/SpringbootDubboSeataAccountApplication.java @@ -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. + */ +package org.apache.seata; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringbootDubboSeataAccountApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringbootDubboSeataAccountApplication.class, args); + } + +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java new file mode 100644 index 000000000..d11c447da --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java @@ -0,0 +1,46 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.seata.service.AccountService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.annotation.Resource; + +@DubboService +public class AccountServiceImpl implements AccountService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); + + @Resource + private 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 ... "); + } + +} \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/all.sql b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/application.properties b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/application.properties new file mode 100644 index 000000000..c89f20f95 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/application.properties @@ -0,0 +1,12 @@ +spring.application.name=springboot-dubbo-seata-account +spring.datasource.driverClassName=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata?userSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=root +spring.datasource.password=123456 +seata.application-id=springboot-dubbo-seata-account +seata.tx-service-group=my_test_tx_group +dubbo.scan.base-packages=org.apache.seata +dubbo.application.qos-enable=false +dubbo.registry.address=zookeeper://localhost:2181 +dubbo.protocol.name=dubbo +dubbo.protocol.port=28801 \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/file.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/registry.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-account/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/pom.xml b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/pom.xml new file mode 100644 index 000000000..5e9168528 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/pom.xml @@ -0,0 +1,111 @@ + + + + 4.0.0 + + org.apache.seata + springboot-dubbo-seata + 2.0.0 + + springboot-dubbo-seata-business + 2.0.0 + springboot-dubbo-seata-business + springboot-dubbo-seata-business + + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + + + + org.slf4j + jcl-over-slf4j + 1.7.32 + + + org.slf4j + log4j-over-slf4j + 1.7.32 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.seata + seata-spring-boot-starter + 2.0.0 + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.apache.dubbo + dubbo-spring-boot-starter + 3.1.2 + + + org.apache.dubbo + dubbo-remoting-zookeeper-curator5 + 3.1.2 + + + org.apache.curator + curator-x-discovery + 5.1.0 + + + + org.apache.seata + springboot-dubbo-seata-common + 2.0.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/SpringbootDubboSeataBusinessApplication.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/SpringbootDubboSeataBusinessApplication.java new file mode 100644 index 000000000..22cd54d86 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/SpringbootDubboSeataBusinessApplication.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.seata; + +import org.apache.seata.service.BusinessService; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringbootDubboSeataBusinessApplication implements BeanFactoryAware { + + private static BeanFactory BEAN_FACTORY; + + public static void main(String[] args) throws Exception { + SpringApplication.run(SpringbootDubboSeataBusinessApplication.class, args); + + BusinessService businessService = BEAN_FACTORY.getBean(BusinessService.class); + + businessService.purchase("U100001", "C00321", 2); + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + BEAN_FACTORY = beanFactory; + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/service/BusinessService.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/service/BusinessService.java new file mode 100644 index 000000000..c6f16f415 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/service/BusinessService.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.seata.service; + +/** + * The interface Business service. + */ +public interface BusinessService { + + /** + * 用户订购商品 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void purchase(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java new file mode 100644 index 000000000..e6e374099 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java @@ -0,0 +1,54 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import io.seata.spring.annotation.GlobalTransactional; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.seata.service.BusinessService; +import org.apache.seata.service.OrderService; +import org.apache.seata.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.Random; + +@Service +public class BusinessServiceImpl implements BusinessService { + + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); + + @DubboReference + private StorageService storageService; + @DubboReference + private OrderService orderService; + private final Random random = new Random(); + + @Override + @GlobalTransactional(timeoutMills = 300000, name = "spring-dubbo-tx") + public void purchase(String userId, String commodityCode, int orderCount) { + LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); + storageService.deduct(commodityCode, orderCount); + // just test batch update + //stockService.batchDeduct(commodityCode, orderCount); + orderService.create(userId, commodityCode, orderCount); + if (random.nextBoolean()) { + throw new RuntimeException("random exception mock!"); + } + } +} \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/all.sql b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/application.properties b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/application.properties new file mode 100644 index 000000000..4dc07526d --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.application.name=springboot-dubbo-seata-business +seata.application-id=springboot-dubbo-seata-business +seata.tx-service-group=my_test_tx_group +dubbo.application.qos-enable=false +dubbo.scan.base-packages=org.apache.seata +dubbo.registry.address=zookeeper://localhost:2181 +dubbo.protocol.name=dubbo +dubbo.protocol.port=20883 \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/file.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/registry.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-business/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/pom.xml b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/pom.xml new file mode 100644 index 000000000..29392592a --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/pom.xml @@ -0,0 +1,33 @@ + + + + 4.0.0 + + org.apache.seata + springboot-dubbo-seata + 2.0.0 + + springboot-dubbo-seata-common + 2.0.0 + springboot-dubbo-seata-common + springboot-dubbo-seata-common + jar + diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/AccountService.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/AccountService.java new file mode 100644 index 000000000..6ae18eea8 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/AccountService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.service; + +public interface AccountService { + + /** + * 余额扣款 + * + * @param userId 用户ID + * @param money 扣款金额 + */ + void debit(String userId, int money); +} \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/OrderService.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/OrderService.java new file mode 100644 index 000000000..fab053c86 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/OrderService.java @@ -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. + */ +package org.apache.seata.service; + +public interface OrderService { + + /** + * 创建订单 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void create(String userId, String commodityCode, int orderCount); +} \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/StorageService.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/StorageService.java new file mode 100644 index 000000000..d0922e579 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-common/src/main/java/org/apache/seata/service/StorageService.java @@ -0,0 +1,36 @@ +/* + * 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.seata.service; + +public interface StorageService { + + /** + * 扣减库存 + * + * @param commodityCode 商品编号 + * @param count 扣减数量 + */ + void deduct(String commodityCode, int count); + + /** + * 批量扣减 + * + * @param commodityCode + * @param count + */ + void batchDeduct(String commodityCode, int count); +} \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/pom.xml b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/pom.xml new file mode 100644 index 000000000..7178780eb --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/pom.xml @@ -0,0 +1,123 @@ + + + + 4.0.0 + + org.apache.seata + springboot-dubbo-seata + 2.0.0 + + springboot-dubbo-seata-order + 2.0.0 + springboot-dubbo-seata-order + springboot-dubbo-seata-order + + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + + + + org.slf4j + jcl-over-slf4j + 1.7.32 + + + org.slf4j + log4j-over-slf4j + 1.7.32 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.seata + seata-spring-boot-starter + 2.0.0 + + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.apache.dubbo + dubbo-spring-boot-starter + 3.1.2 + + + org.apache.dubbo + dubbo-remoting-zookeeper-curator5 + 3.1.2 + + + org.apache.curator + curator-x-discovery + 5.1.0 + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + mysql + mysql-connector-java + 5.1.42 + + + + org.apache.seata + springboot-dubbo-seata-common + 2.0.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/java/org/apache/seata/SpringbootDubboSeataOrderApplication.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/java/org/apache/seata/SpringbootDubboSeataOrderApplication.java new file mode 100644 index 000000000..a86a30a54 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/java/org/apache/seata/SpringbootDubboSeataOrderApplication.java @@ -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. + */ +package org.apache.seata; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringbootDubboSeataOrderApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringbootDubboSeataOrderApplication.class, args); + } + +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..d0617e3ba --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java @@ -0,0 +1,79 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.seata.service.AccountService; +import org.apache.seata.service.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; + +import javax.annotation.Resource; +import java.sql.PreparedStatement; +import java.util.Objects; + +@DubboService +public class OrderServiceImpl implements OrderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); + + @Resource + private JdbcTemplate jdbcTemplate; + + @DubboReference + private AccountService accountService; + + @Override + public void create(String userId, String commodityCode, int orderCount) { + LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID()); + + // 计算订单金额 + int orderMoney = calculate(commodityCode, orderCount); + + // 从账户余额扣款 + accountService.debit(userId, orderMoney); + + LOGGER.info( + "Order Service SQL: insert into order_tbl (user_id, commodity_code, count, money) values ({}, {}, {}, {})", + userId, commodityCode, orderCount, orderMoney); + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update(con -> { + PreparedStatement pst = con.prepareStatement( + "insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)", + PreparedStatement.RETURN_GENERATED_KEYS); + pst.setObject(1, userId); + pst.setObject(2, commodityCode); + pst.setObject(3, orderCount); + pst.setObject(4, orderMoney); + return pst; + }, keyHolder); + + + LOGGER.info("Order Service End ... Created " + Objects.requireNonNull(keyHolder.getKey()).longValue()); + } + + private int calculate(String commodityId, int orderCount) { + return 200 * orderCount; + } + +} \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/all.sql b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/application.properties b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/application.properties new file mode 100644 index 000000000..e192de12e --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/application.properties @@ -0,0 +1,12 @@ +spring.application.name=springboot-dubbo-seata-order +spring.datasource.driverClassName=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata?userSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=root +spring.datasource.password=123456 +seata.application-id=springboot-dubbo-seata-order +seata.tx-service-group=my_test_tx_group +dubbo.scan.base-packages=org.apache.seata +dubbo.application.qos-enable=false +dubbo.registry.address=zookeeper://localhost:2181 +dubbo.protocol.name=dubbo +dubbo.protocol.port=20883 \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/file.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/registry.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-order/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/pom.xml b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/pom.xml new file mode 100644 index 000000000..2c3478b43 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + org.apache.seata + springboot-dubbo-seata + 2.0.0 + + springboot-dubbo-seata-storage + 2.0.0 + springboot-dubbo-seata-storage + springboot-dubbo-seata-storage + + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + + + + org.slf4j + jcl-over-slf4j + 1.7.32 + + + org.slf4j + log4j-over-slf4j + 1.7.32 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.seata + seata-spring-boot-starter + 2.0.0 + + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.apache.dubbo + dubbo-spring-boot-starter + 3.1.2 + + + org.apache.dubbo + dubbo-remoting-zookeeper-curator5 + 3.1.2 + + + org.apache.curator + curator-x-discovery + 5.1.0 + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + mysql + mysql-connector-java + 5.1.42 + + + + org.apache.seata + springboot-dubbo-seata-common + 2.0.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/java/org/apache/seata/SpringbootDubboSeataStorageApplication.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/java/org/apache/seata/SpringbootDubboSeataStorageApplication.java new file mode 100644 index 000000000..d69a9c7f9 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/java/org/apache/seata/SpringbootDubboSeataStorageApplication.java @@ -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. + */ +package org.apache.seata; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringbootDubboSeataStorageApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringbootDubboSeataStorageApplication.class, args); + } + +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java new file mode 100644 index 000000000..e53a2bb41 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java @@ -0,0 +1,61 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.seata.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.annotation.Resource; + +@DubboService +public class StorageServiceImpl implements StorageService { + + private static final Logger LOGGER = LoggerFactory.getLogger(StorageService.class); + + @Resource + private 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 = ?", + 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 ... "); + + } + +} \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/all.sql b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/application.properties b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/application.properties new file mode 100644 index 000000000..33e291f1b --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/application.properties @@ -0,0 +1,12 @@ +spring.application.name=springboot-dubbo-seata-storage +spring.datasource.driverClassName=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata?userSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=root +spring.datasource.password=123456 +seata.application-id=springboot-dubbo-seata-storage +seata.tx-service-group=my_test_tx_group +dubbo.scan.base-packages=org.apache.seata +dubbo.application.qos-enable=false +dubbo.registry.address=zookeeper://localhost:2181 +dubbo.protocol.name=dubbo +dubbo.protocol.port=20882 \ No newline at end of file diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/file.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/registry.conf b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/springboot-dubbo-seata/springboot-dubbo-seata-storage/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/springboot-mybatis-seata/pom.xml b/at-sample/springboot-mybatis-seata/pom.xml new file mode 100644 index 000000000..e073bade6 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/pom.xml @@ -0,0 +1,88 @@ + + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.0 + + + org.apache.seata + springboot-mybatis-seata + 2.0.0 + springboot-mybatis-seata + springboot-mybatis-seata + + 8 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.seata + seata-spring-boot-starter + 2.0.0 + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + mysql + mysql-connector-java + 5.1.42 + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.2.2 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java new file mode 100644 index 000000000..d8a4255e0 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java @@ -0,0 +1,47 @@ +/* + * 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.seata; + +import org.apache.seata.service.BusinessService; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringbootSeataApplication implements BeanFactoryAware { + + private static BeanFactory BEAN_FACTORY; + + public static void main(String[] args) throws Exception { + SpringApplication.run(SpringbootSeataApplication.class, args); + + BusinessService businessService = BEAN_FACTORY.getBean(BusinessService.class); + + Thread thread = new Thread(() -> businessService.purchase(TestData.USER_ID, TestData.COMMODITY_CODE, 2)); + thread.start(); + + //keep run + Thread.currentThread().join(); + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + BEAN_FACTORY = beanFactory; + } +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/TestData.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/TestData.java new file mode 100644 index 000000000..fe972868f --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/TestData.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata; + +public class TestData { + + public static final String USER_ID = "U100001"; + public static final String COMMODITY_CODE = "C00321"; +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/AccountMapper.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/AccountMapper.java new file mode 100644 index 000000000..78ba48cc6 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/AccountMapper.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.seata.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.seata.model.Account; +import org.springframework.stereotype.Repository; + +@Mapper +@Repository +public interface AccountMapper { + + Account selectByUserId(@Param("userId") String userId); + + int updateById(Account record); + +} \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/OrderMapper.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/OrderMapper.java new file mode 100644 index 000000000..814edc743 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/OrderMapper.java @@ -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. + */ +package org.apache.seata.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.seata.model.Order; +import org.springframework.stereotype.Repository; + +@Mapper +@Repository +public interface OrderMapper { + + int insert(Order record); + +} \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/StorageMapper.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/StorageMapper.java new file mode 100644 index 000000000..443e2e334 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/dao/StorageMapper.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.seata.model.Storage; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Mapper +@Repository +public interface StorageMapper { + + Storage selectById(@Param("id") Integer id); + + Storage findByCommodityCode(@Param("commodityCode") String commodityCode); + + int updateById(Storage record); + + void insert(Storage record); + + void insertBatch(List records); + + int updateBatch(@Param("list") List ids, @Param("commodityCode") String commodityCode); +} \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Account.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Account.java new file mode 100644 index 000000000..b8aecbea8 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Account.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.model; + +public class Account { + private Integer id; + + private String userId; + + private Integer money; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Integer getMoney() { + return money; + } + + public void setMoney(Integer money) { + this.money = money; + } +} \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Order.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Order.java new file mode 100644 index 000000000..ad78960c4 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Order.java @@ -0,0 +1,71 @@ +/* + * 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.seata.model; + +import java.math.BigDecimal; + +public class Order { + private Integer id; + + private String userId; + + private String commodityCode; + + private Integer count; + + private Integer money; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getCommodityCode() { + return commodityCode; + } + + public void setCommodityCode(String commodityCode) { + this.commodityCode = commodityCode; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public Integer getMoney() { + return money; + } + + public void setMoney(Integer money) { + this.money = money; + } +} \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Storage.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Storage.java new file mode 100644 index 000000000..fd9399486 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/model/Storage.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.seata.model; + +public class Storage { + + private Integer id; + + private String commodityCode; + + private Integer count; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getCommodityCode() { + return commodityCode; + } + + public void setCommodityCode(String commodityCode) { + this.commodityCode = commodityCode; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/AccountService.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/AccountService.java new file mode 100644 index 000000000..2e8a75daa --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/AccountService.java @@ -0,0 +1,31 @@ +/* + * 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.seata.service; + +/** + * The interface Account service. + */ +public interface AccountService { + + /** + * 余额扣款 + * + * @param userId 用户ID + * @param money 扣款金额 + */ + void debit(String userId, int money); +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/BusinessService.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/BusinessService.java new file mode 100644 index 000000000..c6f16f415 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/BusinessService.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.seata.service; + +/** + * The interface Business service. + */ +public interface BusinessService { + + /** + * 用户订购商品 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void purchase(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/OrderService.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/OrderService.java new file mode 100644 index 000000000..a360ca920 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/OrderService.java @@ -0,0 +1,33 @@ +/* + * 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.seata.service; + + +/** + * The interface Order service. + */ +public interface OrderService { + + /** + * 创建订单 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void create(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/StorageService.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/StorageService.java new file mode 100644 index 000000000..0f68fad94 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/StorageService.java @@ -0,0 +1,31 @@ +/* + * 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.seata.service; + +/** + * The interface Stock service. + */ +public interface StorageService { + + /** + * 扣减库存 + * + * @param commodityCode 商品编号 + * @param count 扣减数量 + */ + void deduct(String commodityCode, int count); +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java new file mode 100644 index 000000000..0af9a2082 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java @@ -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. + */ +package org.apache.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.dao.AccountMapper; +import org.apache.seata.model.Account; +import org.apache.seata.service.AccountService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * The type Account service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class AccountServiceImpl implements AccountService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); + + @Resource + private AccountMapper accountMapper; + + @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); + Account account = accountMapper.selectByUserId(userId); + account.setMoney(money); + accountMapper.updateById(account); + LOGGER.info("Account Service End ... "); + } +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java new file mode 100644 index 000000000..a97ff2fcb --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java @@ -0,0 +1,75 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import io.seata.spring.annotation.GlobalTransactional; +import org.apache.seata.TestData; +import org.apache.seata.service.BusinessService; +import org.apache.seata.service.OrderService; +import org.apache.seata.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.Random; + +/** + * The type Business service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class BusinessServiceImpl implements BusinessService { + + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); + + @Resource + private StorageService storageService; + @Resource + private OrderService orderService; + + @Resource + private JdbcTemplate jdbcTemplate; + + private final Random random = new Random(); + + @Override + @GlobalTransactional(timeoutMills = 300000, name = "spring-seata-tx") + public void purchase(String userId, String commodityCode, int orderCount) { + LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); + storageService.deduct(commodityCode, orderCount); + orderService.create(userId, commodityCode, orderCount); + if (random.nextBoolean()) { + throw new RuntimeException("random exception mock!"); + } + } + + @PostConstruct + public void initData() { + jdbcTemplate.update("delete from account_tbl"); + jdbcTemplate.update("delete from order_tbl"); + jdbcTemplate.update("delete from stock_tbl"); + jdbcTemplate.update("insert into account_tbl(user_id,money) values('" + TestData.USER_ID + "','10000') "); + jdbcTemplate.update( + "insert into stock_tbl(commodity_code,count) values('" + TestData.COMMODITY_CODE + "','100') "); + } + +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..38a7f4399 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.dao.OrderMapper; +import org.apache.seata.model.Order; +import org.apache.seata.service.AccountService; +import org.apache.seata.service.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * The type Order service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class OrderServiceImpl implements OrderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); + + @Resource + private AccountService accountService; + @Resource + private OrderMapper orderMapper; + + @Override + public void create(String userId, String commodityCode, int count) { + LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID()); + Order order = new Order(); + order.setUserId(userId); + order.setCommodityCode(commodityCode); + order.setCount(count); + int orderMoney = calculate(commodityCode, count); + order.setMoney(orderMoney); + + orderMapper.insert(order); + accountService.debit(userId, orderMoney); + } + + private int calculate(String commodityCode, int count) { + return 200 * count; + } + +} diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java new file mode 100644 index 000000000..cfe96d78d --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java @@ -0,0 +1,54 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.dao.StorageMapper; +import org.apache.seata.model.Storage; +import org.apache.seata.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * The type Stock service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class StorageServiceImpl implements StorageService { + + private static final Logger LOGGER = LoggerFactory.getLogger(StorageService.class); + + @Resource + private StorageMapper storageMapper; + + @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); + + Storage stock = storageMapper.findByCommodityCode(commodityCode); + stock.setCount(stock.getCount() - count); + storageMapper.updateById(stock); + LOGGER.info("Stock Service End ... "); + + } + +} diff --git a/at-sample/springboot-mybatis-seata/src/main/resources/all.sql b/at-sample/springboot-mybatis-seata/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/resources/application.properties b/at-sample/springboot-mybatis-seata/src/main/resources/application.properties new file mode 100644 index 000000000..61c3f524c --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/resources/application.properties @@ -0,0 +1,10 @@ +spring.application.name=springboot-mybatis-seata +server.port=8088 +spring.datasource.driverClassName=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata?userSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=root +spring.datasource.password=123456 +seata.application-id=springboot-mybatis-seata +seata.tx-service-group=my_test_tx_group +mybatis.configuration.map-underscore-to-camel-case=true +mybatis.mapper-locations=classpath:mapper/*.xml \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/resources/file.conf b/at-sample/springboot-mybatis-seata/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-mybatis-seata/src/main/resources/mapper/AccountMapper.xml b/at-sample/springboot-mybatis-seata/src/main/resources/mapper/AccountMapper.xml new file mode 100644 index 000000000..328d01d5d --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/resources/mapper/AccountMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + update account_tbl + set money = #{money,jdbcType=INTEGER} + where id = #{id} + + + \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/resources/mapper/OrderMapper.xml b/at-sample/springboot-mybatis-seata/src/main/resources/mapper/OrderMapper.xml new file mode 100644 index 000000000..6343a18d9 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/resources/mapper/OrderMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + insert into order_tbl (user_id, commodity_code, count, money) + values (#{userId,jdbcType=VARCHAR}, #{commodityCode,jdbcType=VARCHAR}, #{count,jdbcType=INTEGER}, + #{money,jdbcType=INTEGER}) + + + \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/resources/mapper/StorageMapper.xml b/at-sample/springboot-mybatis-seata/src/main/resources/mapper/StorageMapper.xml new file mode 100644 index 000000000..6630a6aae --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/resources/mapper/StorageMapper.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + update stock_tbl + set count = #{count,jdbcType=INTEGER} + WHERE id = #{id} + + + + insert into stock_tbl (commodity_code, count) + values (#{commodityCode,jdbcType=VARCHAR}, #{count,jdbcType=INTEGER}) + + + + insert into stock_tbl (commodity_code, count) + values + + (#{item.commodityCode,jdbcType=VARCHAR}, #{item.count,jdbcType=INTEGER}) + + + + + update stock_tbl set count = 100 + WHERE id IN + + #{item} + + and commodity_code = #{commodityCode,jdbcType=VARCHAR} + + \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/resources/registry.conf b/at-sample/springboot-mybatis-seata/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/at-sample/springboot-seata/pom.xml b/at-sample/springboot-seata/pom.xml new file mode 100644 index 000000000..a36f6abca --- /dev/null +++ b/at-sample/springboot-seata/pom.xml @@ -0,0 +1,82 @@ + + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.0 + + + org.apache.seata + springboot-seata + 2.0.0 + springboot-seata + springboot-seata + + 8 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.seata + seata-spring-boot-starter + 2.0.0 + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + mysql + mysql-connector-java + 5.1.42 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java new file mode 100644 index 000000000..32dc50aa3 --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java @@ -0,0 +1,31 @@ +package org.apache.seata; + +import org.apache.seata.service.BusinessService; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringbootSeataApplication implements BeanFactoryAware { + + private static BeanFactory BEAN_FACTORY; + + public static void main(String[] args) throws Exception { + SpringApplication.run(SpringbootSeataApplication.class, args); + + BusinessService businessService = BEAN_FACTORY.getBean(BusinessService.class); + + Thread thread = new Thread(() -> businessService.purchase("U100001", "C00321", 2)); + thread.start(); + + //keep run + Thread.currentThread().join(); + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + BEAN_FACTORY = beanFactory; + } +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/AccountService.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/AccountService.java new file mode 100644 index 000000000..2e8a75daa --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/AccountService.java @@ -0,0 +1,31 @@ +/* + * 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.seata.service; + +/** + * The interface Account service. + */ +public interface AccountService { + + /** + * 余额扣款 + * + * @param userId 用户ID + * @param money 扣款金额 + */ + void debit(String userId, int money); +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/BusinessService.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/BusinessService.java new file mode 100644 index 000000000..c6f16f415 --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/BusinessService.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.seata.service; + +/** + * The interface Business service. + */ +public interface BusinessService { + + /** + * 用户订购商品 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void purchase(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/OrderService.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/OrderService.java new file mode 100644 index 000000000..a360ca920 --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/OrderService.java @@ -0,0 +1,33 @@ +/* + * 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.seata.service; + + +/** + * The interface Order service. + */ +public interface OrderService { + + /** + * 创建订单 + * + * @param userId 用户ID + * @param commodityCode 商品编号 + * @param orderCount 订购数量 + */ + void create(String userId, String commodityCode, int orderCount); +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/StorageService.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/StorageService.java new file mode 100644 index 000000000..0f68fad94 --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/StorageService.java @@ -0,0 +1,31 @@ +/* + * 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.seata.service; + +/** + * The interface Stock service. + */ +public interface StorageService { + + /** + * 扣减库存 + * + * @param commodityCode 商品编号 + * @param count 扣减数量 + */ + void deduct(String commodityCode, int count); +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.java new file mode 100644 index 000000000..ab3482aeb --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/AccountServiceImpl.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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.service.AccountService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * The type Account service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class AccountServiceImpl implements AccountService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); + + @Resource + private 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 = ?", money, userId); + LOGGER.info("Account Service End ... "); + } +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java new file mode 100644 index 000000000..b5d122baf --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/BusinessServiceImpl.java @@ -0,0 +1,59 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import io.seata.spring.annotation.GlobalTransactional; +import org.apache.seata.service.BusinessService; +import org.apache.seata.service.OrderService; +import org.apache.seata.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Random; + +/** + * The type Business service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class BusinessServiceImpl implements BusinessService { + + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); + + @Resource + private StorageService storageService; + @Resource + private OrderService orderService; + + private final Random random = new Random(); + + @Override + @GlobalTransactional(timeoutMills = 300000, name = "spring-seata-tx") + public void purchase(String userId, String commodityCode, int orderCount) { + LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); + storageService.deduct(commodityCode, orderCount); + orderService.create(userId, commodityCode, orderCount); + if (random.nextBoolean()) { + throw new RuntimeException("random exception mock!"); + } + } + +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..7aede43d7 --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/OrderServiceImpl.java @@ -0,0 +1,84 @@ +/* + * 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.service.AccountService; +import org.apache.seata.service.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.sql.PreparedStatement; +import java.util.Objects; + +/** + * The type Order service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class OrderServiceImpl implements OrderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); + + @Resource + private AccountService accountService; + @Resource + private JdbcTemplate jdbcTemplate; + + @Override + public void create(String userId, String commodityCode, int orderCount) { + LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID()); + + // 计算订单金额 + int orderMoney = calculate(commodityCode, orderCount); + + // 从账户余额扣款 + accountService.debit(userId, 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(con -> { + PreparedStatement pst = con.prepareStatement( + "insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)", + PreparedStatement.RETURN_GENERATED_KEYS); + pst.setObject(1, userId); + pst.setObject(2, commodityCode); + pst.setObject(3, orderCount); + pst.setObject(4, orderMoney); + return pst; + }, keyHolder); + + + LOGGER.info("Order Service End ... Created " + Objects.requireNonNull(keyHolder.getKey()).longValue()); + } + + private int calculate(String commodityId, int orderCount) { + return 200 * orderCount; + } + +} diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java new file mode 100644 index 000000000..8ee0cc42d --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/service/impl/StorageServiceImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed 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.seata.service.impl; + +import io.seata.core.context.RootContext; +import org.apache.seata.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * The type Stock service. + * + * @author jimin.jm @alibaba-inc.com + */ +@Service +public class StorageServiceImpl implements StorageService { + + private static final Logger LOGGER = LoggerFactory.getLogger(StorageService.class); + + @Resource + private 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 ... "); + + } + +} diff --git a/at-sample/springboot-seata/src/main/resources/all.sql b/at-sample/springboot-seata/src/main/resources/all.sql new file mode 100644 index 000000000..a6974d7f6 --- /dev/null +++ b/at-sample/springboot-seata/src/main/resources/all.sql @@ -0,0 +1,56 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +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`); \ No newline at end of file diff --git a/at-sample/springboot-seata/src/main/resources/application.properties b/at-sample/springboot-seata/src/main/resources/application.properties new file mode 100644 index 000000000..45ba421f4 --- /dev/null +++ b/at-sample/springboot-seata/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.application.name=springboot-seata +server.port=8088 +spring.datasource.driverClassName=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata?userSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=root +spring.datasource.password=123456 +seata.application-id=springboot-seata +seata.tx-service-group=my_test_tx_group \ No newline at end of file diff --git a/at-sample/springboot-seata/src/main/resources/file.conf b/at-sample/springboot-seata/src/main/resources/file.conf new file mode 100644 index 000000000..e426f6661 --- /dev/null +++ b/at-sample/springboot-seata/src/main/resources/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-seata/src/main/resources/registry.conf b/at-sample/springboot-seata/src/main/resources/registry.conf new file mode 100644 index 000000000..a105dc3e8 --- /dev/null +++ b/at-sample/springboot-seata/src/main/resources/registry.conf @@ -0,0 +1,124 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom + type = "file" + + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" + namespace = "" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + ##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here + #slbPattern = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + aclToken = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom + type = "file" + raft { + metadata-max-age-ms = 30000 + serverAddr = "127.0.0.1:8848" + } + nacos { + serverAddr = "127.0.0.1:8848" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + contextPath = "" + ##if use MSE Nacos with auth, mutex with username/password attribute + #accessKey = "" + #secretKey = "" + dataId = "seata.properties" + } + consul { + serverAddr = "127.0.0.1:8500" + key = "seata.properties" + aclToken = "" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + apolloAccesskeySecret = "" + cluster = "" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + nodePath = "/seata/seata.properties" + } + etcd3 { + serverAddr = "http://localhost:2379" + key = "seata.properties" + } + file { + name = "file.conf" + } + custom { + name = "" + } +} diff --git a/doc/img/fescar-1.png b/doc/img/fescar-1.png deleted file mode 100644 index fa009f41b..000000000 Binary files a/doc/img/fescar-1.png and /dev/null differ diff --git a/doc/img/fescar-2.png b/doc/img/fescar-2.png deleted file mode 100644 index 38b9a6c0f..000000000 Binary files a/doc/img/fescar-2.png and /dev/null differ diff --git a/doc/img/fescar.png b/doc/img/fescar.png deleted file mode 100644 index 6804b6942..000000000 Binary files a/doc/img/fescar.png and /dev/null differ diff --git a/doc/img/nacos-1.png b/doc/img/nacos-1.png deleted file mode 100644 index 448d6ff51..000000000 Binary files a/doc/img/nacos-1.png and /dev/null differ diff --git a/doc/img/nacos-2.png b/doc/img/nacos-2.png deleted file mode 100644 index 06a43dc3a..000000000 Binary files a/doc/img/nacos-2.png and /dev/null differ diff --git a/doc/img/nacos-3.png b/doc/img/nacos-3.png deleted file mode 100644 index 32aa4bc96..000000000 Binary files a/doc/img/nacos-3.png and /dev/null differ diff --git a/doc/img/seata.png b/doc/img/seata.png deleted file mode 100644 index a9a43c1a4..000000000 Binary files a/doc/img/seata.png and /dev/null differ diff --git a/doc/quick-integration-with-spring-cloud.md b/doc/quick-integration-with-spring-cloud.md deleted file mode 100644 index 8b994194e..000000000 --- a/doc/quick-integration-with-spring-cloud.md +++ /dev/null @@ -1,394 +0,0 @@ -# Spring Cloud 快速集成 Seata - -### 1. 添加依赖 - -添加Spring Cloud Alibaba 依赖管理工具和 Seata 依赖 - -
-Gradle - -```groovy -dependencyManagement { - imports { - mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:2.1.0.RELEASE" - } -} -``` - -``` -dependencies { - compile('com.alibaba.cloud:spring-cloud-starter-alibaba-seata') -} -``` - -
- -
-Maven - -```xml - - - - com.alibaba.cloud - spring-cloud-alibaba-dependencies - 2.1.0.RELEASE - pom - import - - - -``` - -```xml - - com.alibaba.cloud - spring-cloud-starter-alibaba-seata - -``` - -
- - -需要注意的是Spring Cloud Alibaba 的毕业版本的 GroupId 是 `com.alibaba.cloud` - -`spring-cloud-starter-alibaba-seata`这个依赖中只依赖了`spring-cloud-alibaba-seata`,所以在项目中添加`spring-cloud-starter-alibaba-seata` -和`spring-cloud-alibaba-seata`是一样的 - -### 2. 添加Seata 配置文件 - -#### registry.conf - -该配置用于指定 TC 的注册中心和配置文件,默认都是 file; 如果使用其他的注册中心,要求 Seata-Server 也注册到该配置中心上 - -
-registry.conf - -``` -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "file" - - nacos { - serverAddr = "localhost" - namespace = "public" - cluster = "default" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3 - type = "file" - - nacos { - serverAddr = "localhost" - namespace = "public" - cluster = "default" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - app.id = "seata-server" - apollo.meta = "http://192.168.1.204:8801" - } - zk { - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} -``` - -
- -#### file.conf - -该配置用于指定TC的相关属性;如果使用注册中心也可以将配置添加到配置中心 - -
-file.conf - -``` -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - #thread factory for netty - thread-factory { - boss-thread-prefix = "NettyBoss" - worker-thread-prefix = "NettyServerNIOWorker" - server-executor-thread-prefix = "NettyServerBizHandler" - share-boss-worker = false - client-selector-thread-prefix = "NettyClientSelector" - client-selector-thread-size = 1 - client-worker-thread-prefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - boss-thread-size = 1 - #auto default pin or 8 - worker-thread-size = 8 - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #vgroup->rgroup - vgroupMapping.my_test_tx_group = "default" - #only support single node - default.grouplist = "127.0.0.1:8091" - #degrade current not support - enableDegrade = false - #disable - disable = false - #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent - max.commit.retry.timeout = "-1" - max.rollback.retry.timeout = "-1" -} - -client { - async.commit.buffer.limit = 10000 - lock { - retry.internal = 10 - retry.times = 30 - } - report.retry.count = 5 -} - -## transaction log store -store { - ## store mode: file、db - mode = "file" - - ## file store - file { - dir = "sessionStore" - - # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions - max-branch-session-size = 16384 - # globe session size , if exceeded throws exceptions - max-global-session-size = 512 - # file buffer size , if exceeded allocate new buffer - file-write-buffer-cache-size = 16384 - # when recover batch read size - session.reload.read_size = 100 - # async, sync - flush-disk-mode = async - } - - ## database store - db { - ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. - datasource = "dbcp" - ## mysql/oracle/h2/oceanbase etc. - db-type = "mysql" - url = "jdbc:mysql://127.0.0.1:3306/seata" - user = "mysql" - password = "mysql" - min-conn = 1 - max-conn = 3 - global.table = "global_table" - branch.table = "branch_table" - lock-table = "lock_table" - query-limit = 100 - } -} -lock { - ## the lock store mode: local、remote - mode = "remote" - - local { - ## store locks in user's database - } - - remote { - ## store locks in the seata's server - } -} -recovery { - committing-retry-delay = 30 - asyn-committing-retry-delay = 30 - rollbacking-retry-delay = 30 - timeout-retry-delay = 30 -} - -transaction { - undo.data.validation = true - undo.log.serialization = "jackson" -} - -## metrics settings -metrics { - enabled = false - registry-type = "compact" - # multi exporters use comma divided - exporter-list = "prometheus" - exporter-prometheus-port = 9898 -} -``` - -
- -需要注意的是 `service.vgroup_mapping`这个配置,在 Spring Cloud 中默认是`${spring.application.name}-fescar-service-group` -,可以通过指定`application.properties`的 `spring.cloud.alibaba.seata.tx-service-group`这个属性覆盖,但是必须要和 `file.conf ` -中的一致,否则会提示 `no available server to connect` - -### 3. 注入数据源 - -Seata 通过代理数据源的方式实现分支事务;MyBatis 和 JPA 都需要注入 `io.seata.rm.datasource.DataSourceProxy`, 不同的是,MyBatis -还需要额外注入 `org.apache.ibatis.session.SqlSessionFactory` - -
-MyBatis - -```java -@Configuration -public class DataSourceProxyConfig { - - @Bean - @ConfigurationProperties(prefix = "spring.datasource") - public DataSource dataSource() { - return new DruidDataSource(); - } - - @Bean - public DataSourceProxy dataSourceProxy(DataSource dataSource) { - return new DataSourceProxy(dataSource); - } - - @Bean - public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception { - SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); - sqlSessionFactoryBean.setDataSource(dataSourceProxy); - return sqlSessionFactoryBean.getObject(); - } -} -``` - -
- - -
-JPA - -```java -@Configuration -public class DataSourceProxyConfig { - - @Bean - @ConfigurationProperties(prefix = "spring.datasource") - public DruidDataSource druidDataSource() { - return new DruidDataSource(); - } - - @Primary - @Bean - public DataSourceProxy dataSource(DruidDataSource druidDataSource) { - return new DataSourceProxy(druidDataSource); - } - -} -``` - -
- -如果使用的是 Hikari 数据源,需要修改数据源的配置,以及注入的 Bean 的配置前缀 - -``` -spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -spring.datasource.hikari.username=root -spring.datasource.hikari.password=123456 -``` - -```java -@Bean -@ConfigurationProperties(prefix = "spring.datasource.hikari") -public DataSource dataSource() { - return new HikariDataSource(); -} -``` - -### 4. 添加 undo_log 表 - -在业务相关的数据库中添加 undo_log 表,用于保存需要回滚的数据 - -```sql -CREATE TABLE `undo_log` -( - `id` BIGINT(20) NOT NULL AUTO_INCREMENT, - `branch_id` BIGINT(20) NOT NULL, - `xid` VARCHAR(100) NOT NULL, - `context` VARCHAR(128) NOT NULL, - `rollback_info` LONGBLOB NOT NULL, - `log_status` INT(11) NOT NULL, - `log_created` DATETIME NOT NULL, - `log_modified` DATETIME NOT NULL, - `ext` VARCHAR(100) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8 -``` - -### 5. 启动 Seata-Server - -在 [https://github.com/seata/seata/releases](https://github.com/seata/seata/releases) 下载相应版本的 -Seata-Server,修改 `registry.conf`为相应的配置(如果使用 file 则不需要修改),解压并通过以下命令启动: - -```bash -sh ./bin/seata-server.sh -``` - -### 6. 使用`@GlobalTransactional`开启事务 - -在业务的发起方的方法上使用`@GlobalTransactional`开启全局事务,Seata 会将事务的 xid 通过拦截器添加到调用其他服务的请求中,实现分布式事务 - diff --git a/dubbo-multiple-datasource-mybatis-plus/README.md b/dubbo-multiple-datasource-mybatis-plus/README.md deleted file mode 100644 index 94bd00df1..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# SpringBoot-Dubbo使用 Seata 实现分布式事务 - MyBatisPlus动态数据源-Nacos为配置/注册中心 - -> 使用 Seata 作为分布式事务组件,使用 MySQL 数据库,使用 MyBatis 作为数据访问层实现多数据源下事务一致,使用 MyBatisPlus 作为 MyBatis 的辅助工具,Nacos为配置/注册中心 - -## 环境准备 - -### 创建数据库及表 - -根据sql文件夹内的sql文件名创建对应表,运行sql - -### 安装Seata跟Nacos - -按照该篇[文章](http://seata.io/zh-cn/blog/seata-nacos-analysis.html)安装seata跟nacos配置 - -## 测试 - -- 先后启动provider跟comsumer -- 测试mp分页查询是否启用: http://127.0.0.1:28888/test/pageByProduct -- 测试事务回滚: http://127.0.0.1:28888/test/testRollback -- 测试事务提交: http://127.0.0.1:28888/test/testCommit - diff --git a/dubbo-multiple-datasource-mybatis-plus/common/pom.xml b/dubbo-multiple-datasource-mybatis-plus/common/pom.xml deleted file mode 100644 index b25228a0d..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - dubbo-multiple-datasource-mybatis-plus - io.seata.samples - 1.1.0 - - 4.0.0 - - common - - - 8 - 8 - - - \ No newline at end of file diff --git a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Account.java b/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Account.java deleted file mode 100644 index aa545997a..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Account.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.entity; - -import java.io.Serializable; -import java.time.LocalDateTime; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * @author Funkye - * @since 2019-12-07 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -public class Account implements Serializable { - - private static final long serialVersionUID = 1L; - - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - private String userName; - - private Integer sum; - - private LocalDateTime lastUpdateTime; - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Orders.java b/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Orders.java deleted file mode 100644 index af3b250b9..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Orders.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.entity; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.time.LocalDateTime; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * @author Funkye - * @since 2019-12-07 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -public class Orders implements Serializable { - - private static final long serialVersionUID = 1L; - - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - private Integer productId; - - private BigDecimal amount; - - private Integer sum; - - private Integer accountId; - - private LocalDateTime createTime; - - private LocalDateTime replaceTime; - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Product.java b/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Product.java deleted file mode 100644 index 85d75bbab..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/entity/Product.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.entity; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.time.LocalDateTime; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * @author Funkye - * @since 2019-12-07 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -public class Product implements Serializable { - - private static final long serialVersionUID = 1L; - - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - private BigDecimal price; - - private Integer stock; - - private Integer accountId; - - private LocalDateTime lastUpdateTime; - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/DemoService.java b/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/DemoService.java deleted file mode 100644 index 326e637ae..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/DemoService.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import io.seata.core.exception.TransactionException; -import io.seata.spring.annotation.GlobalTransactional; - -/** - * @author 陈健斌 - * @date 2019/12/05 - */ -public interface DemoService { - - /** - * @return - * @throws TransactionException - */ - public Object testRollback() throws TransactionException; - - /** - * @return - * @throws TransactionException - */ - public Object testCommit() throws TransactionException; -} diff --git a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IAccountService.java b/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IAccountService.java deleted file mode 100644 index 8f378a6f9..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IAccountService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import com.baomidou.mybatisplus.extension.service.IService; - -import io.seata.samples.entity.Account; - -/** - *

- * 功能 服务类 - *

- * - * @author Funkye - * @since 2019-04-10 - */ -public interface IAccountService extends IService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IOrdersService.java b/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IOrdersService.java deleted file mode 100644 index 6ba34f8b1..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IOrdersService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import com.baomidou.mybatisplus.extension.service.IService; - -import io.seata.samples.entity.Orders; - -/** - *

- * 功能 服务类 - *

- * - * @author Funkye - * @since 2019-04-10 - */ -public interface IOrdersService extends IService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IProductService.java b/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IProductService.java deleted file mode 100644 index be73f2503..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/common/src/main/java/io/seata/samples/service/IProductService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import com.baomidou.mybatisplus.extension.service.IService; - -import io.seata.samples.entity.Product; - -/** - *

- * 功能 服务类 - *

- * - * @author Funkye - * @since 2019-04-10 - */ -public interface IProductService extends IService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/pom.xml b/dubbo-multiple-datasource-mybatis-plus/consumer/pom.xml deleted file mode 100644 index bfa8462f0..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 4.0.0 - - io.seata - dubbo-multiple-datasource-mybatis-plus - 1.1.0 - - consumer - consumer - http://maven.apache.org - - UTF-8 - - - - - diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/ClientApplication.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/ClientApplication.java deleted file mode 100644 index fa31531a5..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/ClientApplication.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples; - -import java.util.TimeZone; -import java.util.concurrent.Executor; - -import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; - -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, MybatisPlusAutoConfiguration.class}) -@EnableDubbo(scanBasePackages = {"io.seata.samples.service"}) -public class ClientApplication { - public static void main(String[] args) { - TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); - SpringApplication app = new SpringApplication(ClientApplication.class); - app.run(args); - } - - @Bean(name = "threadPoolTaskExecutor") - public Executor threadPoolTaskExecutor() { - return new ThreadPoolTaskExecutor(); - } -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/config/SeataAutoConfig.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/config/SeataAutoConfig.java deleted file mode 100644 index 82517b7ef..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/config/SeataAutoConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.config; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import io.seata.spring.annotation.GlobalTransactionScanner; - -@Configuration -public class SeataAutoConfig { - private final static Logger logger = LoggerFactory.getLogger(SeataAutoConfig.class); - - /** - * init global transaction scanner - * - * @Return: GlobalTransactionScanner - */ - @Bean - public GlobalTransactionScanner globalTransactionScanner() { - logger.info("配置seata........"); - return new GlobalTransactionScanner("test-consumer", "my_test_tx_group"); - } -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/controller/TestController.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/controller/TestController.java deleted file mode 100644 index 3e6bd28b3..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/controller/TestController.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.controller; - -import org.apache.dubbo.config.annotation.Reference; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; - -import io.seata.core.exception.TransactionException; -import io.seata.samples.entity.Product; -import io.seata.samples.service.DemoService; -import io.seata.samples.service.IProductService; - -/** - *

- * 文件表 前端控制器 - *

- * - * @author funkye - * @since 2019-03-20 - */ -@RestController -@RequestMapping("/test") -public class TestController { - - private final static Logger logger = LoggerFactory.getLogger(TestController.class); - @Reference(version = "1.0.0", timeout = 60000) - DemoService demoService; - @Reference(version = "1.0.0", timeout = 60000) - private IProductService productService; - - /** - * 测试mp分页插件是否生效 - * - * @return - */ - @GetMapping(value = "pageByProduct") - public Object pageByProduct() { - return productService.page(new Page(1, 10)); - } - - /** - * 测试事务提交 - * - * @return - * @throws TransactionException - */ - @GetMapping(value = "testCommit") - public Object testCommit() throws TransactionException { - return demoService.testCommit(); - } - - /** - * 测试事务回滚 - * - * @return - * @throws TransactionException - */ - @GetMapping(value = "testRollback") - public Object testRollback() throws TransactionException { - return demoService.testRollback(); - } - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Account.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Account.java deleted file mode 100644 index aa545997a..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Account.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.entity; - -import java.io.Serializable; -import java.time.LocalDateTime; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * @author Funkye - * @since 2019-12-07 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -public class Account implements Serializable { - - private static final long serialVersionUID = 1L; - - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - private String userName; - - private Integer sum; - - private LocalDateTime lastUpdateTime; - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Orders.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Orders.java deleted file mode 100644 index af3b250b9..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Orders.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.entity; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.time.LocalDateTime; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * @author Funkye - * @since 2019-12-07 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -public class Orders implements Serializable { - - private static final long serialVersionUID = 1L; - - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - private Integer productId; - - private BigDecimal amount; - - private Integer sum; - - private Integer accountId; - - private LocalDateTime createTime; - - private LocalDateTime replaceTime; - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Product.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Product.java deleted file mode 100644 index 85d75bbab..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/entity/Product.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.entity; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.time.LocalDateTime; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * @author Funkye - * @since 2019-12-07 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -public class Product implements Serializable { - - private static final long serialVersionUID = 1L; - - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - private BigDecimal price; - - private Integer stock; - - private Integer accountId; - - private LocalDateTime lastUpdateTime; - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/DemoService.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/DemoService.java deleted file mode 100644 index 71d2b44a7..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/DemoService.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import io.seata.core.exception.TransactionException; -import io.seata.spring.annotation.GlobalTransactional; - -/** - * @author 陈健斌 - * @date 2019/12/05 - */ -public interface DemoService { - - /** - * @return - * @throws TransactionException - */ - public Object testRollback() throws TransactionException; - - /** - * @return - * @throws TransactionException - */ - @GlobalTransactional - public Object testCommit() throws TransactionException; -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/DemoServiceImpl.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/DemoServiceImpl.java deleted file mode 100644 index dc8148b0d..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/DemoServiceImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import java.time.LocalDateTime; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.config.annotation.DubboService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.baomidou.mybatisplus.core.toolkit.Wrappers; - -import io.seata.core.context.RootContext; -import io.seata.core.exception.TransactionException; -import io.seata.samples.entity.Account; -import io.seata.samples.entity.Orders; -import io.seata.samples.entity.Product; -import io.seata.spring.annotation.GlobalTransactional; -import io.seata.tm.api.GlobalTransactionContext; -import org.springframework.stereotype.Service; - -/** - * @author 陈健斌 - * @date 2019/12/05 - */ -@Service -public class DemoServiceImpl implements DemoService { - private final static Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class); - @DubboReference(version = "1.0.0", timeout = 60000, check = false) - private IAccountService accountService; - @DubboReference(version = "1.0.0", timeout = 60000, check = false) - private IOrdersService ordersService; - @DubboReference(version = "1.0.0", timeout = 60000, check = false) - private IProductService productService; - private Lock lock = new ReentrantLock(); - - /** - * @return - * @throws TransactionException - */ - @Override - @GlobalTransactional - public Object testRollback() throws TransactionException { - logger.info("seata分布式事务Id:{}", RootContext.getXID()); - lock.lock(); - try { - LocalDateTime now = LocalDateTime.now(); - Product product = productService.getOne(Wrappers.query().eq("id", 1).last("for update")); - if (product.getStock() > 0) { - Account account = accountService.getById(1); - Orders orders = new Orders(); - orders.setCreateTime(now); - orders.setProductId(product.getId()); - orders.setReplaceTime(now); - orders.setSum(1); - orders.setAmount(product.getPrice()); - orders.setAccountId(account.getId()); - product.setStock(product.getStock() - 1); - account.setSum(account.getSum() != null ? account.getSum() + 1 : 1); - account.setLastUpdateTime(now); - productService.updateById(product); - accountService.updateById(account); - ordersService.save(orders); - int i = 1 / 0; - return true; - } else { - return false; - } - } catch (Exception e) { - // TODO: handle exception - logger.info("载入事务id进行回滚"); - GlobalTransactionContext.reload(RootContext.getXID()).rollback(); - return false; - } finally { - lock.unlock(); - } - } - - /** - * @return - * @throws TransactionException - */ - @Override - @GlobalTransactional - public Object testCommit() throws TransactionException { - lock.lock(); - try { - LocalDateTime now = LocalDateTime.now(); - Product product = productService.getOne(Wrappers.query().eq("id", 1).last("for update")); - if (product.getStock() > 0) { - logger.info("seata分布式事务Id:{}", RootContext.getXID()); - Account account = accountService.getById(1); - Orders orders = new Orders(); - orders.setCreateTime(now); - orders.setProductId(product.getId()); - orders.setReplaceTime(now); - orders.setSum(1); - orders.setAmount(product.getPrice()); - orders.setAccountId(account.getId()); - product.setStock(product.getStock() - 1); - account.setSum(account.getSum() != null ? account.getSum() + 1 : 1); - account.setLastUpdateTime(now); - productService.updateById(product); - accountService.updateById(account); - ordersService.save(orders); - return true; - } else { - return false; - } - } catch (Exception e) { - // TODO: handle exception - logger.info("载入事务{}进行回滚" + e.getMessage(), RootContext.getXID()); - GlobalTransactionContext.reload(RootContext.getXID()).rollback(); - return false; - } finally { - lock.unlock(); - } - } -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IAccountService.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IAccountService.java deleted file mode 100644 index 8f378a6f9..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IAccountService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import com.baomidou.mybatisplus.extension.service.IService; - -import io.seata.samples.entity.Account; - -/** - *

- * 功能 服务类 - *

- * - * @author Funkye - * @since 2019-04-10 - */ -public interface IAccountService extends IService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IOrdersService.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IOrdersService.java deleted file mode 100644 index 6ba34f8b1..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IOrdersService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import com.baomidou.mybatisplus.extension.service.IService; - -import io.seata.samples.entity.Orders; - -/** - *

- * 功能 服务类 - *

- * - * @author Funkye - * @since 2019-04-10 - */ -public interface IOrdersService extends IService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IProductService.java b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IProductService.java deleted file mode 100644 index be73f2503..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/java/io/seata/samples/service/IProductService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service; - -import com.baomidou.mybatisplus.extension.service.IService; - -import io.seata.samples.entity.Product; - -/** - *

- * 功能 服务类 - *

- * - * @author Funkye - * @since 2019-04-10 - */ -public interface IProductService extends IService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/resources/application.yml b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/resources/application.yml deleted file mode 100644 index 15468eae0..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/resources/application.yml +++ /dev/null @@ -1,32 +0,0 @@ -spring: - application: - name: test-consumer - datasource: - driver-class-name: com.mysql.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/test?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai - username: root - password: 123456 - mvc: - servlet: - load-on-startup: 1 - http: - encoding: - force: true - charset: utf-8 - enabled: true - multipart: - max-file-size: 10MB - max-request-size: 10MB -dubbo: - registry: - id: my-registry - address: nacos://127.0.0.1:8848 - application: - name: test-consumer - qos-enable: false -server: - port: 28888 - max-http-header-size: 8192 - address: 0.0.0.0 - tomcat: - max-http-post-size: 104857600 \ No newline at end of file diff --git a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/resources/registry.conf b/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/resources/registry.conf deleted file mode 100644 index 0700885ff..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/consumer/src/main/resources/registry.conf +++ /dev/null @@ -1,82 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - serverAddr = "localhost" - namespace = "" - cluster = "default" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - password = "" - cluster = "default" - timeout = "0" - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig - type = "nacos" - - nacos { - serverAddr = "localhost" - namespace = "" - group = "SEATA_GROUP" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - app.id = "seata-server" - apollo.meta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/dubbo-multiple-datasource-mybatis-plus/pom.xml b/dubbo-multiple-datasource-mybatis-plus/pom.xml deleted file mode 100644 index 05c028bc2..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/pom.xml +++ /dev/null @@ -1,98 +0,0 @@ - - 4.0.0 - io.seata.samples - dubbo-multiple-datasource-mybatis-plus - 1.1.0 - dubbo-multiple-datasource-mybatis-plus - http://maven.apache.org - - 3.1 - UTF-8 - UTF-8 - 1.8 - 1.8 - 3.3.0 - 2.7.15 - 2.3.1.RELEASE - - - - org.mybatis - mybatis-typehandlers-jsr310 - 1.0.2 - - - com.alibaba.nacos - nacos-client - 1.1.4 - - - org.apache.dubbo - dubbo-registry-nacos - ${dubbo.version} - - - org.apache.dubbo - dubbo-spring-boot-starter - ${dubbo.version} - - - - com.baomidou - mybatis-plus-boot-starter - ${mybatis-plus-boot-starter.version} - - - - org.projectlombok - lombok - provided - 1.18.8 - - - io.seata - seata-all - - - com.alibaba - druid-spring-boot-starter - 1.1.20 - - - mysql - mysql-connector-java - - - org.springframework.boot - spring-boot-starter-web - - - pom - - provider - consumer - common - - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - - - - io.seata - seata-all - 1.4.2 - - - - - diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/pom.xml b/dubbo-multiple-datasource-mybatis-plus/provider/pom.xml deleted file mode 100644 index 060f9f066..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - - io.seata.samples - dubbo-multiple-datasource-mybatis-plus - 1.1.0 - - provider - provider - http://maven.apache.org - - UTF-8 - - - - io.seata.samples - common - 1.1.0 - - - com.baomidou - dynamic-datasource-spring-boot-starter - 3.0.0 - - - com.fasterxml.jackson.core - jackson-databind - - - - diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/ProviderApplication.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/ProviderApplication.java deleted file mode 100644 index 5133501e3..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/ProviderApplication.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples; - -import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; - -/** - * @author funkye - * @date 2019/12/7 - */ -@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class}) -public class ProviderApplication { - - public static void main(String[] args) { - SpringApplication app = new SpringApplication(ProviderApplication.class); - app.run(args); - } - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/config/MybatisPlusConfig.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/config/MybatisPlusConfig.java deleted file mode 100644 index 74b33021c..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/config/MybatisPlusConfig.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.config; - -import java.util.ArrayList; -import java.util.List; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import com.baomidou.mybatisplus.core.parser.ISqlParser; -import com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser; -import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; - -@Configuration -@MapperScan("io.seata.samples.mapper*") -public class MybatisPlusConfig { - - /** - * mybatis-plus分页插件
- * 文档:http://mp.baomidou.com
- */ - @Bean - public PaginationInterceptor paginationInterceptor() { - PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); - List sqlParserList = new ArrayList(); - // 攻击 SQL 阻断解析器、加入解析链 - sqlParserList.add(new BlockAttackSqlParser()); - paginationInterceptor.setSqlParserList(sqlParserList); - return paginationInterceptor; - } - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/config/SeataAutoConfig.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/config/SeataAutoConfig.java deleted file mode 100644 index b5e68082b..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/config/SeataAutoConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.config; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import io.seata.spring.annotation.GlobalTransactionScanner; - -@Configuration -public class SeataAutoConfig { - private final static Logger logger = LoggerFactory.getLogger(SeataAutoConfig.class); - - /** - * init global transaction scanner - * - * @Return: GlobalTransactionScanner - */ - @Bean - public GlobalTransactionScanner globalTransactionScanner() { - logger.info("配置seata........"); - return new GlobalTransactionScanner("test-provider", "my_test_tx_group"); - } -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/AccountMapper.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/AccountMapper.java deleted file mode 100644 index 7ceca1d0a..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/AccountMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; - -import io.seata.samples.entity.Account; - -/** - * @author Funkye - * @since 2019-12-07 - */ -public interface AccountMapper extends BaseMapper { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/OrdersMapper.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/OrdersMapper.java deleted file mode 100644 index 40f2ecbe0..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/OrdersMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; - -import io.seata.samples.entity.Orders; - -/** - * @author Funkye - * @since 2019-12-07 - */ -public interface OrdersMapper extends BaseMapper { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/ProductMapper.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/ProductMapper.java deleted file mode 100644 index 3482fd338..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/mapper/ProductMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; - -import io.seata.samples.entity.Product; - -/** - * @author Funkye - * @since 2019-12-07 - */ -public interface ProductMapper extends BaseMapper { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/AccountServiceImpl.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/AccountServiceImpl.java deleted file mode 100644 index 8cb3a5c99..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service.impl; - -import com.baomidou.mybatisplus.extension.service.IService; -import io.seata.samples.service.IAccountService; -import org.apache.dubbo.config.annotation.DubboService; - -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - -import io.seata.samples.entity.Account; -import io.seata.samples.mapper.AccountMapper; - -@DubboService(version = "1.0.0", interfaceClass = IAccountService.class) -@DS(value = "master_1") -public class AccountServiceImpl extends ServiceImpl implements IAccountService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/OrdersServiceImpl.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/OrdersServiceImpl.java deleted file mode 100644 index 5d5b76075..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/OrdersServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service.impl; - -import com.baomidou.mybatisplus.extension.service.IService; -import io.seata.samples.service.IOrdersService; -import io.seata.samples.service.IProductService; -import org.apache.dubbo.config.annotation.DubboService; - -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - -import io.seata.samples.entity.Orders; -import io.seata.samples.mapper.OrdersMapper; - -@DubboService(version = "1.0.0", interfaceClass = IOrdersService.class) -@DS(value = "master_2") -public class OrdersServiceImpl extends ServiceImpl implements IOrdersService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/ProductServiceImpl.java b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/ProductServiceImpl.java deleted file mode 100644 index dfb76d627..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/java/io/seata/samples/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.service.impl; - -import com.baomidou.mybatisplus.extension.service.IService; -import io.seata.samples.service.IProductService; -import org.apache.dubbo.config.annotation.DubboService; - -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - -import io.seata.samples.entity.Product; -import io.seata.samples.mapper.ProductMapper; - -@DubboService(version = "1.0.0", interfaceClass = IProductService.class) -@DS(value = "master_3") -public class ProductServiceImpl extends ServiceImpl implements IProductService { - -} diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/application.yml b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/application.yml deleted file mode 100644 index 245e225fe..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/application.yml +++ /dev/null @@ -1,51 +0,0 @@ -server: - port: 38888 -spring: - application: - name: test-provider - datasource: - dynamic: - seata: true - primary: master_1 - datasource: - master_1: - url: jdbc:mysql://127.0.0.1:3306/test_pay?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC - driver-class-name: com.mysql.cj.jdbc.Driver - username: root - password: 123456 - master_2: - url: jdbc:mysql://127.0.0.1:3306/test_order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC - driver-class-name: com.mysql.cj.jdbc.Driver - username: root - password: 123456 - master_3: - url: jdbc:mysql://127.0.0.1:3306/test_storage?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC - driver-class-name: com.mysql.cj.jdbc.Driver - username: root - password: 123456 -dubbo: - protocol: - loadbalance: leastactive - threadpool: cached - scan: - base-packages: io.seata.samples.service - application: - qos-enable: false - name: test-provider - registry: - id: my-registry - address: nacos://127.0.0.1:8848 - group: SEATA_GROUP -mybatis-plus: - mapper-locations: classpath:/mapper/*Mapper.xml - typeAliasesPackage: io.seata.samples.entity - global-config: - db-config: - field-strategy: not-empty - id-type: auto - db-type: mysql - configuration: - map-underscore-to-camel-case: true - cache-enabled: true - auto-mapping-unknown-column-behavior: none - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl \ No newline at end of file diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/AccountMapper.xml b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/AccountMapper.xml deleted file mode 100644 index 76b9e0fce..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/AccountMapper.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/OrdersMapper.xml b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/OrdersMapper.xml deleted file mode 100644 index 916adb829..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/OrdersMapper.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/ProductMapper.xml b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/ProductMapper.xml deleted file mode 100644 index af65a815c..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/mapper/ProductMapper.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/registry.conf b/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/registry.conf deleted file mode 100644 index ad2c5f26f..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/provider/src/main/resources/registry.conf +++ /dev/null @@ -1,96 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - application = "seata-server" - serverAddr = "127.0.0.1:8848" - group = "SEATA_GROUP" - namespace = "" - cluster = "default" - username = "nacos" - password = "nacos" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = 0 - password = "" - cluster = "default" - timeout = 0 - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - aclToken = "" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3 - type = "nacos" - - nacos { - serverAddr = "127.0.0.1:8848" - namespace = "" - group = "SEATA_GROUP" - username = "nacos" - password = "nacos" - dataId = "nacos-server.properties" - } - consul { - serverAddr = "127.0.0.1:8500" - aclToken = "" - } - apollo { - appId = "seata-server" - ## apolloConfigService will cover apolloMeta - apolloMeta = "http://192.168.1.204:8801" - apolloConfigService = "http://192.168.1.204:8080" - namespace = "application" - apolloAccesskeySecret = "" - cluster = "seata" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - nodePath = "/seata/seata.properties" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/dubbo-multiple-datasource-mybatis-plus/sql/test_order.sql b/dubbo-multiple-datasource-mybatis-plus/sql/test_order.sql deleted file mode 100644 index db38a5b2b..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/sql/test_order.sql +++ /dev/null @@ -1,32 +0,0 @@ --- test_order.orders definition - -CREATE TABLE `orders` ( - `id` int NOT NULL AUTO_INCREMENT, - `product_id` int DEFAULT NULL, - `amount` double(11,2) DEFAULT NULL, - `sum` int DEFAULT NULL, - `create_time` datetime DEFAULT NULL, - `replace_time` datetime DEFAULT NULL, - `account_id` int DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - -INSERT INTO orders(product_id, amount, sum, create_time, replace_time, account_id) -VALUES(0, 0, 0, '2022-01-01 01:01:00', '2022-01-01 01:01:00', 0); - - --- test_order.undo_log definition - -CREATE TABLE `undo_log` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `branch_id` bigint NOT NULL, - `xid` varchar(100) CHARACTER SET utf8 NOT NULL, - `context` varchar(128) CHARACTER SET utf8 NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - `ext` varchar(100) CHARACTER SET utf8 DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; \ No newline at end of file diff --git a/dubbo-multiple-datasource-mybatis-plus/sql/test_pay.sql b/dubbo-multiple-datasource-mybatis-plus/sql/test_pay.sql deleted file mode 100644 index aa74b6819..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/sql/test_pay.sql +++ /dev/null @@ -1,28 +0,0 @@ --- test_pay.account definition - -CREATE TABLE `account` ( - `id` int NOT NULL AUTO_INCREMENT, - `user_name` varchar(255) CHARACTER SET utf8 DEFAULT NULL, - `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `sum` int DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - -INSERT INTO account (user_name, last_update_time, sum) -VALUES('', CURRENT_TIMESTAMP, 0); - --- test_pay.undo_log definition - -CREATE TABLE `undo_log` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `branch_id` bigint NOT NULL, - `xid` varchar(100) CHARACTER SET utf8 NOT NULL, - `context` varchar(128) CHARACTER SET utf8 NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - `ext` varchar(100) CHARACTER SET utf8 DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; \ No newline at end of file diff --git a/dubbo-multiple-datasource-mybatis-plus/sql/test_storage.sql b/dubbo-multiple-datasource-mybatis-plus/sql/test_storage.sql deleted file mode 100644 index 2c052101e..000000000 --- a/dubbo-multiple-datasource-mybatis-plus/sql/test_storage.sql +++ /dev/null @@ -1,26 +0,0 @@ --- test_storage.product definition - -CREATE TABLE `product` ( - `id` int NOT NULL AUTO_INCREMENT, - `price` double DEFAULT NULL, - `stock` int DEFAULT NULL, - `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - - --- test_storage.undo_log definition - -CREATE TABLE `undo_log` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `branch_id` bigint NOT NULL, - `xid` varchar(100) CHARACTER SET utf8 NOT NULL, - `context` varchar(128) CHARACTER SET utf8 NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - `ext` varchar(100) CHARACTER SET utf8 DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; \ No newline at end of file diff --git a/dubbo/README.md b/dubbo/README.md deleted file mode 100644 index 5f44825af..000000000 --- a/dubbo/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# dubbo - -How to use Seata to ensure consistency between Dubbo Microservices ? - -Please see the blog: -Engligh: http://dubbo.apache.org/en-us/blog/dubbo-fescar.html -中 文: http://dubbo.apache.org/zh-cn/blog/dubbo-fescar.html - -## Quick Start - -1. Startup Seata Server - -```shell script -docker run --name seata-file -p 8091:8091 hellowoodes/seata:0.9.0-file -``` - -> You can also download seata [release](https://github.com/seata/seata/releases) version ,then run bin/seata-server . - -2. Startup Zookeeper - -```shell script -docker run --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -d zookeeper -``` - -3. Execute SQL under `seata-samples\dubbo\src\main\resources\sql` - -4. Run `DubboStockServiceStarter`,`DubboAccountServiceStarter`,`DubboOrderServiceStarter`,`DubboBusinessTester` - diff --git a/dubbo/pom.xml b/dubbo/pom.xml deleted file mode 100644 index 2472e87b2..000000000 --- a/dubbo/pom.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - io.seata - seata-samples - 1.1.0 - - 4.0.0 - seata-samples-dubbo - jar - seata-samples-dubbo ${project.version} - - - org.apache.dubbo - dubbo - - - io.seata - seata-all - - - com.101tec - zkclient - - - com.alibaba - dubbo-registry-nacos - - - com.alibaba.spring - spring-context-support - - - junit - junit - test - - - jakarta.annotation - jakarta.annotation-api - - - org.springframework - spring-jdbc - - - mysql - mysql-connector-java - - - org.apache.curator - curator-recipes - - - - - - - - com.google.guava - guava - - - com.fasterxml.jackson.core - jackson-databind - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - - - diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/ApplicationKeeper.java b/dubbo/src/main/java/io/seata/samples/dubbo/ApplicationKeeper.java deleted file mode 100644 index c59c9c4bf..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/ApplicationKeeper.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo; - -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.support.AbstractApplicationContext; - -/** - * The type Application keeper. - */ -public class ApplicationKeeper { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationKeeper.class); - - private final ReentrantLock LOCK = new ReentrantLock(); - private final Condition STOP = LOCK.newCondition(); - - /** - * Instantiates a new Application keeper. - * - * @param applicationContext the application context - */ - public ApplicationKeeper(AbstractApplicationContext applicationContext) { - addShutdownHook(applicationContext); - } - - private void addShutdownHook(final AbstractApplicationContext applicationContext) { - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { - @Override - public void run() { - try { - applicationContext.close(); - LOGGER.info("ApplicationContext " + applicationContext + " is closed."); - } catch (Exception e) { - LOGGER.error("Failed to close ApplicationContext", e); - } - - LOCK.lock(); - try { - STOP.signal(); - } finally { - LOCK.unlock(); - } - } - })); - } - - /** - * Keep. - */ - public void keep() { - LOCK.lock(); - try { - LOGGER.info("Application is keep running ... "); - STOP.await(); - } catch (InterruptedException e) { - LOGGER.error("ApplicationKeeper.keep() is interrupted by InterruptedException!", e); - } finally { - LOCK.unlock(); - } - } -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/Order.java b/dubbo/src/main/java/io/seata/samples/dubbo/Order.java deleted file mode 100644 index 9e05541d2..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/Order.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo; - -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/dubbo/src/main/java/io/seata/samples/dubbo/service/AccountService.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/AccountService.java deleted file mode 100644 index 9783fe7e4..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/AccountService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service; - -/** - * The interface Account service. - */ -public interface AccountService { - - /** - * 余额扣款 - * - * @param userId 用户ID - * @param money 扣款金额 - */ - void debit(String userId, int money); -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/service/BusinessService.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/BusinessService.java deleted file mode 100644 index eb3849dea..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/BusinessService.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service; - -/** - * The interface Business service. - */ -public interface BusinessService { - - /** - * 用户订购商品 - * - * @param userId 用户ID - * @param commodityCode 商品编号 - * @param orderCount 订购数量 - */ - void purchase(String userId, String commodityCode, int orderCount); -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/service/OrderService.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/OrderService.java deleted file mode 100644 index 799d6b28e..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/OrderService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service; - -import io.seata.samples.dubbo.Order; - -/** - * The interface Order service. - */ -public interface OrderService { - /** - * 创建订单 - * - * @param userId 用户ID - * @param commodityCode 商品编号 - * @param orderCount 订购数量 - * @return 生成的订单 order - */ - Order create(String userId, String commodityCode, int orderCount); -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/service/StockService.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/StockService.java deleted file mode 100644 index e5a664393..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/StockService.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service; - -/** - * The interface Stock service. - */ -public interface StockService { - - /** - * 扣减库存 - * - * @param commodityCode 商品编号 - * @param count 扣减数量 - */ - void deduct(String commodityCode, int count); - - /** - * 批量扣减 - * - * @param commodityCode - * @param count - */ - void batchDeduct(String commodityCode, int count); -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/AccountServiceImpl.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/AccountServiceImpl.java deleted file mode 100644 index 70a47d6fe..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.dubbo.service.AccountService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Please add the follow VM arguments: - *
- *     -Djava.net.preferIPv4Stack=true
- * 
- */ -public class AccountServiceImpl implements AccountService { - - private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); - - private JdbcTemplate jdbcTemplate; - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(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/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/BusinessServiceImpl.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/BusinessServiceImpl.java deleted file mode 100644 index 3f486e787..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/BusinessServiceImpl.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service.impl; - -import java.util.Random; - -import io.seata.core.context.RootContext; -import io.seata.samples.dubbo.service.BusinessService; -import io.seata.samples.dubbo.service.OrderService; -import io.seata.samples.dubbo.service.StockService; -import io.seata.spring.annotation.GlobalTransactional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Please add the follow VM arguments: - *
- *     -Djava.net.preferIPv4Stack=true
- * 
- */ -public class BusinessServiceImpl implements BusinessService { - - private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); - - private StockService stockService; - private OrderService orderService; - private Random random = new Random(); - - @Override - @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") - public void purchase(String userId, String commodityCode, int orderCount) { - LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); - stockService.deduct(commodityCode, orderCount); - // just test batch update - //stockService.batchDeduct(commodityCode, orderCount); - orderService.create(userId, commodityCode, orderCount); - if (random.nextBoolean()) { - throw new RuntimeException("random exception mock!"); - } - - } - - /** - * Sets stock service. - * - * @param stockService the stock service - */ - public void setStockService(StockService stockService) { - this.stockService = stockService; - } - - /** - * Sets order service. - * - * @param orderService the order service - */ - public void setOrderService(OrderService orderService) { - this.orderService = orderService; - } - -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/OrderServiceImpl.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/OrderServiceImpl.java deleted file mode 100644 index 6229d8271..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service.impl; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -import io.seata.core.context.RootContext; -import io.seata.samples.dubbo.Order; -import io.seata.samples.dubbo.service.AccountService; -import io.seata.samples.dubbo.service.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; - -/** - * Please add the follow VM arguments: - *
- *     -Djava.net.preferIPv4Stack=true
- * 
- */ -public class OrderServiceImpl implements OrderService { - - private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); - - private AccountService accountService; - - private 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; - } - - /** - * Sets account service. - * - * @param accountService the account service - */ - public void setAccountService(AccountService accountService) { - this.accountService = accountService; - } - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - private int calculate(String commodityId, int orderCount) { - return 200 * orderCount; - } - -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/StockServiceImpl.java b/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/StockServiceImpl.java deleted file mode 100644 index dbe300dbb..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.dubbo.service.StockService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Please add the follow VM arguments: - *
- *     -Djava.net.preferIPv4Stack=true
- * 
- */ -public class StockServiceImpl implements StockService { - - private static final Logger LOGGER = LoggerFactory.getLogger(StockService.class); - - private JdbcTemplate jdbcTemplate; - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(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/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboAccountServiceStarter.java b/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboAccountServiceStarter.java deleted file mode 100644 index 9289ca6f0..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboAccountServiceStarter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.starter; - -import io.seata.samples.dubbo.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Dubbo account service starter. - */ -public class DubboAccountServiceStarter { - /** - * 2. Account service is ready . A buyer register an account: U100001 on my e-commerce platform - * - * @param args the input arguments - */ - public static void main(String[] args) { - ClassPathXmlApplicationContext accountContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-account-service.xml"}); - accountContext.getBean("service"); - JdbcTemplate accountJdbcTemplate = (JdbcTemplate)accountContext.getBean("jdbcTemplate"); - accountJdbcTemplate.update("delete from account_tbl where user_id = 'U100001'"); - accountJdbcTemplate.update("insert into account_tbl(user_id, money) values ('U100001', 999)"); - - new ApplicationKeeper(accountContext).keep(); - } -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboBusinessTester.java b/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboBusinessTester.java deleted file mode 100644 index 5f55126ab..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboBusinessTester.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.starter; - -import io.seata.samples.dubbo.service.BusinessService; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * The type Dubbo business tester. - */ -public class DubboBusinessTester { - /** - * The entry point of application. - * - * @param args the input arguments - */ - public static void main(String[] args) { - /** - * 4. The whole e-commerce platform is ready , The buyer(U100001) create an order on the sku(C00321) , the - * count is 2 - */ - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-business.xml"}); - final BusinessService business = (BusinessService)context.getBean("business"); - business.purchase("U100001", "C00321", 2); - } -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboOrderServiceStarter.java b/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboOrderServiceStarter.java deleted file mode 100644 index 045054906..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboOrderServiceStarter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.starter; - -import io.seata.samples.dubbo.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * The type Dubbo order service starter. - */ -public class DubboOrderServiceStarter { - /** - * The entry point of application. - * - * @param args the input arguments - */ - public static void main(String[] args) { - /** - * 3. Order service is ready . Waiting for buyers to order - */ - ClassPathXmlApplicationContext orderContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-order-service.xml"}); - orderContext.getBean("service"); - new ApplicationKeeper(orderContext).keep(); - } -} diff --git a/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboStockServiceStarter.java b/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboStockServiceStarter.java deleted file mode 100644 index 94093b710..000000000 --- a/dubbo/src/main/java/io/seata/samples/dubbo/starter/DubboStockServiceStarter.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.dubbo.starter; - -import io.seata.samples.dubbo.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Dubbo stock service starter. - */ -public class DubboStockServiceStarter { - /** - * 1. Stock service is ready . A seller add 100 stock to a sku: C00321 - * - * @param args the input arguments - */ - public static void main(String[] args) { - ClassPathXmlApplicationContext stockContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-stock-service.xml"}); - stockContext.getBean("service"); - JdbcTemplate stockJdbcTemplate = (JdbcTemplate)stockContext.getBean("jdbcTemplate"); - stockJdbcTemplate.update("delete from stock_tbl where commodity_code = 'C00321'"); - stockJdbcTemplate.update("insert into stock_tbl(commodity_code, count) values ('C00321', 100)"); - new ApplicationKeeper(stockContext).keep(); - } -} diff --git a/dubbo/src/main/resources/file.conf b/dubbo/src/main/resources/file.conf deleted file mode 100644 index e38ee8290..000000000 --- a/dubbo/src/main/resources/file.conf +++ /dev/null @@ -1,66 +0,0 @@ -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - # the client batch send request enable - enableClientBatchSendRequest = true - #thread factory for netty - threadFactory { - bossThreadPrefix = "NettyBoss" - workerThreadPrefix = "NettyServerNIOWorker" - serverExecutorThread-prefix = "NettyServerBizHandler" - shareBossWorker = false - clientSelectorThreadPrefix = "NettyClientSelector" - clientSelectorThreadSize = 1 - clientWorkerThreadPrefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - bossThreadSize = 1 - #auto default pin or 8 - workerThreadSize = "default" - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #transaction service group mapping - vgroupMapping.my_test_tx_group = "default" - #only support when registry.type=file, please don't set multiple addresses - default.grouplist = "127.0.0.1:8091" - #degrade, current not support - enableDegrade = false - #disable seata - disableGlobalTransaction = false -} - -client { - rm { - asyncCommitBufferLimit = 10000 - lock { - retryInterval = 10 - retryTimes = 30 - retryPolicyBranchRollbackOnConflict = true - } - reportRetryCount = 5 - tableMetaCheckEnable = false - reportSuccessEnable = false - } - tm { - commitRetryCount = 5 - rollbackRetryCount = 5 - } - undo { - dataValidation = true - logSerialization = "jackson" - logTable = "undo_log" - } - log { - exceptionRate = 100 - } -} \ No newline at end of file diff --git a/dubbo/src/main/resources/jdbc.properties b/dubbo/src/main/resources/jdbc.properties deleted file mode 100644 index d01393190..000000000 --- a/dubbo/src/main/resources/jdbc.properties +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 1999-2018 Alibaba Group Holding Ltd. -# -# Licensed 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. -# -jdbc.account.url=jdbc:mysql://localhost:3306/seata -jdbc.account.username=root -jdbc.account.password=123456 -jdbc.account.driver=com.mysql.jdbc.Driver -# stock db config -jdbc.stock.url=jdbc:mysql://localhost:3306/seata -jdbc.stock.username=root -jdbc.stock.password=123456 -jdbc.stock.driver=com.mysql.jdbc.Driver -# order db config -jdbc.order.url=jdbc:mysql://localhost:3306/seata -jdbc.order.username=root -jdbc.order.password=123456 -jdbc.order.driver=com.mysql.jdbc.Driver \ No newline at end of file diff --git a/dubbo/src/main/resources/log4j.properties b/dubbo/src/main/resources/log4j.properties deleted file mode 100644 index 78697f5fa..000000000 --- a/dubbo/src/main/resources/log4j.properties +++ /dev/null @@ -1,6 +0,0 @@ -log4j.rootLogger=info,stdout -### output console ### -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n diff --git a/dubbo/src/main/resources/registry.conf b/dubbo/src/main/resources/registry.conf deleted file mode 100644 index cd2b7ac33..000000000 --- a/dubbo/src/main/resources/registry.conf +++ /dev/null @@ -1,79 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "file" - - nacos { - application = "seata-server" - serverAddr = "localhost" - namespace = "" - username = "" - password = "" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - password = "" - timeout = "0" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - serverAddr = "127.0.0.1:8500" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig - type = "file" - - nacos { - serverAddr = "localhost" - namespace = "" - group = "SEATA_GROUP" - username = "" - password = "" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - appId = "seata-server" - apolloMeta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/dubbo/src/main/resources/spring/dubbo-account-service.xml b/dubbo/src/main/resources/spring/dubbo-account-service.xml deleted file mode 100644 index a3cbbb348..000000000 --- a/dubbo/src/main/resources/spring/dubbo-account-service.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/dubbo/src/main/resources/spring/dubbo-business.xml b/dubbo/src/main/resources/spring/dubbo-business.xml deleted file mode 100644 index 7b45a3504..000000000 --- a/dubbo/src/main/resources/spring/dubbo-business.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/dubbo/src/main/resources/spring/dubbo-order-service.xml b/dubbo/src/main/resources/spring/dubbo-order-service.xml deleted file mode 100644 index 6082038c2..000000000 --- a/dubbo/src/main/resources/spring/dubbo-order-service.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dubbo/src/main/resources/spring/dubbo-stock-service.xml b/dubbo/src/main/resources/spring/dubbo-stock-service.xml deleted file mode 100644 index 9038d471a..000000000 --- a/dubbo/src/main/resources/spring/dubbo-stock-service.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dubbo/src/main/resources/sql/dubbo_biz.sql b/dubbo/src/main/resources/sql/dubbo_biz.sql deleted file mode 100644 index 3a97410c2..000000000 --- a/dubbo/src/main/resources/sql/dubbo_biz.sql +++ /dev/null @@ -1,31 +0,0 @@ -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; \ No newline at end of file diff --git a/dubbo/src/main/resources/sql/undo_log.sql b/dubbo/src/main/resources/sql/undo_log.sql deleted file mode 100644 index 8ee88ab1e..000000000 --- a/dubbo/src/main/resources/sql/undo_log.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 注意此处0.3.0+ 增加唯一索引 ux_undo_log -CREATE TABLE `undo_log` -( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `branch_id` bigint(20) NOT NULL, - `xid` varchar(100) NOT NULL, - `context` varchar(128) NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int(11) NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/etcd3/api-etcd3-samples/pom.xml b/etcd3/api-etcd3-samples/pom.xml deleted file mode 100644 index 4d5b1d3f6..000000000 --- a/etcd3/api-etcd3-samples/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - etcd3 - io.seata - 1.1.0 - - 4.0.0 - - api-etcd3-samples - - - - io.seata - seata-all - - - com.alibaba - druid - - - mysql - mysql-connector-java - ${mysql-connector.version} - - - com.fasterxml.jackson.core - jackson-databind - - - - - io.etcd - jetcd-core - - - - - \ No newline at end of file diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/Bussiness.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/Bussiness.java deleted file mode 100644 index 229a351bb..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/Bussiness.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api; - -import io.seata.core.exception.TransactionException; -import io.seata.rm.RMClient; -import io.seata.samples.etcd3.api.service.AccountService; -import io.seata.samples.etcd3.api.service.OrderService; -import io.seata.samples.etcd3.api.service.StockService; -import io.seata.samples.etcd3.api.service.impl.AccountServiceImpl; -import io.seata.samples.etcd3.api.service.impl.OrderServiceImpl; -import io.seata.samples.etcd3.api.service.impl.StockServiceImpl; -import io.seata.tm.TMClient; -import io.seata.tm.api.GlobalTransaction; -import io.seata.tm.api.GlobalTransactionContext; - -import java.sql.SQLException; -import java.util.concurrent.TimeUnit; - - - -/** - * The type Bussiness. - * @author xiaochangbai - * @date 2022/1/15 - */ -public class Bussiness { - - /** - * The entry point of application. - * - * @param args the input arguments - * @throws SQLException the sql exception - * @throws TransactionException the transaction exception - */ - public static void main(String[] args) throws SQLException, TransactionException, InterruptedException { - - String userId = "U100001"; - String commodityCode = "C00321"; - int commodityCount = 100; - int money = 999; - AccountService accountService = new AccountServiceImpl(); - StockService stockService = new StockServiceImpl(); - OrderService orderService = new OrderServiceImpl(); - orderService.setAccountService(accountService); - - //reset data - accountService.reset(userId, String.valueOf(money)); - stockService.reset(commodityCode, String.valueOf(commodityCount)); - orderService.reset(null, null); - - //init seata; only once - String applicationId = "seata-server"; - String txServiceGroup = "default_tx_group"; - TMClient.init(applicationId, txServiceGroup); - RMClient.init(applicationId, txServiceGroup); - - //trx - GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate(); - try { - tx.begin(60000, "testBiz"); - System.out.println("begin trx, xid is " + tx.getXid()); - - //biz operate 3 dataSources - //set >=5 will be rollback(200*5>999) else will be commit - int opCount = 5; - stockService.deduct(commodityCode, opCount); - orderService.create(userId, commodityCode, opCount); - - //check data if negative - boolean needCommit = ((StockServiceImpl)stockService).validNegativeCheck("count", commodityCode) - && ((AccountServiceImpl)accountService).validNegativeCheck("money", userId); - - //if data negative rollback else commit - if (needCommit) { - tx.commit(); - } else { - System.out.println("rollback trx, cause: data negative, xid is " + tx.getXid()); - tx.rollback(); - } - } catch (Exception exx) { - System.out.println("rollback trx, cause: " + exx.getMessage() + " , xid is " + tx.getXid()); - tx.rollback(); - throw exx; - } - TimeUnit.SECONDS.sleep(3); - - } -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/AbstractDataCheck.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/AbstractDataCheck.java deleted file mode 100644 index 1a7b9ad7c..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/AbstractDataCheck.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service; - -import java.sql.SQLException; - -/** - * The type Abstract data check. - * @author xiaochangbai - * @date 2022/1/15 - */ -public abstract class AbstractDataCheck { - - /** - * Valid negative check boolean. - * - * @param field the field - * @param id the id - * @return the boolean - */ - public boolean validNegativeCheck(String field, String id) throws SQLException { - return doNegativeCheck(field, id) >= 0; - } - - /** - * Do negative check int. - * - * @param field the field - * @param id the id - * @return the int - * @throws SQLException the sql exception - */ - public abstract int doNegativeCheck(String field, String id) throws SQLException; -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/AccountService.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/AccountService.java deleted file mode 100644 index 3c653fb9d..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/AccountService.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service; - -import java.sql.SQLException; - -/** - * The interface Account service. - * @author xiaochangbai - * @date 2022/1/15 - */ -public interface AccountService extends DataResetService { - /** - * Reduce. - * - * @param userId the user id - * @param money the money - * @throws SQLException the sql exception - */ - void reduce(String userId, int money) throws SQLException; -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/DataResetService.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/DataResetService.java deleted file mode 100644 index 3b9f515ea..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/DataResetService.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service; - -import java.sql.SQLException; - -/** - * The interface Data reset service. - * @author xiaochangbai - * @date 2022/1/15 - */ -public interface DataResetService { - /** - * Reset. - * - * @param key the key - * @param value the value - * @throws SQLException the sql exception - */ - void reset(String key, String value) throws SQLException; -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/OrderService.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/OrderService.java deleted file mode 100644 index 42eedc58a..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/OrderService.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service; - -import java.sql.SQLException; - -/** - * The interface Order service. - * @author xiaochangbai - * @date 2022/1/15 - */ -public interface OrderService extends DataResetService { - /** - * Sets account service. - * - * @param accountService the account service - */ - void setAccountService(AccountService accountService); - - /** - * Create. - * - * @param userId the user id - * @param commodityCode the commodity code - * @param count the count - * @throws SQLException the sql exception - */ - void create(String userId, String commodityCode, Integer count) throws SQLException; -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/StockService.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/StockService.java deleted file mode 100644 index f88f3d2a5..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/StockService.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service; - -import java.sql.SQLException; - -/** - * The interface Stock service. - * @author xiaochangbai - * @date 2022/1/15 - */ -public interface StockService extends DataResetService { - /** - * Deduct. - * - * @param commodityCode the commodity code - * @param count the count - * @throws SQLException the sql exception - */ - void deduct(String commodityCode, int count) throws SQLException; -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/AccountServiceImpl.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/AccountServiceImpl.java deleted file mode 100644 index 4d2e3676c..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service.impl; - -import io.seata.samples.etcd3.api.service.AbstractDataCheck; -import io.seata.samples.etcd3.api.service.AccountService; -import io.seata.samples.etcd3.api.utils.DataSourceUtil; - -import java.sql.SQLException; - - - -/** - * The type Account service. - * @author xiaochangbai - * @date 2022/1/15 - */ -public class AccountServiceImpl extends AbstractDataCheck implements AccountService { - - /** - * The constant DB_KEY. - */ - public static final String DB_KEY = "account"; - - @Override - public void reduce(String userId, int money) throws SQLException { - String sql = "update account_tbl set money = money - " + money + " where user_id = '" + userId + "'"; - DataSourceUtil.executeUpdate(DB_KEY, sql); - } - - @Override - public int doNegativeCheck(String field, String id) throws SQLException { - String checkSql = "select " + field + " from account_tbl where user_id='" + id + "'"; - String result = DataSourceUtil.getSingleResult(DB_KEY, checkSql); - return Integer.parseInt(result); - } - - @Override - public void reset(String key, String value) throws SQLException { - String deleteSql = "delete from account_tbl where user_id = '" + key + "'"; - String insertSql = "insert into account_tbl(user_id, money) values ('" + key + "', " + value + ")"; - DataSourceUtil.executeUpdate(DB_KEY, deleteSql); - DataSourceUtil.executeUpdate(DB_KEY, insertSql); - } -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/OrderServiceImpl.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/OrderServiceImpl.java deleted file mode 100644 index 9e1617b5b..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service.impl; - -import io.seata.samples.etcd3.api.service.AccountService; -import io.seata.samples.etcd3.api.service.OrderService; -import io.seata.samples.etcd3.api.utils.DataSourceUtil; - -import java.sql.SQLException; - - - -/** - * The type Order service. - * @author xiaochangbai - * @date 2022/1/15 - */ -public class OrderServiceImpl implements OrderService { - - /** - * The constant DB_KEY. - */ - public static final String DB_KEY = "order"; - private AccountService accountService; - - @Override - public void setAccountService(AccountService accountService) { - this.accountService = accountService; - } - - @Override - public void create(String userId, String commodityCode, Integer count) throws SQLException { - int money = count * 200; - String sql = "insert into order_tbl (user_id, commodity_code, count, money) values ('" + userId + "','" - + commodityCode + "'," + count + "," + money + ")"; - DataSourceUtil.executeUpdate(DB_KEY, sql); - accountService.reduce(userId, money); - - } - - @Override - public void reset(String key, String value) throws SQLException { - String deleteSql = "delete from order_tbl"; - DataSourceUtil.executeUpdate(DB_KEY, deleteSql); - } -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/StockServiceImpl.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/StockServiceImpl.java deleted file mode 100644 index 36431e70a..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.service.impl; - -import io.seata.samples.etcd3.api.service.AbstractDataCheck; -import io.seata.samples.etcd3.api.service.StockService; -import io.seata.samples.etcd3.api.utils.DataSourceUtil; - -import java.sql.SQLException; - - - -/** - * The type Stock service. - * @author xiaochangbai - * @date 2022/1/15 - */ -public class StockServiceImpl extends AbstractDataCheck implements StockService { - /** - * The constant DB_KEY. - */ - public static final String DB_KEY = "stock"; - - @Override - public void deduct(String commodityCode, int count) throws SQLException { - String sql = "update stock_tbl set count = count - " + count + " where commodity_code = '" + commodityCode - + "'"; - DataSourceUtil.executeUpdate(DB_KEY, sql); - } - - @Override - public void reset(String key, String value) throws SQLException { - String deleteSql = "delete from stock_tbl where commodity_code = '" + key + "'"; - String insertSql = "insert into stock_tbl(commodity_code, count) values ('" + key + "', " + value + ")"; - DataSourceUtil.executeUpdate(DB_KEY, deleteSql); - DataSourceUtil.executeUpdate(DB_KEY, insertSql); - } - - @Override - public int doNegativeCheck(String field, String id) throws SQLException { - String checkSql = "select " + field + " from stock_tbl where commodity_code='" + id + "'"; - String result = DataSourceUtil.getSingleResult(DB_KEY, checkSql); - return Integer.parseInt(result); - } -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/utils/DataSourceUtil.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/utils/DataSourceUtil.java deleted file mode 100644 index 4eda2b07a..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/utils/DataSourceUtil.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.utils; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.sql.DataSource; - -import com.alibaba.druid.pool.DruidDataSource; - -import io.seata.rm.datasource.DataSourceProxy; - -/** - * The type Data source util. - * @author xiaochangbai - * @date 2022/1/15 - */ -public class DataSourceUtil { - - /** - * The constant JDBC_PRO_PATH. - */ - public static final String JDBC_PRO_PATH = "jdbc.properties"; - /** - * The constant DATA_SOURCE_MAP. - */ - public static final ConcurrentMap DATA_SOURCE_MAP = new ConcurrentHashMap<>(); - - /** - * Gets data source. - * - * @param name the name - * @return the data source - */ - public static DataSource getDataSource(String name) { - String driverKey = "jdbc." + name + ".driver"; - String urlKey = "jdbc." + name + ".url"; - String userNameKey = "jdbc." + name + ".username"; - String pwdKey = "jdbc." + name + ".password"; - DataSource dataSource = new DruidDataSource(); - ((DruidDataSource)dataSource).setDriverClassName(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, driverKey)); - ((DruidDataSource)dataSource).setUrl(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, urlKey)); - ((DruidDataSource)dataSource).setUsername(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, userNameKey)); - ((DruidDataSource)dataSource).setPassword(PropertiesUtil.getPropertieValue(JDBC_PRO_PATH, pwdKey)); - return new DataSourceProxy(dataSource); - } - - /** - * Gets connection. - * - * @param name the name - * @return the connection - * @throws SQLException the sql exception - */ - public static Connection getConnection(String name) throws SQLException { - DATA_SOURCE_MAP.putIfAbsent(name, getDataSource(name)); - return DATA_SOURCE_MAP.get(name).getConnection(); - } - - /** - * Execute update int. - * - * @param name the name - * @param sql the sql - * @return the int - * @throws SQLException the sql exception - */ - public static int executeUpdate(String name, String sql) throws SQLException { - Connection connection = null; - Statement statement = null; - int result = 0; - try { - connection = getConnection(name); - statement = connection.createStatement(); - result = statement.executeUpdate(sql); - - } catch (SQLException exx) { - //todo - throw exx; - } finally { - try { - if (statement != null) { - statement.close(); - } - if (connection != null) { - connection.close(); - } - } catch (SQLException exx) { - } - } - return result; - } - - /** - * Gets single result. - * - * @param name the name - * @param sql the sql - * @return the single result - * @throws SQLException the sql exception - */ - public static String getSingleResult(String name, String sql) throws SQLException { - Connection connection = null; - Statement statement = null; - String result = null; - try { - connection = getConnection(name); - statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery(sql); - resultSet.next(); - result = resultSet.getString(1); - } catch (SQLException exx) { - //todo - throw exx; - } finally { - try { - if (statement != null) { - statement.close(); - } - if (connection != null) { - connection.close(); - } - } catch (SQLException exx) { - } - } - return result; - } -} diff --git a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/utils/PropertiesUtil.java b/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/utils/PropertiesUtil.java deleted file mode 100644 index 7383830d7..000000000 --- a/etcd3/api-etcd3-samples/src/main/java/io/seata/samples/etcd3/api/utils/PropertiesUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.etcd3.api.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -/** - * The type Properties util. - * @author xiaochangbai - * @date 2022/1/15 - */ -public class PropertiesUtil { - - /** - * Gets propertie value. - * - * @param path the path - * @param key the key - * @return the propertie value - */ - public static String getPropertieValue(String path, String key) { - return getPropertieValue(path, key, null); - - } - - /** - * Gets propertie value. - * - * @param path the path - * @param key the key - * @param defaultValue the default value - * @return the propertie value - */ - public static String getPropertieValue(String path, String key, String defaultValue) { - Properties properties = new Properties(); - InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream(path); - try { - properties.load(in); - } catch (IOException ignore) { - } - String value = properties.getProperty(key); - return value == null ? defaultValue : value; - } -} - diff --git a/etcd3/api-etcd3-samples/src/main/resources/all.sql b/etcd3/api-etcd3-samples/src/main/resources/all.sql deleted file mode 100644 index b6ae6fb9f..000000000 --- a/etcd3/api-etcd3-samples/src/main/resources/all.sql +++ /dev/null @@ -1,41 +0,0 @@ -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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - -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` (`commodity_code`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - -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 AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - -CREATE TABLE `undo_log` -( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `branch_id` bigint(20) NOT NULL, - `xid` varchar(100) NOT NULL, - `context` varchar(128) NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int(11) NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - `ext` varchar(100) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/etcd3/api-etcd3-samples/src/main/resources/file.conf b/etcd3/api-etcd3-samples/src/main/resources/file.conf deleted file mode 100644 index c960c460a..000000000 --- a/etcd3/api-etcd3-samples/src/main/resources/file.conf +++ /dev/null @@ -1,10 +0,0 @@ -service { - #vgroup->rgroup - vgroupMapping.my_test_tx_group = "default" - #only support single node - default.grouplist = "127.0.0.1:8091" - #degrade current not support - enableDegrade = false - #disable - disable = false -} diff --git a/etcd3/api-etcd3-samples/src/main/resources/jdbc.properties b/etcd3/api-etcd3-samples/src/main/resources/jdbc.properties deleted file mode 100644 index 4ed60813a..000000000 --- a/etcd3/api-etcd3-samples/src/main/resources/jdbc.properties +++ /dev/null @@ -1,14 +0,0 @@ -jdbc.account.url=jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC -jdbc.account.username=root -jdbc.account.password=root -jdbc.account.driver=com.mysql.jdbc.Driver -# stock db config -jdbc.stock.url=jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC -jdbc.stock.username=root -jdbc.stock.password=root -jdbc.stock.driver=com.mysql.jdbc.Driver -# order db config -jdbc.order.url=jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC -jdbc.order.username=root -jdbc.order.password=root -jdbc.order.driver=com.mysql.jdbc.Driver \ No newline at end of file diff --git a/etcd3/api-etcd3-samples/src/main/resources/registry.conf b/etcd3/api-etcd3-samples/src/main/resources/registry.conf deleted file mode 100644 index 25d405926..000000000 --- a/etcd3/api-etcd3-samples/src/main/resources/registry.conf +++ /dev/null @@ -1,82 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "etcd3" - - nacos { - serverAddr = "localhost" - namespace = "" - cluster = "default" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - password = "" - cluster = "default" - timeout = "0" - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig - type = "etcd3" - - nacos { - serverAddr = "localhost" - namespace = "" - group = "SEATA_GROUP" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - app.id = "seata-server" - apollo.meta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/etcd3/pom.xml b/etcd3/pom.xml deleted file mode 100644 index f3d67e0ec..000000000 --- a/etcd3/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - seata-samples - io.seata - 1.1.0 - - 4.0.0 - pom - - api-etcd3-samples - - etcd3 - - - 0.3.0 - - - - - - io.etcd - jetcd-core - ${jetcd.client.version} - - - - - \ No newline at end of file diff --git a/ha/Readme.md b/ha/Readme.md deleted file mode 100644 index f6adfad01..000000000 --- a/ha/Readme.md +++ /dev/null @@ -1,421 +0,0 @@ -# 基于 Seata 解决微服务架构下数据一致性的实践 - -[Seata](https://github.com/seata/seata) 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务。 - -本文将通过一个简单的微服务架构的例子,说明业务如何step by step的使用 Seata、Dubbo 来保证业务数据的一致性; - -本案例中,seata-server 服务端 使用数据库作为事务日志存储,用户可以部署多个seata-server以提供集群服务,从而支持服务端高可用。 - -## 业务案例 - -用户采购商品业务,整个业务包含3个微服务: - -- 库存服务: 扣减给定商品的库存数量。 -- 订单服务: 根据采购请求生成订单。 -- 账户服务: 用户账户金额扣减。 - -### 业务结构图 - - - -#### StockService - -```java -public interface StockService { - /** - * deduct stock count - */ - void deduct(String commodityCode, int count); -} -``` - -#### OrderService - -```java -public interface OrderService { - /** - * create order - */ - Order create(String userId, String commodityCode, int orderCount); -} -``` - -#### AccountService - -```java -public interface AccountService { - /** - * debit balance of user's account - */ - void debit(String userId, int money); -} -``` - -**说明:** 以上三个微服务独立部署。 - -### Seata、Dubbo 集成 - -#### Step 1 初始化 MySQL 数据库(需要InnoDB 存储引擎) - -在 [resources/jdbc.properties](https://github.com/seata/seata-samples/blob/master/ha/src/main/resources/jdbc. properties) -修改StockService、OrderService、AccountService 对应的连接信息。 - -```properties -jdbc.account.url=jdbc:mysql://xxxx/xxxx -jdbc.account.username=xxxx -jdbc.account.password=xxxx -jdbc.account.driver=com.mysql.jdbc.Driver -# stock db config -jdbc.stock.url=jdbc:mysql://xxxx/xxxx -jdbc.stock.username=xxxx -jdbc.stock.password=xxxx -jdbc.stock.driver=com.mysql.jdbc.Driver -# order db config -jdbc.order.url=jdbc:mysql://xxxx/xxxx -jdbc.order.username=xxxx -jdbc.order.password=xxxx -jdbc.order.driver=com.mysql.jdbc.Driver -``` - -#### Step 2 创建 undo_log(用于 Seata AT 模式)表和相关业务表 - -相关建表脚本可在 [resources/sql/](https://github.com/seata/seata-samples/tree/master/ha/src/main/resources/sql) -下获取,在相应数据库中执行 [dubbo_biz.sql](https://github.com/seata/seata-samples/blob/master/ha/src/main/resources/sql/dubbo_biz.sql) -中的业务建表脚本,在每个数据库执行 [undo_log.sql](https://github.com/seata/seata-samples/blob/master/ha/src/main/resources/sql/undo_log.sql) -建表脚本。 - -```sql --- 注意此处0.3.0+ 增加唯一索引 ux_undo_log -CREATE TABLE `undo_log` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `branch_id` bigint(20) NOT NULL, - `xid` varchar(100) NOT NULL, - `context` varchar(128) NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int(11) NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - `ext` varchar(100) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -``` - -```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; -``` - -**说明:** 需要保证每个物理库都包含 undo_log 表,此处可使用一个物理库来表示上述三个微服务对应的独立逻辑库。 - -#### Step 3 引入 Seata、Dubbo 相关 POM 依赖 - -```xml - - x.x.x - 2.6.5 - - - - io.seata - seata-all - ${seata.version} - - - - com.alibaba - dubbo - ${dubbo.alibaba.version} - - -``` - -#### Step 4 微服务 Provider Spring配置 - -分别在三个微服务Spring配置文件([dubbo-account-service.xml](https://github.com/seata/seata-samples/blob/master/ha/src/main/resources/spring/dubbo-account-service.xml)、 -[dubbo-order-service](https://github.com/seata/seata-samples/blob/master/ha/src/main/resources/spring/dubbo-order-service.xml) -和 -[dubbo-stock-service.xml](https://github.com/seata/seata-samples/blob/master/ha/src/main/resources/spring/dubbo-stock-service.xml) -)进行如下配置: - -- 配置 Seata 代理数据源 - -```xml - - - - - - - -``` - -此处需要使用 io.seata.rm.datasource.DataSourceProxy 包装 Druid 数据源作为直接业务数据源,DataSourceProxy 用于业务 sql 的拦截解析并与 TC 交互协调事务操作状态。 - -- 配置 Dubbo 注册中心 - -```xml - -``` - -- 配置 Seata GlobalTransactionScanner - -```xml - - - - -``` - -此处构造方法的第一个参数为业务自定义 applicationId,若在单机部署多微服务需要保证 applicationId 唯一。 -构造方法的第二个参数为 Seata 事务服务逻辑分组,此分组通过配置中心配置项 service.vgroup_mapping.my_test_tx_group 映射到相应的 Seata-Server -集群名称,然后再根据集群名称.grouplist 获取到可用服务列表。 - -#### Step 5 事务发起方配置 - -在 [dubbo-business.xml](https://github.com/seata/seata-samples/blob/master/ha/src/main/resources/spring/dubbo-business.xml) -配置以下配置: - -- 配置 Dubbo 注册中心 - -同 Step 4 - -- 配置 Seata GlobalTransactionScanner - -同 Step 4 - -- 在事务发起方 service 方法上添加 @GlobalTransactional 注解 - -```java -@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") -``` - -timeoutMills 为事务的总体超时时间默认60s,name 为事务方法签名的别名,默认为空。注解内参数均可省略。 - -#### Step 6 启动 Zookeeper - -本地以单机模式启动 zookeeper-server; - -#### Step 7 启动 Seata-Server - -配置 Seata-Server的数据库,启动Seata-Server ; - -- 下载 Seata-Server 最新 [release](https://github.com/seata/seata/releases) 包并解压 - -- 准备 Seata-Server的数据库: - -安装mysql,创建数据库 seata_server : "create database seata_server;" - -创建 事务记录表,建表语句 [db_store.sql](https://github.com/seata/seata/blob/develop/server/src/main/resources/db_store.sql) : - -```sql --- the table to store GlobalSession data -drop table `global_table`; -create table `global_table` ( - `xid` varchar(128) not null, - `transaction_id` bigint, - `status` tinyint not null, - `application_id` varchar(64), - `transaction_service_group` varchar(64), - `transaction_name` varchar(128), - `timeout` int, - `begin_time` bigint, - `application_data` varchar(2000), - `gmt_create` datetime, - `gmt_modified` datetime, - primary key (`xid`), - key `idx_gmt_modified_status` (`gmt_modified`, `status`), - key `idx_transaction_id` (`transaction_id`) -); - --- the table to store BranchSession data -drop table `branch_table`; -create table `branch_table` ( - `branch_id` bigint not null, - `xid` varchar(128) not null, - `transaction_id` bigint , - `resource_group_id` varchar(128), - `resource_id` varchar(256) , - `lock_key` varchar(256) , - `branch_type` varchar(8) , - `status` tinyint, - `client_id` varchar(64), - `application_data` varchar(2000), - `gmt_create` datetime, - `gmt_modified` datetime, - primary key (`branch_id`), - key `idx_xid` (`xid`) -); - --- the table to store lock data -drop table `lock_table`; -create table `lock_table` ( - `row_key` varchar(128) not null, - `xid` varchar(128), - `transaction_id` long , - `branch_id` long, - `resource_id` varchar(256) , - `table_name` varchar(64) , - `pk` varchar(128) , - `gmt_create` datetime , - `gmt_modified` datetime, - primary key(`row_key`) -); - -``` - -- 初始化 Seata 配置 - -进入到 Seata-Server 解压目录 conf -文件夹下 [file.conf](https://github.com/seata/seata/blob/develop/server/src/main/resources/file.conf) ,修改事务日志存储相关属性: - -修改项如下: - -``` -store.mode = "db" -store.db.datasource=dbcp -store.db.db-type=mysql -store.db.driver-class-name=com.mysql.jdbc.Driver -store.db.url=jdbc:mysql://127.0.0.1:3306/seata_server?useUnicode=true -store.db.user=mysql -store.db.password=mysql -lock.mode=db - -``` - -修改后 file.conf 中 store和lock 节点内容如下: - -```properties -## transaction log store -store { - ## store mode: file、db - mode = "db" - - ## file store - file { - dir = "sessionStore" - - # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions - max-branch-session-size = 16384 - # globe session size , if exceeded throws exceptions - max-global-session-size = 512 - # file buffer size , if exceeded allocate new buffer - file-write-buffer-cache-size = 16384 - # when recover batch read size - session.reload.read_size = 100 - # async, sync - flush-disk-mode = async - } - - ## database store - db { - ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. - datasource = "dbcp" - ## mysql/oracle/h2/oceanbase etc. - db-type = "mysql" - driver-class-name = com.mysql.jdbc.Driver - url = "jdbc:mysql://127.0.0.1:3306/seata_server" - user = "mysql" - password = "mysql" - min-conn = 1 - max-conn = 3 - global.table = "global_table" - branch.table = "branch_table" - query-limit = 100 - } -} -lock { - ## the data row lock store mode: local_db、memory or db - mode = "db" - - memory{ - ## store lock in memory of server - } - - db{ - ## use db of server to store lock, the db is ${store.db.url} - lock-table= "lock_table" - } - -} - - -``` - -- 运行 Seata-server - -**Linux/Unix/Mac** - -```bash -sh seata-server.sh $LISTEN_PORT $STORE_MODE $IP(此参数可选) -``` - -**Windows** - -```bash -cmd seata-server.bat $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA $IP(此参数可选) - -``` - -**$LISTEN_PORT**: Seata-Server 服务端口 -**$STORE_MODE**: 事务操作记录存储模式:file、db -**$IP(可选参数)**: 用于多 IP 环境下指定 Seata-Server 注册服务的IP - -**eg**: -sh seata-server.sh 8091 db - -#### Step 8 启动微服务并测试 - -- 修改业务客户端发现注册方式为 zookeeper - 同Step 7 中[修改 Seata-server 服务注册方式为 zookeeper] 步骤 -- - -启动 [DubboAccountServiceStarter](https://github.com/seata/seata-samples/blob/master/ha/src/main/java/io/seata/samples/ha/starter/DubboAccountServiceStarter.java) -- -启动 [DubboOrderServiceStarter](https://github.com/seata/seata-samples/blob/master/ha/src/main/java/io/seata/samples/ha/starter/DubboOrderServiceStarter.java) -- -启动 [DubboStockServiceStarter](https://github.com/seata/seata-samples/blob/master/ha/src/main/java/io/seata/samples/ha/starter/DubboStockServiceStarter.java) - -- - -启动 [DubboBusinessTester](https://github.com/seata/seata-samples/blob/master/ha/src/main/java/io/seata/samples/ha/starter/DubboBusinessTester.java) -进行测试 - -**注意:** 在标注 @GlobalTransactional 注解方法内部显示的抛出异常才会进行事务的回滚。整个 Dubbo 服务调用链路只需要在事务最开始发起方的 service 方法标注注解即可。 - -## 相关链接: - -本文 sample 地址: https://github.com/seata/seata-samples/tree/master/ha -Seata: https://github.com/seata/seata -Dubbo: https://github.com/apache/incubator-dubbo - - - - - diff --git a/ha/pom.xml b/ha/pom.xml deleted file mode 100644 index a8fdf68ec..000000000 --- a/ha/pom.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - io.seata - seata-samples - 1.1.0 - - 4.0.0 - seata-samples-HA - seata-samples-HA ${project.version} - - - 2.7.14 - 0.0.2 - - - - - - io.seata - seata-all - ${seata.version} - - - - org.apache.dubbo - dubbo - ${dubbo.version} - - - com.alibaba.nacos - nacos-client - 1.1.4 - - - org.apache.dubbo - dubbo-registry-nacos - ${dubbo.version} - - - com.alibaba.spring - spring-context-support - - - com.101tec - zkclient - - - slf4j-log4j12 - org.slf4j - - - log4j - log4j - - - - - junit - junit - test - - - mysql - mysql-connector-java - - - org.springframework - spring-jdbc - - - ch.qos.logback - logback-classic - - - org.apache.curator - curator-recipes - - - - - - - mysql - mysql-connector-java - 8.0.28 - - - - com.alibaba.spring - spring-context-support - 1.0.11 - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - - \ No newline at end of file diff --git a/ha/src/main/java/io/seata/samples/nacos/ApplicationKeeper.java b/ha/src/main/java/io/seata/samples/nacos/ApplicationKeeper.java deleted file mode 100644 index a45e71416..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/ApplicationKeeper.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos; - -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.support.AbstractApplicationContext; - -/** - * The type Application keeper. - */ -public class ApplicationKeeper { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationKeeper.class); - - private final ReentrantLock LOCK = new ReentrantLock(); - private final Condition STOP = LOCK.newCondition(); - - /** - * Instantiates a new Application keeper. - * - * @param applicationContext the application context - */ - public ApplicationKeeper(AbstractApplicationContext applicationContext) { - addShutdownHook(applicationContext); - } - - private void addShutdownHook(final AbstractApplicationContext applicationContext) { - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { - @Override - public void run() { - try { - applicationContext.close(); - LOGGER.info("ApplicationContext " + applicationContext + " is closed."); - } catch (Exception e) { - LOGGER.error("Failed to close ApplicationContext", e); - } - - try { - LOCK.lock(); - STOP.signal(); - } finally { - LOCK.unlock(); - } - } - })); - } - - /** - * Keep. - */ - public void keep() { - synchronized (LOCK) { - try { - LOGGER.info("Application is keep running ... "); - LOCK.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } -} diff --git a/ha/src/main/java/io/seata/samples/nacos/Order.java b/ha/src/main/java/io/seata/samples/nacos/Order.java deleted file mode 100644 index 348692134..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/Order.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos; - -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/ha/src/main/java/io/seata/samples/nacos/service/AccountService.java b/ha/src/main/java/io/seata/samples/nacos/service/AccountService.java deleted file mode 100644 index a2d0217c5..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/AccountService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -/** - * The interface Account service. - */ -public interface AccountService { - - /** - * 余额扣款 - * - * @param userId 用户ID - * @param money 扣款金额 - */ - void debit(String userId, int money); -} diff --git a/ha/src/main/java/io/seata/samples/nacos/service/BusinessService.java b/ha/src/main/java/io/seata/samples/nacos/service/BusinessService.java deleted file mode 100644 index 248405eaf..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/BusinessService.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -/** - * The interface Business service. - */ -public interface BusinessService { - - /** - * 用户订购商品 - * - * @param userId 用户ID - * @param commodityCode 商品编号 - * @param orderCount 订购数量 - */ - void purchase(String userId, String commodityCode, int orderCount); -} diff --git a/ha/src/main/java/io/seata/samples/nacos/service/OrderService.java b/ha/src/main/java/io/seata/samples/nacos/service/OrderService.java deleted file mode 100644 index a5491859a..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/OrderService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -import io.seata.samples.nacos.Order; - -/** - * The interface Order service. - */ -public interface OrderService { - /** - * 创建订单 - * - * @param userId 用户ID - * @param commodityCode 商品编号 - * @param orderCount 订购数量 - * @return 生成的订单 order - */ - Order create(String userId, String commodityCode, int orderCount); -} diff --git a/ha/src/main/java/io/seata/samples/nacos/service/StockService.java b/ha/src/main/java/io/seata/samples/nacos/service/StockService.java deleted file mode 100644 index c1d98e889..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/StockService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -/** - * The interface Stock service. - */ -public interface StockService { - - /** - * 扣减库存 - * - * @param commodityCode 商品编号 - * @param count 扣减数量 - */ - void deduct(String commodityCode, int count); -} diff --git a/ha/src/main/java/io/seata/samples/nacos/service/impl/AccountServiceImpl.java b/ha/src/main/java/io/seata/samples/nacos/service/impl/AccountServiceImpl.java deleted file mode 100644 index 2c7ac1555..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.service.AccountService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Account service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class AccountServiceImpl implements AccountService { - - private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); - - private JdbcTemplate jdbcTemplate; - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(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/ha/src/main/java/io/seata/samples/nacos/service/impl/BusinessServiceImpl.java b/ha/src/main/java/io/seata/samples/nacos/service/impl/BusinessServiceImpl.java deleted file mode 100644 index f351d72f5..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/impl/BusinessServiceImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.service.BusinessService; -import io.seata.samples.nacos.service.OrderService; -import io.seata.samples.nacos.service.StockService; -import io.seata.spring.annotation.GlobalTransactional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Business service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class BusinessServiceImpl implements BusinessService { - - private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); - - private StockService stockService; - private OrderService orderService; - - @Override - @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") - public void purchase(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("xxx"); - - } - - /** - * Sets stock service. - * - * @param stockService the stock service - */ - public void setStockService(StockService stockService) { - this.stockService = stockService; - } - - /** - * Sets order service. - * - * @param orderService the order service - */ - public void setOrderService(OrderService orderService) { - this.orderService = orderService; - } - -} diff --git a/ha/src/main/java/io/seata/samples/nacos/service/impl/OrderServiceImpl.java b/ha/src/main/java/io/seata/samples/nacos/service/impl/OrderServiceImpl.java deleted file mode 100644 index 95722c5af..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.Order; -import io.seata.samples.nacos.service.AccountService; -import io.seata.samples.nacos.service.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; - -/** - * The type Order service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class OrderServiceImpl implements OrderService { - - private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); - - private AccountService accountService; - - private 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; - } - - /** - * Sets account service. - * - * @param accountService the account service - */ - public void setAccountService(AccountService accountService) { - this.accountService = accountService; - } - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - private int calculate(String commodityId, int orderCount) { - return 200 * orderCount; - } - -} diff --git a/ha/src/main/java/io/seata/samples/nacos/service/impl/StockServiceImpl.java b/ha/src/main/java/io/seata/samples/nacos/service/impl/StockServiceImpl.java deleted file mode 100644 index 19145846a..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.service.StockService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Stock service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class StockServiceImpl implements StockService { - - private static final Logger LOGGER = LoggerFactory.getLogger(StockService.class); - - private JdbcTemplate jdbcTemplate; - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(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 ... "); - - } - -} diff --git a/ha/src/main/java/io/seata/samples/nacos/starter/DubboAccountServiceStarter.java b/ha/src/main/java/io/seata/samples/nacos/starter/DubboAccountServiceStarter.java deleted file mode 100644 index 887b497c6..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/starter/DubboAccountServiceStarter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Dubbo account service starter. - */ -public class DubboAccountServiceStarter { - /** - * 2. Account service is ready . A buyer register an account: U100001 on my e-commerce platform - * - * @param args the input arguments - */ - public static void main(String[] args) { - ClassPathXmlApplicationContext accountContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-account-service.xml"}); - accountContext.getBean("service"); - JdbcTemplate accountJdbcTemplate = (JdbcTemplate)accountContext.getBean("jdbcTemplate"); - accountJdbcTemplate.update("delete from account_tbl where user_id = 'U100001'"); - accountJdbcTemplate.update("insert into account_tbl(user_id, money) values ('U100001', 999)"); - - new ApplicationKeeper(accountContext).keep(); - } -} diff --git a/ha/src/main/java/io/seata/samples/nacos/starter/DubboBusinessTester.java b/ha/src/main/java/io/seata/samples/nacos/starter/DubboBusinessTester.java deleted file mode 100644 index c61eed6db..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/starter/DubboBusinessTester.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.service.BusinessService; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * The type Dubbo business tester. - */ -public class DubboBusinessTester { - /** - * The entry point of application. - * - * @param args the input arguments - */ - public static void main(String[] args) { - /** - * 4. The whole e-commerce platform is ready , The buyer(U100001) create an order on the sku(C00321) , the - * count is 2 - */ - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-business.xml"}); - // - - final BusinessService business = (BusinessService)context.getBean("business"); - business.purchase("U100001", "C00321", 2); - } -} diff --git a/ha/src/main/java/io/seata/samples/nacos/starter/DubboOrderServiceStarter.java b/ha/src/main/java/io/seata/samples/nacos/starter/DubboOrderServiceStarter.java deleted file mode 100644 index c3f86163f..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/starter/DubboOrderServiceStarter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * The type Dubbo order service starter. - */ -public class DubboOrderServiceStarter { - /** - * The entry point of application. - * - * @param args the input arguments - */ - public static void main(String[] args) { - /** - * 3. Order service is ready . Waiting for buyers to order - */ - ClassPathXmlApplicationContext orderContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-order-service.xml"}); - orderContext.getBean("service"); - new ApplicationKeeper(orderContext).keep(); - } -} diff --git a/ha/src/main/java/io/seata/samples/nacos/starter/DubboStockServiceStarter.java b/ha/src/main/java/io/seata/samples/nacos/starter/DubboStockServiceStarter.java deleted file mode 100644 index 3f39d59ff..000000000 --- a/ha/src/main/java/io/seata/samples/nacos/starter/DubboStockServiceStarter.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Dubbo stock service starter. - */ -public class DubboStockServiceStarter { - /** - * 1. Stock service is ready . A seller add 100 stock to a sku: C00321 - * - * @param args the input arguments - */ - public static void main(String[] args) { - ClassPathXmlApplicationContext stockContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-stock-service.xml"}); - stockContext.getBean("service"); - JdbcTemplate stockJdbcTemplate = (JdbcTemplate)stockContext.getBean("jdbcTemplate"); - stockJdbcTemplate.update("delete from stock_tbl where commodity_code = 'C00321'"); - stockJdbcTemplate.update("insert into stock_tbl(commodity_code, count) values ('C00321', 100)"); - new ApplicationKeeper(stockContext).keep(); - } -} diff --git a/ha/src/main/resources/file.conf b/ha/src/main/resources/file.conf deleted file mode 100644 index 02bbc5e4d..000000000 --- a/ha/src/main/resources/file.conf +++ /dev/null @@ -1,67 +0,0 @@ -@@ -1,66 +0,0 @@ -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - # the client batch send request enable - enableClientBatchSendRequest = true - #thread factory for netty - threadFactory { - bossThreadPrefix = "NettyBoss" - workerThreadPrefix = "NettyServerNIOWorker" - serverExecutorThread-prefix = "NettyServerBizHandler" - shareBossWorker = false - clientSelectorThreadPrefix = "NettyClientSelector" - clientSelectorThreadSize = 1 - clientWorkerThreadPrefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - bossThreadSize = 1 - #auto default pin or 8 - workerThreadSize = "default" - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #transaction service group mapping - vgroupMapping.my_test_tx_group = "default" - #only support when registry.type=file, please don't set multiple addresses - default.grouplist = "127.0.0.1:8091" - #degrade, current not support - enableDegrade = false - #disable seata - disableGlobalTransaction = false -} - -client { - rm { - asyncCommitBufferLimit = 10000 - lock { - retryInterval = 10 - retryTimes = 30 - retryPolicyBranchRollbackOnConflict = true - } - reportRetryCount = 5 - tableMetaCheckEnable = false - reportSuccessEnable = false - } - tm { - commitRetryCount = 5 - rollbackRetryCount = 5 - } - undo { - dataValidation = true - logSerialization = "jackson" - logTable = "undo_log" - } - log { - exceptionRate = 100 - } -} \ No newline at end of file diff --git a/ha/src/main/resources/jdbc.properties b/ha/src/main/resources/jdbc.properties deleted file mode 100644 index c18554dfa..000000000 --- a/ha/src/main/resources/jdbc.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 1999-2018 Alibaba Group Holding Ltd. -# -# Licensed 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. -# -# account db config -jdbc.account.url=jdbc:mysql://127.0.0.1:3306/seata -jdbc.account.username=root -jdbc.account.password=123456 -jdbc.account.driver=com.mysql.cj.jdbc.Driver -# stock db config -jdbc.stock.url=jdbc:mysql://127.0.0.1:3306/seata -jdbc.stock.username=root -jdbc.stock.password=123456 -jdbc.stock.driver=com.mysql.cj.jdbc.Driver -# order db config -jdbc.order.url=jdbc:mysql://127.0.0.1:3306/seata -jdbc.order.username=root -jdbc.order.password=123456 -jdbc.order.driver=com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/ha/src/main/resources/logback.xml b/ha/src/main/resources/logback.xml deleted file mode 100644 index baf4f9702..000000000 --- a/ha/src/main/resources/logback.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - %-4relative [%thread] %-5level %logger{35} - %msg %n - - - - - - - diff --git a/ha/src/main/resources/registry.conf b/ha/src/main/resources/registry.conf deleted file mode 100644 index ad2c5f26f..000000000 --- a/ha/src/main/resources/registry.conf +++ /dev/null @@ -1,96 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - application = "seata-server" - serverAddr = "127.0.0.1:8848" - group = "SEATA_GROUP" - namespace = "" - cluster = "default" - username = "nacos" - password = "nacos" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = 0 - password = "" - cluster = "default" - timeout = 0 - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - aclToken = "" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3 - type = "nacos" - - nacos { - serverAddr = "127.0.0.1:8848" - namespace = "" - group = "SEATA_GROUP" - username = "nacos" - password = "nacos" - dataId = "nacos-server.properties" - } - consul { - serverAddr = "127.0.0.1:8500" - aclToken = "" - } - apollo { - appId = "seata-server" - ## apolloConfigService will cover apolloMeta - apolloMeta = "http://192.168.1.204:8801" - apolloConfigService = "http://192.168.1.204:8080" - namespace = "application" - apolloAccesskeySecret = "" - cluster = "seata" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - nodePath = "/seata/seata.properties" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/ha/src/main/resources/spring/dubbo-account-service.xml b/ha/src/main/resources/spring/dubbo-account-service.xml deleted file mode 100644 index d34df92ad..000000000 --- a/ha/src/main/resources/spring/dubbo-account-service.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ha/src/main/resources/spring/dubbo-business.xml b/ha/src/main/resources/spring/dubbo-business.xml deleted file mode 100644 index e5e8a4883..000000000 --- a/ha/src/main/resources/spring/dubbo-business.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ha/src/main/resources/spring/dubbo-order-service.xml b/ha/src/main/resources/spring/dubbo-order-service.xml deleted file mode 100644 index 1b27cbccf..000000000 --- a/ha/src/main/resources/spring/dubbo-order-service.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ha/src/main/resources/spring/dubbo-stock-service.xml b/ha/src/main/resources/spring/dubbo-stock-service.xml deleted file mode 100644 index d8cebaa07..000000000 --- a/ha/src/main/resources/spring/dubbo-stock-service.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ha/src/main/resources/sql/dubbo_biz.sql b/ha/src/main/resources/sql/dubbo_biz.sql deleted file mode 100644 index 3a97410c2..000000000 --- a/ha/src/main/resources/sql/dubbo_biz.sql +++ /dev/null @@ -1,31 +0,0 @@ -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; \ No newline at end of file diff --git a/ha/src/main/resources/sql/undo_log.sql b/ha/src/main/resources/sql/undo_log.sql deleted file mode 100644 index 8ee88ab1e..000000000 --- a/ha/src/main/resources/sql/undo_log.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 注意此处0.3.0+ 增加唯一索引 ux_undo_log -CREATE TABLE `undo_log` -( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `branch_id` bigint(20) NOT NULL, - `xid` varchar(100) NOT NULL, - `context` varchar(128) NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int(11) NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/.gitignore b/mp-shadingsphere-druid-seata-tcc/.gitignore deleted file mode 100644 index 6b534701d..000000000 --- a/mp-shadingsphere-druid-seata-tcc/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.idea -*.iml -/target \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/README.md b/mp-shadingsphere-druid-seata-tcc/README.md deleted file mode 100644 index 5b8dbf3c7..000000000 --- a/mp-shadingsphere-druid-seata-tcc/README.md +++ /dev/null @@ -1,139 +0,0 @@ -# mp-shadingsphere-druid-seata-tcc - -## 准备环境 - -1. 创建mysql 数据库,导入脚本 - -2. 启动 Nacos server
- [Nacos Server 下载地址](https://github.com/alibaba/nacos/releases) - -> 下载最新版本Nacos Server, 本地启动Nacos - -注: 分别导入 doc service-A-dev.yml,service-B-dev.yml 配置文件到nacos - -3. 启动Seata Server
- [Seata Server 下载地址](https://github.com/seata/seata/releases) - -> 下载最新版本Seata Server, 本地启动Seata - -4. 启动A 启动B - -5. 访问API - - localhost:8070/geneOrder - -6. 观察事务回滚效果 - -> 注释 UserOrderServiceImpl 的代码 int a = 1 / 0; 可以观察事务回滚情况 - -## 使用组件介绍 - -* Nacos 注册中心 -* Nacos 配置中心 -* Open Feign REST 服务调用 -* Sentinel 限流熔断 -* Seata 分布式事务解决方案 - -## 项目目录介绍 - -- mp-shadingsphere-druid-seata-tcc - - base-common - `通用常量 vo` - - base-starter - `通用star组件` - - base-core-starter - `核心依赖,集成了nacos注册配置中心,openfeign,sentinel,validator` - - base-jdbc-starter - `持久化依赖,集成了mybatis-plus+druid+shardingsphere(分库分表+读写分离)` - - base-transaction-starter - `分布式事务依赖,集成了seata分布式事务(主要使用tcc模式)` - - demo-service-A - `订单服务` - - demo-service-B - `产品库存服务` - - doc `sql数据库和yaml配置` - -> 注意: 使用seata tcc模式的时候请关闭 enable-auto-data-source-proxy: false 自动代码,否则tcc模式执行后会执行at模式 - -- 版本 - -```xml -3.4.1 -1.1.22 -8.0.21 -4.0.0-RC2 -``` - -## demo - -场景:
-当创建订单的时候库存-1
-此时两个服务为分布式事务操作
-> 当两个服务调用完毕的时候1/0,发生异常,两个数据回滚 - -## 关键代码 - -```java -@Override -@GlobalTransactional -@Transactional -public void geneOrder(UserOrder userOrder) { - // 扣减库存 - ResponseEntity forEntity = restTemplate.getForEntity("http://localhost:8071/deduct?id=1", Result.class); - if(forEntity.getStatusCode() != HttpStatus.OK || - Optional.ofNullable(forEntity.getBody()).orElse(new Result()).getCode() != 200) { - throw new RuntimeException("扣减库存失败!"); - } - // 生成订单 - long id = IdWorker.getId(); - userOrder.setId(id); - userOrderTccAction.geneOrder(userOrder,id); - - int a = 1/0; -} -``` - -## 运行结果 - -- 订单服务 - -``` -2021-04-29 15:57:35.909 INFO 9104 --- [nio-8070-exec-1] i.seata.tm.api.DefaultGlobalTransaction : Begin new global transaction [127.0.0.1:8091:27149561796388640] -2021-04-29 15:57:39.033 INFO 9104 --- [nio-8070-exec-1] ShardingSphere-SQL : Rule Type: master-slave -2021-04-29 15:57:39.033 INFO 9104 --- [nio-8070-exec-1] ShardingSphere-SQL : SQL: INSERT INTO user_order ( id, -order_id, -p_id ) VALUES ( ?, -?, -? ) ::: DataSources: master -2021-04-29 15:57:39.063 INFO 9104 --- [nio-8070-exec-1] c.d.m.o.a.impl.UserOrderTccActionImpl : geneOrder---------------------1387677438737305602 -2021-04-29 15:57:39.149 INFO 9104 --- [h_RMROLE_1_1_12] i.s.c.r.p.c.RmBranchRollbackProcessor : rm handle branch rollback process:xid=127.0.0.1:8091:27149561796388640,branchId=27149561796388658,branchType=TCC,resourceId=gene-order,applicationData={"actionContext":{"action-start-time":1619683057855,"sys::prepare":"geneOrder","sys::rollback":"cancel","sys::commit":"commit","id":1387677438737305602,"host-name":"169.254.174.68","actionName":"gene-order"}} -2021-04-29 15:57:39.157 INFO 9104 --- [h_RMROLE_1_1_12] io.seata.rm.AbstractRMHandler : Branch Rollbacking: 127.0.0.1:8091:27149561796388640 27149561796388658 gene-order -2021-04-29 15:57:39.174 INFO 9104 --- [h_RMROLE_1_1_12] c.d.m.o.a.impl.UserOrderTccActionImpl : cancel---------------------1387677438737305602 -2021-04-29 15:57:39.191 INFO 9104 --- [h_RMROLE_1_1_12] ShardingSphere-SQL : Rule Type: master-slave -2021-04-29 15:57:39.191 INFO 9104 --- [h_RMROLE_1_1_12] ShardingSphere-SQL : SQL: DELETE FROM user_order WHERE id=? ::: DataSources: master -2021-04-29 15:57:39.197 INFO 9104 --- [h_RMROLE_1_1_12] io.seata.rm.AbstractResourceManager : TCC resource rollback result : true, xid: 127.0.0.1:8091:27149561796388640, branchId: 27149561796388658, resourceId: gene-order -2021-04-29 15:57:39.199 INFO 9104 --- [h_RMROLE_1_1_12] io.seata.rm.AbstractRMHandler : Branch Rollbacked result: PhaseTwo_Rollbacked -2021-04-29 15:57:39.314 INFO 9104 --- [nio-8070-exec-1] i.seata.tm.api.DefaultGlobalTransaction : [127.0.0.1:8091:27149561796388640] rollback status: Rollbacked -2021-04-29 15:57:39.338 ERROR 9104 --- [nio-8070-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ArithmeticException: / by zero] with root cause - -java.lang.ArithmeticException: / by zero -``` - -- 库存服务 - -``` -2021-04-29 15:57:39.221 INFO 4656 --- [h_RMROLE_1_1_12] i.s.c.r.p.c.RmBranchRollbackProcessor : rm handle branch rollback process:xid=127.0.0.1:8091:27149561796388640,branchId=27149561796388642,branchType=TCC,resourceId=order-decuct,applicationData={"actionContext":{"action-start-time":1619683056387,"sys::prepare":"deduct","sys::rollback":"cancel","sys::commit":"commit","id":1,"host-name":"169.254.174.68","actionName":"order-decuct"}} -2021-04-29 15:57:39.229 INFO 4656 --- [h_RMROLE_1_1_12] io.seata.rm.AbstractRMHandler : Branch Rollbacking: 127.0.0.1:8091:27149561796388640 27149561796388642 order-decuct -2021-04-29 15:57:39.251 INFO 4656 --- [h_RMROLE_1_1_12] c.d.m.p.a.impl.CompanyProductActionImpl : cancel---------------------1 -2021-04-29 15:57:39.252 INFO 4656 --- [h_RMROLE_1_1_12] ShardingSphere-SQL : Rule Type: master-slave -2021-04-29 15:57:39.252 INFO 4656 --- [h_RMROLE_1_1_12] ShardingSphere-SQL : SQL: SELECT id,product_name,account FROM company_product - - WHERE (id = ?) ::: DataSources: slave02 -2021-04-29 15:57:39.257 INFO 4656 --- [h_RMROLE_1_1_12] ShardingSphere-SQL : Rule Type: master-slave -2021-04-29 15:57:39.257 INFO 4656 --- [h_RMROLE_1_1_12] ShardingSphere-SQL : SQL: UPDATE company_product SET product_name=?, -account=? WHERE id=? ::: DataSources: master -2021-04-29 15:57:39.264 INFO 4656 --- [h_RMROLE_1_1_12] io.seata.rm.AbstractResourceManager : TCC resource rollback result : true, xid: 127.0.0.1:8091:27149561796388640, branchId: 27149561796388642, resourceId: order-decuct -2021-04-29 15:57:39.266 INFO 4656 --- [h_RMROLE_1_1_12] io.seata.rm.AbstractRMHandler : Branch Rollbacked result: PhaseTwo_Rollbacked -``` - -感谢seata团队的帮助。 \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-common/pom.xml b/mp-shadingsphere-druid-seata-tcc/base-common/pom.xml deleted file mode 100644 index 9e1a9f519..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-common/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - mp-shadingsphere-druid-seata-tcc - com.seata - 1.0.0-SNAPSHOT - - 4.0.0 - - base-common - 1.0.0-SNAPSHOT - - - - cn.hutool - hutool-all - ${hutool-all.version} - - - - commons-beanutils - commons-beanutils - ${commons-beanutils.version} - - - org.apache.commons - commons-pool2 - - - com.auth0 - java-jwt - - - - - - org.apache.maven.plugins - maven-source-plugin - - - - \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-common/src/main/java/com/seata/common/api/vo/Result.java b/mp-shadingsphere-druid-seata-tcc/base-common/src/main/java/com/seata/common/api/vo/Result.java deleted file mode 100644 index ec917cacf..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-common/src/main/java/com/seata/common/api/vo/Result.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.common.api.vo; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.seata.common.constant.CommonConstant; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.io.Serializable; - -/** - * 接口返回数据格式 - */ -@Data -@ApiModel(value = "接口返回对象", description = "接口返回对象") -public class Result implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * 成功标志 - */ - @ApiModelProperty(value = "成功标志") - private boolean success = true; - - /** - * 返回处理消息 - */ - @ApiModelProperty(value = "返回处理消息") - private String message = "操作成功!"; - - /** - * 返回代码 - */ - @ApiModelProperty(value = "返回代码") - private Integer code = 0; - - /** - * 返回数据对象 data - */ - @ApiModelProperty(value = "返回数据对象") - private T result; - - /** - * 时间戳 - */ - @ApiModelProperty(value = "时间戳") - private long timestamp = System.currentTimeMillis(); - - public Result() { - - } - - public Result success(String message) { - this.message = message; - this.code = CommonConstant.SC_OK_200; - this.success = true; - return this; - } - - @Deprecated - public static Result ok() { - Result r = new Result(); - r.setSuccess(true); - r.setCode(CommonConstant.SC_OK_200); - r.setMessage("成功"); - return r; - } - - @Deprecated - public static Result ok(String msg) { - Result r = new Result(); - r.setSuccess(true); - r.setCode(CommonConstant.SC_OK_200); - r.setMessage(msg); - return r; - } - - @Deprecated - public static Result ok(Object data) { - Result r = new Result(); - r.setSuccess(true); - r.setCode(CommonConstant.SC_OK_200); - r.setResult(data); - return r; - } - - public static Result OK() { - Result r = new Result(); - r.setSuccess(true); - r.setCode(CommonConstant.SC_OK_200); - r.setMessage("成功"); - return r; - } - - public static Result OK(T data) { - Result r = new Result(); - r.setSuccess(true); - r.setCode(CommonConstant.SC_OK_200); - r.setResult(data); - return r; - } - - public static Result OK(String msg, T data) { - Result r = new Result(); - r.setSuccess(true); - r.setCode(CommonConstant.SC_OK_200); - r.setMessage(msg); - r.setResult(data); - return r; - } - - public static Result error(String msg) { - return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg); - } - - public static Result error(int code, String msg) { - Result r = new Result(); - r.setCode(code); - r.setMessage(msg); - r.setSuccess(false); - return r; - } - - public Result error500(String message) { - this.message = message; - this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500; - this.success = false; - return this; - } - - /** - * 无权限访问返回结果 - */ - public static Result noauth(String msg) { - return error(CommonConstant.SC_YZS_NO_AUTHZ, msg); - } - - /** - * 404没找到 - * - * @param message - * @return - */ - public static Result notFound(String message) { - return error(CommonConstant.SC_YZS_NOT_FOUND, message); - } - - @JsonIgnore - private String onlTable; - -} \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-common/src/main/java/com/seata/common/constant/CommonConstant.java b/mp-shadingsphere-druid-seata-tcc/base-common/src/main/java/com/seata/common/constant/CommonConstant.java deleted file mode 100644 index 5de673318..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-common/src/main/java/com/seata/common/constant/CommonConstant.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.common.constant; - -public interface CommonConstant { - - public static final String FORMAT_DATETIME_WITH_Y_M_D_H_M_S = "yyyy-MM-dd HH:mm:ss"; - /** - * 验证码原始字符 - */ - public static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890"; - - /** - * {@code 500 Server Error} (HTTP/1.0 - RFC 1945) - */ - public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500; - /** - * {@code 200 OK} (HTTP/1.0 - RFC 1945) - */ - public static final Integer SC_OK_200 = 200; - - /** - * 访问权限认证未通过 510 - */ - public static final Integer SC_YZS_NO_AUTHZ = 510; - - /** - * 没找到资源 404 - */ - public static final Integer SC_YZS_NOT_FOUND = 404; - - /** - * 登录用户Token令牌缓存KEY前缀 - */ - public static final String PREFIX_USER_TOKEN = "prefix_user_token_"; - /** - * Token缓存时间:3600秒即一小时 - */ - public static final int TOKEN_EXPIRE_TIME = 10 * 3600; - /** - * 状态(0无效1有效) - */ - public static final String STATUS_0 = "0"; - public static final String STATUS_1 = "1"; - - public final static String X_ACCESS_TOKEN = "X-Access-Token"; - - /** - * 多租户 请求头 - */ - public final static String TENANT_ID = "tenant_id"; - - /** - * 请求头 用户id - */ - public final static String USER_ID = "user_id"; - - /** - * 请求头用户名 - */ - public final static String USERNAME = "username"; - - /** - * 微服务读取配置文件属性 服务地址 - */ - public final static String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr"; - - /** - * 验证码缓存到期时间 - */ - public static final Long VERIFY_CODE_EXPIRED = 180L; - - /** - * 用户账号已锁定 - */ - public static final String USER_ACCOUNT_STATUS_LOCKED = "1"; - - /** - * 用户账号正常 - */ - public static final String USER_ACCOUNT_STATUS_NORMAL = "0"; - - /** - * 租户状态正常 - */ - public static final String TENANT_STATUS_NORMAL = "1"; - /** - * 租户状态禁用 - */ - public static final String TENANT_STATUS_DISABLE = "0"; - - /** - * 系统id - */ - public static final String SYS_ID = "sys_id"; - /** - * 终端id - */ - public static final String TERM_ID = "term_id"; - - /** - * 账号最大会话数,为1表明一个账号同时只允许一个人登陆 - */ - public static final Integer ACCOUNT_MAX_SESSION = 1; - - /** - * 发送短信topic - */ - public static final String KAFKA_TOP_SEND_SMS_CODE = "SEND_SMS_CODE_TOPIC"; - - /** - * 日志处理topic - */ - public static final String KAFKA_TOP_LOG_DEAL_TOPIC = "LOG_DEAL_TOPIC"; - - /** - * redis手机验证码缓存 - */ - public static final String PHONE_CODE_CACHE = "phone::code::cache::"; - - /** - * 账号类型-职工 - */ - public static final String ACCOUNT_TYPE_WORKER = "2"; - /** - * 账号类型-用户 - */ - public static final String ACCOUNT_TYPE_USER = "1"; - - /** - * md5密码盐 - */ - public static final String PWD_SALT = "qwertyuiopasdfghjkl;dsy./123456798"; -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/pom.xml b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/pom.xml deleted file mode 100644 index b8262b2c6..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - base-starter - com.seata - 1.0.0-SNAPSHOT - - 4.0.0 - 1.0.0-SNAPSHOT - base-core-starter - - - - - org.springframework.boot - spring-boot-starter-web - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-config - - - - org.springframework.cloud - spring-cloud-starter-openfeign - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - - org.springframework.boot - spring-boot-starter-validation - - - - - - org.apache.maven.plugins - maven-source-plugin - - - - \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/FeignClientConfig.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/FeignClientConfig.java deleted file mode 100644 index 0c2c63dd7..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/FeignClientConfig.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.core.config; - -import com.seata.common.constant.CommonConstant; -import feign.Feign; -import feign.Logger; -import feign.RequestInterceptor; -import feign.codec.Encoder; -import feign.form.spring.SpringFormEncoder; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.http.HttpMessageConverters; -import org.springframework.cloud.openfeign.FeignAutoConfiguration; -import org.springframework.cloud.openfeign.support.SpringEncoder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.Scope; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.servlet.http.HttpServletRequest; - -@ConditionalOnClass(Feign.class) -@AutoConfigureBefore(FeignAutoConfiguration.class) -@Slf4j -@Configuration -public class FeignClientConfig { - - @Bean - public RequestInterceptor requestInterceptor() { - return requestTemplate -> { - ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); - if (null != attributes) { - HttpServletRequest request = attributes.getRequest(); - log.info("Feign request: {}", request.getRequestURI()); - // 将token信息放入header中 - String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); - String tenantId = request.getHeader(CommonConstant.TENANT_ID); - String uid = request.getHeader(CommonConstant.USER_ID); - String sys_id = request.getHeader(CommonConstant.SYS_ID); - String term_id = request.getHeader(CommonConstant.TERM_ID); - String username = request.getHeader(CommonConstant.USERNAME); - if (token == null) { - token = request.getParameter("token"); - } - log.info("Feign request token: {}", token); - requestTemplate.header(CommonConstant.TENANT_ID, request.getHeader(CommonConstant.TENANT_ID)); - requestTemplate.header(CommonConstant.USER_ID, request.getHeader(CommonConstant.USER_ID)); - requestTemplate.header(CommonConstant.USERNAME, request.getHeader(CommonConstant.USERNAME)); - requestTemplate.header(CommonConstant.SYS_ID, request.getHeader(CommonConstant.SYS_ID)); - requestTemplate.header(CommonConstant.TERM_ID, request.getHeader(CommonConstant.TERM_ID)); - requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token); - requestTemplate.header(CommonConstant.TENANT_ID, tenantId); - requestTemplate.header(CommonConstant.USER_ID, uid); - requestTemplate.header(CommonConstant.SYS_ID, sys_id); - requestTemplate.header(CommonConstant.TERM_ID, term_id); - requestTemplate.header(CommonConstant.USERNAME, username); - - } - }; - } - - /** - * Feign 客户端的日志记录,默认级别为NONE - * Logger.Level 的具体级别如下: - * NONE:不记录任何信息 - * BASIC:仅记录请求方法、URL以及响应状态码和执行时间 - * HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息 - * FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据 - */ - @Bean - Logger.Level feignLoggerLevel() { - return Logger.Level.FULL; - } - - /** - * Feign支持文件上传 - * - * @param messageConverters - * @return - */ - @Bean - @Primary - @Scope("prototype") - public Encoder multipartFormEncoder(ObjectFactory messageConverters) { - return new SpringFormEncoder(new SpringEncoder(messageConverters)); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/JacksonAutoConfiguration.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/JacksonAutoConfiguration.java deleted file mode 100644 index ca329d8a5..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/JacksonAutoConfiguration.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.core.config; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; -import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; -import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; - -import java.io.IOException; -import java.math.BigDecimal; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.TimeZone; - -import static com.seata.starter.core.config.JacksonAutoConfiguration.SerializerFeature.*; - -/** - * jackson全局序列化配置 - * - * @author xiangdongdong - * @email boolean1135@gmail.com - */ -@Slf4j -@Configuration -public class JacksonAutoConfiguration { - - public enum SerializerFeature { - // WriteNullListAsEmpty, - WriteNullStringAsEmpty, - WriteNullNumberAsZero, - WriteNullBooleanAsFalse, - WriteNullMapAsEmpty; - - public final int mask; - - SerializerFeature() { - mask = (1 << ordinal()); - } - } - - public static class FastJsonSerializerFeatureCompatibleForJackson extends BeanSerializerModifier { - final private JsonSerializer nullBooleanJsonSerializer; - final private JsonSerializer nullNumberJsonSerializer; - // final private JsonSerializer nullListJsonSerializer; - final private JsonSerializer nullStringJsonSerializer; - final private JsonSerializer nullMapJsonSerializer; - - FastJsonSerializerFeatureCompatibleForJackson(SerializerFeature... features) { - int config = 0; - for (SerializerFeature feature : features) { - config |= feature.mask; - } - nullBooleanJsonSerializer = (config & WriteNullBooleanAsFalse.mask) != 0 ? new NullBooleanSerializer() - : null; - nullNumberJsonSerializer = (config & WriteNullNumberAsZero.mask) != 0 ? new NullNumberSerializer() : null; - // nullListJsonSerializer = (config & WriteNullListAsEmpty.mask) != 0 ? new - // NullListJsonSerializer() : null; - nullStringJsonSerializer = (config & WriteNullStringAsEmpty.mask) != 0 ? new NullStringSerializer() : null; - nullMapJsonSerializer = (config & WriteNullMapAsEmpty.mask) != 0 ? new NullMapSerializer() : null; - } - - @Override - public List changeProperties(SerializationConfig config, BeanDescription beanDesc, - List beanProperties) { - for (BeanPropertyWriter writer : beanProperties) { - final JavaType javaType = writer.getType(); - final Class rawClass = javaType.getRawClass(); - if (javaType.isArrayType() || javaType.isCollectionLikeType()) { - // writer.assignNullSerializer(nullListJsonSerializer); - } else if (Number.class.isAssignableFrom(rawClass) && (rawClass.getName().startsWith("java.lang") - || rawClass.getName().startsWith("java.match"))) { - writer.assignNullSerializer(nullNumberJsonSerializer); - } else if (BigDecimal.class.isAssignableFrom(rawClass)) { - writer.assignNullSerializer(nullNumberJsonSerializer); - } else if (Boolean.class.equals(rawClass)) { - writer.assignNullSerializer(nullBooleanJsonSerializer); - } else if (String.class.equals(rawClass) || Date.class.equals(rawClass)) { - writer.assignNullSerializer(nullStringJsonSerializer); - } else if (!Date.class.equals(rawClass)) { - writer.assignNullSerializer(nullMapJsonSerializer); - } - } - return beanProperties; - } - - private static class NullListJsonSerializer extends JsonSerializer { - @Override - public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeStartArray(); - jgen.writeEndArray(); - } - } - - private static class NullNumberSerializer extends JsonSerializer { - @Override - public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeNumber(0); - } - } - - private static class NullBooleanSerializer extends JsonSerializer { - @Override - public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeBoolean(false); - } - } - - private static class NullStringSerializer extends JsonSerializer { - @Override - public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeString(""); - } - } - - private static class NullMapSerializer extends JsonSerializer { - @Override - public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeStartObject(); - jgen.writeEndObject(); - } - } - } - - @Bean - @Primary - @ConditionalOnMissingBean(ObjectMapper.class) - public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); - objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8")); - objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - // 排序key - objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); - - objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); - //忽略在json字符串中存在,在java类中不存在字段,防止错误。 - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); - /** - * 序列换成json时,将所有的long变成string - * js中long过长精度丢失 - */ - SimpleModule simpleModule = new SimpleModule(); - simpleModule.addSerializer(Long.class, ToStringSerializer.instance); - simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); - //注册xss解析器 - //simpleModule.addSerializer(String.class, new XssStringJsonSerializer()); - //simpleModule.addDeserializer(String.class, new XssStringJsonDeserializer()); - objectMapper.registerModule(simpleModule); - // 兼容fastJson 的一些空值处理 - SerializerFeature[] features = new SerializerFeature[] { - // WriteNullListAsEmpty, - WriteNullStringAsEmpty, WriteNullNumberAsZero, WriteNullBooleanAsFalse, WriteNullMapAsEmpty}; - objectMapper.setSerializerFactory(objectMapper.getSerializerFactory() - .withSerializerModifier(new FastJsonSerializerFeatureCompatibleForJackson(features))); - log.info("ObjectMapper [{}]", objectMapper); - return objectMapper; - } - -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/Knife4jConfiguration.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/Knife4jConfiguration.java deleted file mode 100644 index 14686a951..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/Knife4jConfiguration.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.core.config; - -import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -@Configuration -@EnableSwagger2 -@EnableKnife4j -@ComponentScan(basePackages = {"com.yzs.starter.core"}) -public class Knife4jConfiguration { - - @Value("${spring.swagger.description}") - private String description; - @Value("${spring.swagger.termsOfServiceUrl}") - private String termsOfServiceUrl; - @Value("${spring.swagger.version}") - private String version; - @Value("${spring.swagger.groupName}") - private String groupName; - @Value("${spring.swagger.basePackage}") - private String basePackage; - - @Bean(value = "defaultApi2") - public Docket defaultApi2() { - return new Docket(DocumentationType.SWAGGER_2).apiInfo(new ApiInfoBuilder() - //.title("swagger-bootstrap-ui-demo RESTful APIs") - .description(description).termsOfServiceUrl(termsOfServiceUrl).version(version).build()) - //分组名称 - .groupName(groupName).select() - //这里指定Controller扫描包路径 - .apis(RequestHandlerSelectors.basePackage(basePackage)).paths(PathSelectors.any()).build(); - } -} \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/PersonBeanConfiguration.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/PersonBeanConfiguration.java deleted file mode 100644 index a8a51342e..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/config/PersonBeanConfiguration.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.core.config; - -import feign.Client; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; -import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory; -import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class PersonBeanConfiguration { - - /** - * 创建FeignClient - */ - @Bean - @ConditionalOnMissingBean - public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) { - return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory, clientFactory); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/feign/IFeignService.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/feign/IFeignService.java deleted file mode 100644 index 9c8b1584a..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/feign/IFeignService.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.core.feign; - -public interface IFeignService { - - T newInstance(Class apiType, String name); -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/feign/impl/IFeignServiceImpl.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/feign/impl/IFeignServiceImpl.java deleted file mode 100644 index d43bc19ae..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/feign/impl/IFeignServiceImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.core.feign.impl; - -import com.seata.common.constant.CommonConstant; -import com.seata.starter.core.feign.IFeignService; -import feign.Client; -import feign.Contract; -import feign.Feign; -import feign.codec.Decoder; -import feign.codec.Encoder; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cloud.openfeign.FeignAutoConfiguration; -import org.springframework.cloud.openfeign.FeignClientsConfiguration; -import org.springframework.context.annotation.Import; -import org.springframework.stereotype.Service; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.servlet.http.HttpServletRequest; - -@Service -@Slf4j -@ConditionalOnClass(Feign.class) -@AutoConfigureBefore(FeignAutoConfiguration.class) -@Import(FeignClientsConfiguration.class) -public class IFeignServiceImpl implements IFeignService { - - //Feign 原生构造器 - Feign.Builder builder; - - //创建构造器 - public IFeignServiceImpl(Decoder decoder, Encoder encoder, Client client, Contract contract) { - this.builder = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract); - } - - @Override - public T newInstance(Class clientClass, String serviceName) { - builder.requestInterceptor(requestTemplate -> { - ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); - if (null != attributes) { - HttpServletRequest request = attributes.getRequest(); - log.info("Feign request: {}", request.getRequestURI()); - // 将token信息放入header中 - String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); - if (token == null) { - token = request.getParameter("token"); - } - log.info("Feign request token: {}", token); - requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token); - } - }); - return builder.target(clientClass, String.format("http://%s/", serviceName)); - } -} \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/handler/GlobalExceptionHandler.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/handler/GlobalExceptionHandler.java deleted file mode 100644 index 7de79207c..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/java/com/seata/starter/core/handler/GlobalExceptionHandler.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.core.handler; - -import com.seata.common.api.vo.Result; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.validation.ObjectError; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.servlet.ViewResolver; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.util.List; - -/** - * 全局异常处理 - */ -@RestControllerAdvice -@ConditionalOnClass(ViewResolver.class) -@Slf4j -public class GlobalExceptionHandler { - @ExceptionHandler(MethodArgumentNotValidException.class) - public Result MethodArgumentNotValidException(Exception ex, HttpServletRequest request, - HttpServletResponse response) { - ex.printStackTrace(); - MethodArgumentNotValidException c = (MethodArgumentNotValidException)ex; - List errors = c.getBindingResult().getAllErrors(); - // StringBuffer errorMsg=new StringBuffer(); - // errors.stream().forEach(x -> errorMsg.append(x.getDefaultMessage()).append(";")); - return Result.error(errors.get(0).getDefaultMessage()); - } - - // 默认的异常 - @ExceptionHandler(value = Exception.class) - public Result handleException(Exception e) { - e.printStackTrace(); - return Result.error(e.getMessage()); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/resources/META-INF/spring.factories b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 8e9f0371a..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.seata.starter.core.config.Knife4jConfiguration \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/resources/bootstrap.yml b/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/resources/bootstrap.yml deleted file mode 100644 index 921ab03b5..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-core-starter/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,43 +0,0 @@ -spring: - profiles: - # 当前激活环境 - active: @profile.name@ - main: - allow-bean-definition-overriding: true - cloud: - #配置Bus id(远程推送事件) - bus: - id: ${spring.application.name}:${server.port} - nacos: - config: - # Nacos 认证用户 - username: nacos - # Nacos 认证密码 - password: nacos - # 命名空间 常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等 - namespace: @config.namespace@ - # 配置中心地址 - server-addr: @config.server-addr@ - # 配置对应的分组 - group: @config.group@ - # 配置文件后缀 - file-extension: yml - # prefix: @prefix.name@ - # 支持多个共享 Data Id 的配置,优先级小于extension-configs,自定义 Data Id 配置 属性是个集合,内部由 Config POJO 组成。Config 有 3 个属性,分别是 dataId, group 以及 refresh - #shared-configs[0]: - #data-id: ${prefix.name}-common.yaml # 配置文件名-Data Id - #group: ${config.group} # 默认为DEFAULT_GROUP - #refresh: false # 是否动态刷新,默认为false - discovery: - namespace: @config.namespace@ - server-addr: @config.server-addr@ - watch: - enabled: false -feign: - client: - config: - default: - #建立连接所用的时间,适用于网络状况正常的情况下,两端连接所需要的时间 - ConnectTimeOut: 5000 - #指建立连接后从服务端读取到可用资源所用的时间 - ReadTimeOut: 5000 \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/pom.xml b/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/pom.xml deleted file mode 100644 index 802f79c3e..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - base-starter - com.seata - 1.0.0-SNAPSHOT - - 4.0.0 - - base-jdbc-starter - 1.0.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter-aop - - - - - org.apache.shardingsphere - sharding-jdbc-core - ${shardingsphere.version} - - - org.apache.shardingsphere - sharding-jdbc-spring-boot-starter - ${shardingsphere.version} - - - - - - - - - - com.baomidou - mybatis-plus-boot-starter - ${mybatis-plus.version} - - - - - com.alibaba - druid - ${druid.version} - - - - - - - - - - - - - - - - - mysql - mysql-connector-java - ${mysql-connector-java.version} - runtime - - - org.springframework - spring-web - provided - - - javax.servlet - servlet-api - 2.4 - provided - - - - - - org.apache.maven.plugins - maven-source-plugin - - - - \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/src/main/java/com/seata/starter/jdbc/config/MybatisPlusConfig.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/src/main/java/com/seata/starter/jdbc/config/MybatisPlusConfig.java deleted file mode 100644 index de80df21c..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/src/main/java/com/seata/starter/jdbc/config/MybatisPlusConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.jdbc.config; - -import com.baomidou.mybatisplus.annotation.DbType; -import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; -import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ComponentScan(basePackages = {"com.seata.starter.jdbc"}) -public class MybatisPlusConfig { - /** - * mybatis分页插件 - * - * @return - */ - @Bean - public MybatisPlusInterceptor mybatisPlusInterceptor() { - MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); - interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); - return interceptor; - } - -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/src/main/resources/META-INF/spring.factories b/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 4d9d22c92..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-jdbc-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.seata.starter.jdbc.config.MybatisPlusConfig \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/pom.xml b/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/pom.xml deleted file mode 100644 index 2981c1528..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/pom.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - base-starter - com.seata - 1.0.0-SNAPSHOT - - 4.0.0 - 1.0.0-SNAPSHOT - base-transaction-starter - - - com.seata - base-jdbc-starter - provided - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-seata - - - - org.apache.shardingsphere - sharding-jdbc-spring-boot-starter - ${shardingsphere.version} - provided - - - - org.apache.shardingsphere - sharding-transaction-base-seata-at - ${shardingsphere.version} - - - - - - - - io.seata - seata-rm-datasource - 0.7.1 - - - io.seata - seata-tm - 0.7.1 - - - io.seata - seata-spring - 0.7.1 - - - - - - org.apache.maven.plugins - maven-source-plugin - - - - - \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/java/com/seata/starter/transaction/config/MybatisPlusAutoConfig.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/java/com/seata/starter/transaction/config/MybatisPlusAutoConfig.java deleted file mode 100644 index fccb10534..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/java/com/seata/starter/transaction/config/MybatisPlusAutoConfig.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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. - */ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by Fernflower decompiler) -// - -package com.seata.starter.transaction.config; - -import com.baomidou.mybatisplus.autoconfigure.*; -import com.baomidou.mybatisplus.core.MybatisConfiguration; -import com.baomidou.mybatisplus.core.config.GlobalConfig; -import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; -import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; -import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; -import com.baomidou.mybatisplus.core.injector.ISqlInjector; -import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; -import com.seata.starter.jdbc.config.MybatisPlusConfig; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.mapping.DatabaseIdProvider; -import org.apache.ibatis.plugin.Interceptor; -import org.apache.ibatis.scripting.LanguageDriver; -import org.apache.ibatis.session.ExecutorType; -import org.apache.ibatis.session.SqlSessionFactory; -import org.apache.ibatis.transaction.TransactionFactory; -import org.apache.ibatis.type.TypeHandler; -import org.mybatis.spring.SqlSessionFactoryBean; -import org.mybatis.spring.SqlSessionTemplate; -import org.mybatis.spring.mapper.MapperFactoryBean; -import org.mybatis.spring.mapper.MapperScannerConfigurer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.boot.autoconfigure.AutoConfigurationPackages; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -import javax.sql.DataSource; - -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.function.Consumer; -import java.util.stream.Stream; - -@Configuration -@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class}) -@ConditionalOnSingleCandidate(DataSource.class) -@EnableConfigurationProperties({MybatisPlusProperties.class}) -@AutoConfigureAfter( - {DataSourceAutoConfiguration.class, MybatisPlusLanguageDriverAutoConfiguration.class, MybatisPlusConfig.class}) -public class MybatisPlusAutoConfig implements InitializingBean { - private static final Logger logger = LoggerFactory.getLogger(MybatisPlusAutoConfig.class); - private final MybatisPlusProperties properties; - private final Interceptor[] interceptors; - private final TypeHandler[] typeHandlers; - private final LanguageDriver[] languageDrivers; - private final ResourceLoader resourceLoader; - private final DatabaseIdProvider databaseIdProvider; - private final List configurationCustomizers; - private final List mybatisPlusPropertiesCustomizers; - private final ApplicationContext applicationContext; - - public MybatisPlusAutoConfig(MybatisPlusProperties properties, ObjectProvider interceptorsProvider, - ObjectProvider typeHandlersProvider, - ObjectProvider languageDriversProvider, - ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, - ObjectProvider> configurationCustomizersProvider, - ObjectProvider> mybatisPlusPropertiesCustomizerProvider, - ApplicationContext applicationContext) { - this.properties = properties; - this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable(); - this.typeHandlers = (TypeHandler[])typeHandlersProvider.getIfAvailable(); - this.languageDrivers = (LanguageDriver[])languageDriversProvider.getIfAvailable(); - this.resourceLoader = resourceLoader; - this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable(); - this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable(); - this.mybatisPlusPropertiesCustomizers = (List)mybatisPlusPropertiesCustomizerProvider.getIfAvailable(); - this.applicationContext = applicationContext; - } - - public void afterPropertiesSet() { - if (!CollectionUtils.isEmpty(this.mybatisPlusPropertiesCustomizers)) { - this.mybatisPlusPropertiesCustomizers.forEach((i) -> { - i.customize(this.properties); - }); - } - - this.checkConfigFileExists(); - } - - private void checkConfigFileExists() { - if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) { - Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation()); - Assert.state(resource.exists(), "Cannot find config location: " + resource - + " (please add config file or check your Mybatis configuration)"); - } - - } - - @Bean - @ConditionalOnMissingBean - public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { - MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); - factory.setDataSource(dataSource); - factory.setVfs(SpringBootVFS.class); - if (StringUtils.hasText(this.properties.getConfigLocation())) { - factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); - } - - this.applyConfiguration(factory); - if (this.properties.getConfigurationProperties() != null) { - factory.setConfigurationProperties(this.properties.getConfigurationProperties()); - } - - if (!ObjectUtils.isEmpty(this.interceptors)) { - factory.setPlugins(this.interceptors); - } - - if (this.databaseIdProvider != null) { - factory.setDatabaseIdProvider(this.databaseIdProvider); - } - - if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { - factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); - } - - if (this.properties.getTypeAliasesSuperType() != null) { - factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); - } - - if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { - factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); - } - - if (!ObjectUtils.isEmpty(this.typeHandlers)) { - factory.setTypeHandlers(this.typeHandlers); - } - - Resource[] mapperLocations = this.properties.resolveMapperLocations(); - if (!ObjectUtils.isEmpty(mapperLocations)) { - factory.setMapperLocations(mapperLocations); - } - - this.getBeanThen(TransactionFactory.class, factory::setTransactionFactory); - Class defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver(); - if (!ObjectUtils.isEmpty(this.languageDrivers)) { - factory.setScriptingLanguageDrivers(this.languageDrivers); - } - - Optional.ofNullable(defaultLanguageDriver).ifPresent(factory::setDefaultScriptingLanguageDriver); - if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) { - factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage()); - } - - GlobalConfig globalConfig = this.properties.getGlobalConfig(); - this.getBeanThen(MetaObjectHandler.class, globalConfig::setMetaObjectHandler); - this.getBeanThen(IKeyGenerator.class, (i) -> { - globalConfig.getDbConfig().setKeyGenerator(i); - }); - this.getBeanThen(ISqlInjector.class, globalConfig::setSqlInjector); - this.getBeanThen(IdentifierGenerator.class, globalConfig::setIdentifierGenerator); - factory.setGlobalConfig(globalConfig); - return factory.getObject(); - } - - private void getBeanThen(Class clazz, Consumer consumer) { - if (this.applicationContext.getBeanNamesForType(clazz, false, false).length > 0) { - consumer.accept(this.applicationContext.getBean(clazz)); - } - - } - - private void applyConfiguration(MybatisSqlSessionFactoryBean factory) { - MybatisConfiguration configuration = this.properties.getConfiguration(); - if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) { - configuration = new MybatisConfiguration(); - } - - if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) { - Iterator var3 = this.configurationCustomizers.iterator(); - - while (var3.hasNext()) { - ConfigurationCustomizer customizer = (ConfigurationCustomizer)var3.next(); - customizer.customize(configuration); - } - } - - factory.setConfiguration(configuration); - } - - @Bean - @ConditionalOnMissingBean - public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { - ExecutorType executorType = this.properties.getExecutorType(); - return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate( - sqlSessionFactory); - } - - @Configuration - @Import({MybatisPlusAutoConfig.AutoConfiguredMapperScannerRegistrar.class}) - @ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class}) - public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean { - public MapperScannerRegistrarNotFoundConfiguration() { - } - - public void afterPropertiesSet() { - MybatisPlusAutoConfig.logger.debug( - "Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and " - + "MapperScannerConfigurer."); - } - } - - public static class AutoConfiguredMapperScannerRegistrar - implements BeanFactoryAware, ImportBeanDefinitionRegistrar { - private BeanFactory beanFactory; - - public AutoConfiguredMapperScannerRegistrar() { - } - - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, - BeanDefinitionRegistry registry) { - if (!AutoConfigurationPackages.has(this.beanFactory)) { - MybatisPlusAutoConfig.logger.debug( - "Could not determine auto-configuration package, automatic mapper scanning disabled."); - } else { - MybatisPlusAutoConfig.logger.debug("Searching for mappers annotated with @Mapper"); - List packages = AutoConfigurationPackages.get(this.beanFactory); - if (MybatisPlusAutoConfig.logger.isDebugEnabled()) { - packages.forEach((pkg) -> { - MybatisPlusAutoConfig.logger.debug("Using auto-configuration base package '{}'", pkg); - }); - } - - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( - MapperScannerConfigurer.class); - builder.addPropertyValue("processPropertyPlaceHolders", true); - builder.addPropertyValue("annotationClass", Mapper.class); - builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); - BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class); - Stream.of(beanWrapper.getPropertyDescriptors()).filter((x) -> { - return x.getName().equals("lazyInitialization"); - }).findAny().ifPresent((x) -> { - builder.addPropertyValue("lazyInitialization", "${mybatis.lazy-initialization:false}"); - }); - registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition()); - } - } - - public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/java/com/seata/starter/transaction/config/SeataConfig.java b/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/java/com/seata/starter/transaction/config/SeataConfig.java deleted file mode 100644 index e43728e9e..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/java/com/seata/starter/transaction/config/SeataConfig.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.seata.starter.transaction.config; - -import io.seata.spring.annotation.GlobalTransactionalInterceptor; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.aop.Advisor; -import org.springframework.aop.aspectj.AspectJExpressionPointcut; -import org.springframework.aop.support.DefaultPointcutAdvisor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Aspect -@Configuration -public class SeataConfig { - private static final String AOP_POINTCUT_EXPRESSION = "@annotation(io.seata.spring.annotation.GlobalTransactional)"; - - @Bean - public GlobalTransactionalInterceptor globalTransactionalInterceptor() { - GlobalTransactionalInterceptor globalTransactionalInterceptor = new GlobalTransactionalInterceptor(null); - return globalTransactionalInterceptor; - } - - @Bean - public Advisor seataAdviceAdvisor() { - AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); - pointcut.setExpression(AOP_POINTCUT_EXPRESSION); - return new DefaultPointcutAdvisor(pointcut, globalTransactionalInterceptor()); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/resources/META-INF/spring.factories b/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 5ee68b063..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/base-transaction-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.seata.starter.transaction.config.MybatisPlusAutoConfig,\ - com.seata.starter.transaction.config.SeataConfig \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/base-starter/pom.xml b/mp-shadingsphere-druid-seata-tcc/base-starter/pom.xml deleted file mode 100644 index 2ad3a53d2..000000000 --- a/mp-shadingsphere-druid-seata-tcc/base-starter/pom.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - mp-shadingsphere-druid-seata-tcc - com.seata - 1.0.0-SNAPSHOT - - 4.0.0 - - base-starter - pom - 1.0.0-SNAPSHOT - - base-core-starter - base-jdbc-starter - base-transaction-starter - - - - com.seata - base-common - - - - - - org.apache.maven.plugins - maven-source-plugin - - - - \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/pom.xml b/mp-shadingsphere-druid-seata-tcc/demo-service-A/pom.xml deleted file mode 100644 index 76d49a47c..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - mp-shadingsphere-druid-seata-tcc - com.seata - 1.0.0-SNAPSHOT - - 4.0.0 - - demo-service-A - - - - com.seata - base-common - - - com.seata - base-core-starter - - - com.seata - base-jdbc-starter - - - com.seata - base-transaction-starter - - - \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/ServiceAApp.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/ServiceAApp.java deleted file mode 100644 index 7a0522525..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/ServiceAApp.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo; - -import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.web.client.RestTemplate; - -@SpringBootApplication(exclude = {MybatisPlusAutoConfiguration.class, DataSourceAutoConfiguration.class,}) -@MapperScan(basePackages = {"com.demo.modules.**.mapper*"}) -@EnableAspectJAutoProxy(proxyTargetClass = true) -public class ServiceAApp { - @Bean - public RestTemplate template() { - return new RestTemplate(); - } - - public static void main(String[] args) { - SpringApplication.run(ServiceAApp.class, args); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/action/UserOrderTccAction.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/action/UserOrderTccAction.java deleted file mode 100644 index 96718a9ff..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/action/UserOrderTccAction.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.order.action; - -import com.demo.modules.order.entity.UserOrder; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextParameter; -import io.seata.rm.tcc.api.LocalTCC; -import io.seata.rm.tcc.api.TwoPhaseBusinessAction; - -@LocalTCC -public interface UserOrderTccAction { - @TwoPhaseBusinessAction(name = "gene-order", commitMethod = "commit", rollbackMethod = "cancel") - void geneOrder(UserOrder userOrder, @BusinessActionContextParameter(paramName = "id") Long id); - - boolean commit(BusinessActionContext businessActionContext); - - boolean cancel(BusinessActionContext businessActionContext); -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/action/impl/UserOrderTccActionImpl.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/action/impl/UserOrderTccActionImpl.java deleted file mode 100644 index 91033c04c..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/action/impl/UserOrderTccActionImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.order.action.impl; - -import com.demo.modules.order.action.UserOrderTccAction; -import com.demo.modules.order.entity.UserOrder; -import com.demo.modules.order.service.UserOderService; -import com.seata.common.api.vo.Result; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.spring.annotation.GlobalTransactional; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -import java.util.Optional; - -@Slf4j -@Component -public class UserOrderTccActionImpl implements UserOrderTccAction { - @Autowired - private UserOderService userOderService; - - @Override - public void geneOrder(UserOrder userOrder, Long id) { - // 生成订单 - userOderService.save(userOrder); - log.info("geneOrder---------------------{}", id); - } - - @Override - public boolean commit(BusinessActionContext businessActionContext) { - Long id = (Long)businessActionContext.getActionContext("id"); - log.info("commit---------------------{}", id); - return true; - } - - @Override - public boolean cancel(BusinessActionContext businessActionContext) { - Long id = (Long)businessActionContext.getActionContext("id"); - log.info("cancel---------------------{}", id); - if (id == null) { - return true; - } - userOderService.removeById(id); - return true; - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/controller/UserOrderController.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/controller/UserOrderController.java deleted file mode 100644 index 3c149b4c5..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/controller/UserOrderController.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.order.controller; - -import com.baomidou.mybatisplus.core.toolkit.IdWorker; -import com.demo.modules.order.action.UserOrderTccAction; -import com.demo.modules.order.entity.UserOrder; -import com.demo.modules.order.service.UserOderService; -import com.seata.common.api.vo.Result; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@Api(tags = "用户订单") -public class UserOrderController { - @Autowired - private UserOderService userOderService; - - @GetMapping("/geneOrder") - @ApiOperation("生成订单") - public Result geneOrder() { - UserOrder userOrder = new UserOrder(); - userOrder.setOrderId(IdWorker.getId()); - userOrder.setPId(1L); - userOderService.geneOrder(userOrder); - return Result.OK(userOrder); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/entity/UserOrder.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/entity/UserOrder.java deleted file mode 100644 index d18e46df5..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/entity/UserOrder.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.order.entity; - -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; - -@Data -public class UserOrder implements Serializable { - @TableId - private Long id; - private Long orderId; - private Long pId; -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/mapper/UserOrderMapper.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/mapper/UserOrderMapper.java deleted file mode 100644 index 42bde0502..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/mapper/UserOrderMapper.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.order.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.demo.modules.order.entity.UserOrder; - -public interface UserOrderMapper extends BaseMapper {} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/mapper/xml/UserOrderMapper.xml b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/mapper/xml/UserOrderMapper.xml deleted file mode 100644 index 7c4453778..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/mapper/xml/UserOrderMapper.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/service/UserOderService.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/service/UserOderService.java deleted file mode 100644 index 55bdb451f..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/service/UserOderService.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.order.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.demo.modules.order.entity.UserOrder; - -public interface UserOderService extends IService { - void geneOrder(UserOrder userOrder); -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/service/impl/UserOderServiceImpl.java b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/service/impl/UserOderServiceImpl.java deleted file mode 100644 index 9f08b7e7e..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/java/com/demo/modules/order/service/impl/UserOderServiceImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.order.service.impl; - -import com.baomidou.mybatisplus.core.toolkit.IdWorker; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.demo.modules.order.action.UserOrderTccAction; -import com.demo.modules.order.entity.UserOrder; -import com.demo.modules.order.mapper.UserOrderMapper; -import com.demo.modules.order.service.UserOderService; -import com.seata.common.api.vo.Result; -import io.seata.spring.annotation.GlobalTransactional; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.client.RestTemplate; - -import java.util.Optional; - -@Service -public class UserOderServiceImpl extends ServiceImpl implements UserOderService { - @Autowired - private UserOrderTccAction userOrderTccAction; - @Autowired - private RestTemplate restTemplate; - - @Override - @GlobalTransactional - @Transactional - public void geneOrder(UserOrder userOrder) { - // 扣减库存 - ResponseEntity forEntity = restTemplate.getForEntity("http://localhost:8071/deduct?id=1", Result.class); - if (forEntity.getStatusCode() != HttpStatus.OK || Optional.ofNullable(forEntity.getBody()).orElse(new Result()) - .getCode() != 200) { - throw new RuntimeException("扣减库存失败!"); - } - // 生成订单 - long id = IdWorker.getId(); - userOrder.setId(id); - userOrderTccAction.geneOrder(userOrder, id); - - // 校验 事务回滚 - int a = 1 / 0; - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/application.yml b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/application.yml deleted file mode 100644 index b67009835..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/application.yml +++ /dev/null @@ -1,3 +0,0 @@ -spring: - application: - name: service-A \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/bootstrap.properties b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/bootstrap.properties deleted file mode 100644 index b3342a27b..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/bootstrap.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.cloud.nacos.config.server-addr=@config.server-addr@ -spring.cloud.nacos.config.file-extension=yml -spring.application.name=service-A -spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/config.properties b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/config.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/file.conf b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/file.conf deleted file mode 100644 index 7674d8743..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/file.conf +++ /dev/null @@ -1,118 +0,0 @@ - -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - # the client batch send request enable - enableClientBatchSendRequest = true - #thread factory for netty - threadFactory { - bossThreadPrefix = "NettyBoss" - workerThreadPrefix = "NettyServerNIOWorker" - serverExecutorThread-prefix = "NettyServerBizHandler" - shareBossWorker = false - clientSelectorThreadPrefix = "NettyClientSelector" - clientSelectorThreadSize = 1 - clientWorkerThreadPrefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - bossThreadSize = 1 - #auto default pin or 8 - workerThreadSize = "default" - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #transaction service group mapping - vgroupMapping.my_test_tx_group = "default" - #only support when registry.type=file, please don't set multiple addresses - default.grouplist = "127.0.0.1:8091" - #degrade, current not support - enableDegrade = false - #disable seata - disableGlobalTransaction = false -} -client { - rm { - asyncCommitBufferLimit = 10000 - lock { - retryInterval = 10 - retryTimes = 30 - retryPolicyBranchRollbackOnConflict = true - } - reportRetryCount = 5 - tableMetaCheckEnable = false - reportSuccessEnable = false - } - tm { - commitRetryCount = 5 - rollbackRetryCount = 5 - } - undo { - dataValidation = true - logSerialization = "jackson" - logTable = "undo_log" - } - log { - exceptionRate = 100 - } -} -## transaction log store, only used in seata-server -store { - ## store mode: file、db、redis - mode = "db" - - ## file store property - file { - ## store location dir - dir = "sessionStore" - # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions - maxBranchSessionSize = 16384 - # globe session size , if exceeded throws exceptions - maxGlobalSessionSize = 512 - # file buffer size , if exceeded allocate new buffer - fileWriteBufferCacheSize = 16384 - # when recover batch read size - sessionReloadReadSize = 100 - # async, sync - flushDiskMode = async - } - - ## database store property - db { - ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc. - datasource = "druid" - ## mysql/oracle/postgresql/h2/oceanbase etc. - dbType = "mysql" - driverClassName = "com.mysql.jdbc.Driver" - url = "jdbc:mysql://127.0.0.1:3307/yzs-plat?rewriteBatchedStatements=true" - user = "mysql" - password = "123456789" - minConn = 5 - maxConn = 30 - globalTable = "global_table" - branchTable = "branch_table" - lockTable = "lock_table" - queryLimit = 100 - maxWait = 5000 - } - - ## redis store property - redis { - host = "127.0.0.1" - port = "6379" - password = "" - database = "0" - minConn = 1 - maxConn = 10 - queryLimit = 100 - } - -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/registry.conf b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/registry.conf deleted file mode 100644 index 0c46e26a1..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/registry.conf +++ /dev/null @@ -1,89 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - application = "seata-server" - serverAddr = "127.0.0.1:8848" - group = "SEATA_GROUP" - namespace = "" - cluster = "default" - username = "nacos" - password = "nacos" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = 0 - password = "" - cluster = "default" - timeout = 0 - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3 - type = "nacos" - - nacos { - serverAddr = "127.0.0.1:8848" - namespace = "" - group = "SEATA_GROUP" - username = "nacos" - password = "nacos" - dataId = "seataServer.properties" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - appId = "seata-server" - apolloMeta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/seata.conf b/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/seata.conf deleted file mode 100644 index e0e46db3a..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-A/src/main/resources/seata.conf +++ /dev/null @@ -1,4 +0,0 @@ -client { - application.id = service-A ## 应用唯一主键 - transaction.service.group = my_test_tx_group ## 所属事务组 -} \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/pom.xml b/mp-shadingsphere-druid-seata-tcc/demo-service-B/pom.xml deleted file mode 100644 index 5a962a986..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - mp-shadingsphere-druid-seata-tcc - com.seata - 1.0.0-SNAPSHOT - - 4.0.0 - - demo-service-B - - - - com.seata - base-common - - - com.seata - base-core-starter - - - com.seata - base-jdbc-starter - - - com.seata - base-transaction-starter - - - \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/ServiceBApp.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/ServiceBApp.java deleted file mode 100644 index be9dbe159..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/ServiceBApp.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo; - -import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; - -@SpringBootApplication(exclude = {MybatisPlusAutoConfiguration.class, DataSourceAutoConfiguration.class,}) -@MapperScan(basePackages = {"com.demo.modules.**.mapper*"}) -@EnableAspectJAutoProxy(proxyTargetClass = true) -public class ServiceBApp { - public static void main(String[] args) { - SpringApplication.run(ServiceBApp.class, args); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/action/CompanyProductAction.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/action/CompanyProductAction.java deleted file mode 100644 index ba92504f3..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/action/CompanyProductAction.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.product.action; - -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextParameter; -import io.seata.rm.tcc.api.LocalTCC; -import io.seata.rm.tcc.api.TwoPhaseBusinessAction; - -@LocalTCC -public interface CompanyProductAction { - @TwoPhaseBusinessAction(name = "order-decuct", commitMethod = "commit", rollbackMethod = "cancel") - void deduct(@BusinessActionContextParameter(paramName = "id") Long id); - - boolean commit(BusinessActionContext businessActionContext); - - boolean cancel(BusinessActionContext businessActionContext); -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/action/impl/CompanyProductActionImpl.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/action/impl/CompanyProductActionImpl.java deleted file mode 100644 index 61971f599..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/action/impl/CompanyProductActionImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.product.action.impl; - -import com.demo.modules.product.action.CompanyProductAction; -import com.demo.modules.product.entity.CompanyProduct; -import com.demo.modules.product.service.ICompanyProductService; -import io.seata.rm.tcc.api.BusinessActionContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -@Component -@Slf4j -public class CompanyProductActionImpl implements CompanyProductAction { - @Autowired - private ICompanyProductService companyProductService; - - @Override - @Transactional - public void deduct(Long id) { - CompanyProduct id1 = companyProductService.query().eq("id", id).one(); - id1.setAccount(id1.getAccount() - 1); - companyProductService.updateById(id1); - } - - @Override - public boolean commit(BusinessActionContext businessActionContext) { - Long id = Long.parseLong(businessActionContext.getActionContext("id") + ""); - log.info("cancel---------------------{}", id); - return true; - } - - @Override - public boolean cancel(BusinessActionContext businessActionContext) { - Long id = Long.parseLong(businessActionContext.getActionContext("id") + ""); - log.info("cancel---------------------{}", id); - CompanyProduct id1 = companyProductService.query().eq("id", id).one(); - id1.setAccount(id1.getAccount() + 1); - companyProductService.updateById(id1); - return true; - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/controller/CompanyProductController.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/controller/CompanyProductController.java deleted file mode 100644 index 672e4a26b..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/controller/CompanyProductController.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.product.controller; - -import com.demo.modules.product.action.CompanyProductAction; -import com.seata.common.api.vo.Result; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@Api(tags = "产品库存") -public class CompanyProductController { - @Autowired - private CompanyProductAction companyProductAction; - - @GetMapping("/deduct") - @ApiOperation("扣减库存") - public Result deduct(@RequestParam("id") Long id) { - companyProductAction.deduct(id); - return Result.OK(); - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/entity/CompanyProduct.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/entity/CompanyProduct.java deleted file mode 100644 index b30144e6a..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/entity/CompanyProduct.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.product.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; - -@Data -public class CompanyProduct implements Serializable { - @TableId - private Long id; - @TableField(value = "product_name") - private String productName; - @TableField(value = "account") - private Long account; -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/mapper/CompanyProductMapper.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/mapper/CompanyProductMapper.java deleted file mode 100644 index aa6762b36..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/mapper/CompanyProductMapper.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.product.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.demo.modules.product.entity.CompanyProduct; - -public interface CompanyProductMapper extends BaseMapper {} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/mapper/xml/CompanyProductMapper.xml b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/mapper/xml/CompanyProductMapper.xml deleted file mode 100644 index 9db35682b..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/mapper/xml/CompanyProductMapper.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/service/ICompanyProductService.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/service/ICompanyProductService.java deleted file mode 100644 index c290a296e..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/service/ICompanyProductService.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.product.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.demo.modules.product.entity.CompanyProduct; - -public interface ICompanyProductService extends IService {} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/service/impl/CompanyProductImpl.java b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/service/impl/CompanyProductImpl.java deleted file mode 100644 index 422bf31d6..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/java/com/demo/modules/product/service/impl/CompanyProductImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 com.demo.modules.product.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.demo.modules.product.entity.CompanyProduct; -import com.demo.modules.product.mapper.CompanyProductMapper; -import com.demo.modules.product.service.ICompanyProductService; -import org.springframework.stereotype.Service; - -@Service -public class CompanyProductImpl extends ServiceImpl - implements ICompanyProductService {} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/application.yml b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/application.yml deleted file mode 100644 index 2d48fd813..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/application.yml +++ /dev/null @@ -1,3 +0,0 @@ -spring: - application: - name: service-B \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/bootstrap.properties b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/bootstrap.properties deleted file mode 100644 index 0faa7e693..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/bootstrap.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.cloud.nacos.config.server-addr=@config.server-addr@ -spring.cloud.nacos.config.file-extension=yml -spring.application.name=service-B -spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/config.properties b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/config.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/file.conf b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/file.conf deleted file mode 100644 index d1199abfc..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/file.conf +++ /dev/null @@ -1,118 +0,0 @@ - -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - # the client batch send request enable - enableClientBatchSendRequest = true - #thread factory for netty - threadFactory { - bossThreadPrefix = "NettyBoss" - workerThreadPrefix = "NettyServerNIOWorker" - serverExecutorThread-prefix = "NettyServerBizHandler" - shareBossWorker = false - clientSelectorThreadPrefix = "NettyClientSelector" - clientSelectorThreadSize = 1 - clientWorkerThreadPrefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - bossThreadSize = 1 - #auto default pin or 8 - workerThreadSize = "default" - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #transaction service group mapping - vgroupMapping.my_test_tx_group = "default" - #only support when registry.type=file, please don't set multiple addresses - default.grouplist = "127.0.0.1:8091" - #degrade, current not support - enableDegrade = false - #disable seata - disableGlobalTransaction = false -} -client { - rm { - asyncCommitBufferLimit = 10000 - lock { - retryInterval = 10 - retryTimes = 30 - retryPolicyBranchRollbackOnConflict = true - } - reportRetryCount = 5 - tableMetaCheckEnable = false - reportSuccessEnable = false - } - tm { - commitRetryCount = 5 - rollbackRetryCount = 5 - } - undo { - dataValidation = true - logSerialization = "jackson" - logTable = "undo_log" - } - log { - exceptionRate = 100 - } -} -## transaction log store, only used in seata-server -store { - ## store mode: file、db、redis - mode = "db" - - ## file store property - file { - ## store location dir - dir = "sessionStore" - # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions - maxBranchSessionSize = 16384 - # globe session size , if exceeded throws exceptions - maxGlobalSessionSize = 512 - # file buffer size , if exceeded allocate new buffer - fileWriteBufferCacheSize = 16384 - # when recover batch read size - sessionReloadReadSize = 100 - # async, sync - flushDiskMode = async - } - - ## database store property - db { - ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc. - datasource = "druid" - ## mysql/oracle/postgresql/h2/oceanbase etc. - dbType = "mysql" - driverClassName = "com.mysql.jdbc.Driver" - url = "jdbc:mysql://127.0.0.1:3306/yzs-plat?rewriteBatchedStatements=true" - user = "mysql" - password = "123456789" - minConn = 5 - maxConn = 30 - globalTable = "global_table" - branchTable = "branch_table" - lockTable = "lock_table" - queryLimit = 100 - maxWait = 5000 - } - - ## redis store property - redis { - host = "127.0.0.1" - port = "6379" - password = "" - database = "0" - minConn = 1 - maxConn = 10 - queryLimit = 100 - } - -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/registry.conf b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/registry.conf deleted file mode 100644 index 0c46e26a1..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/registry.conf +++ /dev/null @@ -1,89 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - application = "seata-server" - serverAddr = "127.0.0.1:8848" - group = "SEATA_GROUP" - namespace = "" - cluster = "default" - username = "nacos" - password = "nacos" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = 0 - password = "" - cluster = "default" - timeout = 0 - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3 - type = "nacos" - - nacos { - serverAddr = "127.0.0.1:8848" - namespace = "" - group = "SEATA_GROUP" - username = "nacos" - password = "nacos" - dataId = "seataServer.properties" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - appId = "seata-server" - apolloMeta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/seata.conf b/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/seata.conf deleted file mode 100644 index d1d1c1047..000000000 --- a/mp-shadingsphere-druid-seata-tcc/demo-service-B/src/main/resources/seata.conf +++ /dev/null @@ -1,4 +0,0 @@ -client { - application.id = service-B ## 应用唯一主键 - transaction.service.group = my_test_tx_group ## 所属事务组 -} \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/doc/seata-test-service-a.sql b/mp-shadingsphere-druid-seata-tcc/doc/seata-test-service-a.sql deleted file mode 100644 index 943e452c2..000000000 --- a/mp-shadingsphere-druid-seata-tcc/doc/seata-test-service-a.sql +++ /dev/null @@ -1,35 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : mysql_188_master - Source Server Type : MySQL - Source Server Version : 50733 - Source Host : 127.0.0.1:3307 - Source Schema : seata-test-service-a - - Target Server Type : MySQL - Target Server Version : 50733 - File Encoding : 65001 - - Date: 29/04/2021 14:55:25 -*/ - -SET NAMES utf8mb4; -SET -FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for user_order --- ---------------------------- -DROP TABLE IF EXISTS `user_order`; -CREATE TABLE `user_order` -( - `id` bigint(255) NOT NULL, - `uid` bigint(255) NULL DEFAULT NULL, - `order_id` bigint(20) NULL DEFAULT NULL, - `p_id` bigint(20) NULL DEFAULT NULL, - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; - -SET -FOREIGN_KEY_CHECKS = 1; diff --git a/mp-shadingsphere-druid-seata-tcc/doc/seata-test-service-b.sql b/mp-shadingsphere-druid-seata-tcc/doc/seata-test-service-b.sql deleted file mode 100644 index 808c83498..000000000 --- a/mp-shadingsphere-druid-seata-tcc/doc/seata-test-service-b.sql +++ /dev/null @@ -1,40 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : mysql_188_master - Source Server Type : MySQL - Source Server Version : 50733 - Source Host : 127.0.0.1:3307 - Source Schema : seata-test-service-b - - Target Server Type : MySQL - Target Server Version : 50733 - File Encoding : 65001 - - Date: 29/04/2021 14:55:31 -*/ - -SET NAMES utf8mb4; -SET -FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for company_product --- ---------------------------- -DROP TABLE IF EXISTS `company_product`; -CREATE TABLE `company_product` -( - `id` int(11) NOT NULL, - `product_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, - `account` bigint(255) NULL DEFAULT NULL, - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of company_product --- ---------------------------- -INSERT INTO `company_product` -VALUES (1, '测试', 100); - -SET -FOREIGN_KEY_CHECKS = 1; diff --git a/mp-shadingsphere-druid-seata-tcc/doc/service-A-dev.yml b/mp-shadingsphere-druid-seata-tcc/doc/service-A-dev.yml deleted file mode 100644 index f8c72ce9f..000000000 --- a/mp-shadingsphere-druid-seata-tcc/doc/service-A-dev.yml +++ /dev/null @@ -1,126 +0,0 @@ -server: - application: - name: service-demo - port: 8070 - undertow: - io-threads: 6 - worker-threads: 48 - error: - include-exception: true - include-stacktrace: ALWAYS - include-message: ALWAYS - servlet: - context-path: / - compression: - enabled: true - min-response-size: 1024 - mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/* -management: - endpoints: - web: - exposure: - include: metrics,httptrace - health: - db: - enabled: false -spring: - swagger: - description: 'demo服务a' - termsOfServiceUrl: 'http://localhost' - version: '2.0.0' - groupName: '2.x版本' - basePackage: 'com.demo.modules' - cloud: - sentinel: - transport: - dashboard: 172.0.0.1:8858 - clientIp: 192.168.1.117 - main: - allow-bean-definition-overriding: true - servlet: - multipart: - max-file-size: 10MB - max-request-size: 10MB - #json 时间戳统一转换 - jackson: - date-format: yyyy-MM-dd HH:mm:ss - time-zone: GMT+8 - aop: - proxy-target-class: true - shardingsphere: - datasource: - names: - master,slave01,slave02 - # 主数据源 - master: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://172.0.0.1:3306/seata-test-service-a?characterEncoding=utf-8 - username: root - password: 123456 - # 从数据源 - slave01: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://172.0.0.1:3306:3306/seata-test-service-a?characterEncoding=utf-8 - username: root - password: 123456 - slave02: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://172.0.0.1:3306/seata-test-service-a?characterEncoding=utf-8 - username: root - password: 123456 - masterslave: - # 读写分离配置 - load-balance-algorithm-type: round_robin - # 最终的数据源名称 - name: dataSource - # 主库数据源名称 - master-data-source-name: master - # 从库数据源名称列表,多个逗号分隔 - slave-data-source-names: slave01,slave02 - props: - # 开启SQL显示,默认false - sql: - show: true -#mybatis plus 设置 -mybatis-plus: - mapper-locations: classpath*:com/yzs/modules/**/mapper/xml/*Mapper.xml - global-config: - # 关闭MP3.0自带的banner - banner: false - db-config: - #主键类型 - id-type: ID_WORKER_STR - # 默认数据库表下划线命名 - table-underline: true - configuration: - # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 - #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - # 返回类型为Map,显示null对应的字段 - call-setters-on-nulls: true -seata: - enabled: true - application-id: ${spring.application.name} - tx-service-group: my_test_tx_group - enable-auto-data-source-proxy: false - config: - type: nacos - nacos: - namespace: - serverAddr: 172.0.0.1:8848 - group: SEATA_GROUP - userName: "nacos" - password: "nacos" - registry: - type: nacos - nacos: - application: seata-server - server-addr: 172.0.0.1:8848 - namespace: - userName: "nacos" - password: "nacos" -ribbon: - ConnectTimeout: 5000 - ReadTimeout: 5000 \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/doc/service-B-dev.yml b/mp-shadingsphere-druid-seata-tcc/doc/service-B-dev.yml deleted file mode 100644 index 5587637e6..000000000 --- a/mp-shadingsphere-druid-seata-tcc/doc/service-B-dev.yml +++ /dev/null @@ -1,126 +0,0 @@ -server: - application: - name: service-demo - port: 8071 - undertow: - io-threads: 6 - worker-threads: 48 - error: - include-exception: true - include-stacktrace: ALWAYS - include-message: ALWAYS - servlet: - context-path: / - compression: - enabled: true - min-response-size: 1024 - mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/* -management: - endpoints: - web: - exposure: - include: metrics,httptrace - health: - db: - enabled: false -spring: - swagger: - description: 'demo服务' - termsOfServiceUrl: 'http://localhost' - version: '2.0.0' - groupName: '2.x版本' - basePackage: 'com.demo.modules' - cloud: - sentinel: - transport: - dashboard: 127.0.0.1:8858 - clientIp: 192.168.1.117 - main: - allow-bean-definition-overriding: true - servlet: - multipart: - max-file-size: 10MB - max-request-size: 10MB - #json 时间戳统一转换 - jackson: - date-format: yyyy-MM-dd HH:mm:ss - time-zone: GMT+8 - aop: - proxy-target-class: true - shardingsphere: - datasource: - names: - master,slave01,slave02 - # 主数据源 - master: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/seata-test-service-b?characterEncoding=utf-8 - username: root - password: 123456 - # 从数据源 - slave01: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/seata-test-service-b?characterEncoding=utf-8 - username: root - password: 123456 - slave02: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/seata-test-service-b?characterEncoding=utf-8 - username: root - password: 123456 - masterslave: - # 读写分离配置 - load-balance-algorithm-type: round_robin - # 最终的数据源名称 - name: dataSource - # 主库数据源名称 - master-data-source-name: master - # 从库数据源名称列表,多个逗号分隔 - slave-data-source-names: slave01,slave02 - props: - # 开启SQL显示,默认false - sql: - show: true -#mybatis plus 设置 -mybatis-plus: - mapper-locations: classpath*:com/yzs/modules/**/mapper/xml/*Mapper.xml - global-config: - # 关闭MP3.0自带的banner - banner: false - db-config: - #主键类型 - id-type: ID_WORKER_STR - # 默认数据库表下划线命名 - table-underline: true - configuration: - # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 - #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - # 返回类型为Map,显示null对应的字段 - call-setters-on-nulls: true -seata: - enabled: true - application-id: ${spring.application.name} - tx-service-group: my_test_tx_group - enable-auto-data-source-proxy: false - config: - type: nacos - nacos: - namespace: - serverAddr: 127.0.0.1:8848 - group: SEATA_GROUP - userName: "nacos" - password: "nacos" - registry: - type: nacos - nacos: - application: seata-server - server-addr: 127.0.0.1:8848 - namespace: - userName: "nacos" - password: "nacos" -ribbon: - ConnectTimeout: 5000 - ReadTimeout: 5000 \ No newline at end of file diff --git a/mp-shadingsphere-druid-seata-tcc/pom.xml b/mp-shadingsphere-druid-seata-tcc/pom.xml deleted file mode 100644 index 97cf3d6ab..000000000 --- a/mp-shadingsphere-druid-seata-tcc/pom.xml +++ /dev/null @@ -1,308 +0,0 @@ - - - 4.0.0 - - com.seata - mp-shadingsphere-druid-seata-tcc - pom - 1.0.0-SNAPSHOT - - base-starter - base-common - demo-service-A - demo-service-B - - - 通用jar包, swagger3 - - - org.springframework.boot - spring-boot-starter-parent - 2.3.5.RELEASE - - - - 2.6 - 2.0.4 - 2.0.4 - 5.3.8 - 1.9.4 - 29.0-jre - Hoxton.SR8 - 2.2.3.RELEASE - 1.0.0-SNAPSHOT - 1.0.0-SNAPSHOT - 1.0.0-SNAPSHOT - 1.0.0-SNAPSHOT - 1.2.83 - 3.4.1 - 1.1.22 - 42.2.6 - 11.2.0.3 - 4.0 - 8.0.21 - 3.2.0 - 4.0.0-RC2 - 3.7.0 - 3.13.6 - - - - aliyun - aliyun Repository - https://maven.aliyun.com/nexus/content/groups/public - - false - - - - - - - org.projectlombok - lombok - - - - com.github.xiaoymin - knife4j-spring-boot-starter - ${knife4j-spring-boot-starter.version} - - - com.github.xiaoymin - knife4j-spring-ui - ${knife4j-spring-ui.version} - - - - - - com.seata - base-common - ${base-common.version} - - - com.seata - base-jdbc-starter - ${base-jdbc-starter.version} - - - com.seata - base-core-starter - ${base-core-starter.version} - - - com.seata - base-transaction-starter - ${base-transaction-starter.version} - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - com.alibaba.cloud - spring-cloud-alibaba-dependencies - ${spring-cloud-alibaba.version} - pom - import - - - - - dom4j - dom4j - ${dom4j.version} - - - - com.auth0 - java-jwt - ${jwt.version} - - - - com.google.guava - guava - ${guava.version} - - - - - org.redisson - redisson - ${redisson.version} - - - - cn.hutool - hutool-all - ${hutool-all.version} - - - - - commons-beanutils - commons-beanutils - ${commons-beanutils.version} - - - com.squareup.okhttp3 - okhttp - 4.4.1 - - - org.apache.shardingsphere - sharding-transaction-base-seata-at - ${shardingsphere.version} - - - com.alibaba - fastjson - ${fastjson.version} - - - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - true - - - - compile - - jar - - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - - org.apache.maven.plugins - maven-resources-plugin - - - woff - woff2 - eot - ttf - svg - - - - - - - src/main/resources - true - - - src/main/java - - **/*.xml - **/*.json - **/*.ftl - - - - - - - - - dev - - - true - - - - dev - - yzs - - 127.0.0.1:8848 - - - - DEFAULT_GROUP - - 127.0.0.1:8848 - - - - - test - - - test - - yzs - - 127.0.0.1:8848 - - - - DEFAULT_GROUP - - localhost:8848 - - - - - prod - - - prod - - yzs - - 127.0.0.1:8848 - - - - DEFAULT_GROUP - - localhost:8848 - - - - \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/README.md b/multiple-datasource-mybatis-plus/README.md deleted file mode 100644 index e168f1fa3..000000000 --- a/multiple-datasource-mybatis-plus/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# Spring Cloud 使用 Seata 实现分布式事务 - 多数据源和 MyBatisPlus - -> 使用 Seata 作为分布式事务组件,使用 MySQL 数据库,使用 MyBatis 作为数据访问层实现多数据源下事务一致,使用 MyBatisPlus 作为 MyBatis 的辅助工具 - -## 环境准备 - -### 创建数据库及表 - -执行 `data.sql` - -### 启动 Seata Server - -可以直接通过bash 脚本启动 Seata Server,也可以通过 Docker 镜像启动,但是 Docker 方式目前只支持使用 file 模式,不支持将 Seata-Server 注册到 Eureka 或 Nacos 等注册中心 - -- 通过脚本启动 - -在 [Seata Release](https://github.com/seata/seata/releases) 下载相应版本的 Seata Server,解压后执行以下命令启动,这里使用 file 配置 - -```bash -sh ./bin/seata-server.sh -``` - -- 通过 Docker 启动 - -```bash -docker run --name seata-file -d -p 8091:8091 hellowoodes/seata:0.9.0-file -``` - -## 测试 - -- 启动应用 - -- 测试成功场景 - -调用 placeOrder 接口,将 price 设置为 1,此时余额为 10,可以下单成功 - -```bash -curl -X POST \ - http://localhost:8081/order/placeOrder \ - -H 'Content-Type: application/json' \ - -d '{ - "userId": 1, - "productId": 1, - "price": 1 -}' -``` - -此时返回结果为: - -```json -{"success":true,"message":null,"data":null} -``` - -- 测试失败场景 - -设置 price 为 100,此时余额不足,会下单失败,pay-service会抛出异常,事务会回滚 - -```bash -curl -X POST \ - http://localhost:8081/order/placeOrder \ - -H 'Content-Type: application/json' \ - -d '{ - "userId": 1, - "productId": 1, - "price": 100 -}' -``` - -查看 undo_log 的日志或者主键,可以看到在执行过程中有保存数据 - -如查看主键自增的值,在执行前后的值会发生变化,在执行前是 1,执行后是 5 - -```sql -SELECT - auto_increment -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = 'seata_order' - AND TABLE_NAME = 'undo_log' -``` \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/data.sql b/multiple-datasource-mybatis-plus/data.sql deleted file mode 100644 index fc53d3ab4..000000000 --- a/multiple-datasource-mybatis-plus/data.sql +++ /dev/null @@ -1,106 +0,0 @@ -# -Order -DROP -DATABASE IF EXISTS seata_order; -CREATE -DATABASE seata_order; -CREATE TABLE seata_order.orders -( - id INT(11) NOT NULL AUTO_INCREMENT, - user_id INT(11) DEFAULT NULL, - product_id INT(11) DEFAULT NULL, - pay_amount DECIMAL(10, 0) DEFAULT NULL, - status VARCHAR(100) DEFAULT NULL, - add_time DATETIME DEFAULT CURRENT_TIMESTAMP, - last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -CREATE TABLE seata_order.undo_log -( - id BIGINT(20) NOT NULL AUTO_INCREMENT, - branch_id BIGINT(20) NOT NULL, - xid VARCHAR(100) NOT NULL, - context VARCHAR(128) NOT NULL, - rollback_info LONGBLOB NOT NULL, - log_status INT(11) NOT NULL, - log_created DATETIME NOT NULL, - log_modified DATETIME NOT NULL, - PRIMARY KEY (id), - UNIQUE KEY ux_undo_log (xid, branch_id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8 -; -# -Stock -DROP -DATABASE IF EXISTS seata_stock; -CREATE -DATABASE seata_stock; -CREATE TABLE seata_stock.product -( - id INT(11) NOT NULL AUTO_INCREMENT, - price DOUBLE DEFAULT NULL, - stock INT(11) DEFAULT NULL, - last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -INSERT INTO seata_stock.product (id, price, stock) -VALUES (1, 5, 10); -CREATE TABLE seata_stock.undo_log -( - id BIGINT(20) NOT NULL AUTO_INCREMENT, - branch_id BIGINT(20) NOT NULL, - xid VARCHAR(100) NOT NULL, - context VARCHAR(128) NOT NULL, - rollback_info LONGBLOB NOT NULL, - log_status INT(11) NOT NULL, - log_created DATETIME NOT NULL, - log_modified DATETIME NOT NULL, - PRIMARY KEY (id), - UNIQUE KEY ux_undo_log (xid, branch_id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; - -# -Pay -DROP -DATABASE IF EXISTS seata_pay; -CREATE -DATABASE seata_pay; -CREATE TABLE seata_pay.account -( - id INT(11) NOT NULL AUTO_INCREMENT, - balance DOUBLE DEFAULT NULL, - last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -CREATE TABLE seata_pay.undo_log -( - id BIGINT(20) NOT NULL AUTO_INCREMENT, - branch_id BIGINT(20) NOT NULL, - xid VARCHAR(100) NOT NULL, - context VARCHAR(128) NOT NULL, - rollback_info LONGBLOB NOT NULL, - log_status INT(11) NOT NULL, - log_created DATETIME NOT NULL, - log_modified DATETIME NOT NULL, - PRIMARY KEY (id), - UNIQUE KEY ux_undo_log (xid, branch_id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -INSERT INTO seata_pay.account (id, balance) -VALUES (1, 1); - -SELECT auto_increment -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = 'seata_order' - AND TABLE_NAME = 'undo_log' \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/pom.xml b/multiple-datasource-mybatis-plus/pom.xml deleted file mode 100644 index cc50c8f21..000000000 --- a/multiple-datasource-mybatis-plus/pom.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - 4.0.0 - - io.seata - multiple-datasource-mybatis-plus - 0.0.1-SNAPSHOT - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - - 1.4.2 - UTF-8 - 1.8 - 1.8 - 1.8 - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-seata - compile - - - io.seata - seata-all - - - - - io.seata - seata-all - ${seata.version} - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-web - - - com.baomidou - mybatis-plus-boot-starter - 3.1.2 - - - mysql - mysql-connector-java - runtime - 8.0.16 - - - org.projectlombok - lombok - true - 1.18.8 - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - com.alibaba.cloud - spring-cloud-alibaba-dependencies - 2.1.0.RELEASE - import - pom - - - org.springframework.boot - spring-boot-dependencies - 2.1.5.RELEASE - import - pom - - - - diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/MultipleDatasourceMyBatisPlusApplication.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/MultipleDatasourceMyBatisPlusApplication.java deleted file mode 100644 index d53a964dd..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/MultipleDatasourceMyBatisPlusApplication.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author HelloWoodes - */ -@SpringBootApplication -@MapperScan("io.seata.samples.mutiple.mybatisplus.dao") -public class MultipleDatasourceMyBatisPlusApplication { - - public static void main(String[] args) { - SpringApplication.run(MultipleDatasourceMyBatisPlusApplication.class, args); - } - -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/OperationResponse.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/OperationResponse.java deleted file mode 100644 index 30421fad6..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/OperationResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 操作返回结果 - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class OperationResponse { - - private boolean success; - - private String message; - - private Object data; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/Order.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/Order.java deleted file mode 100644 index ec492993a..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/Order.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common.order; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -@TableName(value = "orders") -public class Order { - - @TableId(type = IdType.AUTO) - private Integer id; - - private Long userId; - - private Long productId; - - private OrderStatus status; - - private Integer payAmount; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/OrderStatus.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/OrderStatus.java deleted file mode 100644 index bb3cb73c5..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/OrderStatus.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common.order; - -/** - * 订单状态 - * - * @author HelloWoodes - */ -public enum OrderStatus { - /** - * INIT - */ - INIT, - /** - * SUCCESS - */ - SUCCESS, - /** - * FAIL - */ - FAIL -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/PlaceOrderRequestVO.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/PlaceOrderRequestVO.java deleted file mode 100644 index d253146eb..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/order/PlaceOrderRequestVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common.order; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 下单请求 VO - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class PlaceOrderRequestVO { - private Long userId; - - private Long productId; - - private Integer price; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/pay/Account.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/pay/Account.java deleted file mode 100644 index 6fa0a113f..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/pay/Account.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common.pay; - -import java.util.Date; - -import lombok.Builder; -import lombok.Data; - -/** - * @author HelloWood - */ -@Data -@Builder -public class Account { - - private Long id; - - private Integer balance; - - private Date lastUpdateTime; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/pay/ReduceBalanceRequestVO.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/pay/ReduceBalanceRequestVO.java deleted file mode 100644 index f891155a2..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/pay/ReduceBalanceRequestVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common.pay; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 扣减余额请求 VO - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class ReduceBalanceRequestVO { - - private Long userId; - - private Integer price; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/stock/Product.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/stock/Product.java deleted file mode 100644 index c6d83d780..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/stock/Product.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common.stock; - -import java.util.Date; - -import lombok.Builder; -import lombok.Data; - -/** - * @author HelloWood - */ -@Data -@Builder -public class Product { - - private Integer id; - - private Double price; - - private Integer stock; - - private Date lastUpdateTime; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/stock/ReduceStockRequestVO.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/stock/ReduceStockRequestVO.java deleted file mode 100644 index 15838faac..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/common/stock/ReduceStockRequestVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.common.stock; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 扣减库存请求 VO - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class ReduceStockRequestVO { - - private Long productId; - - private Integer amount; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DataSourceKey.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DataSourceKey.java deleted file mode 100644 index 9e99d6160..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DataSourceKey.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.config; - -import lombok.Getter; - -/** - * @author HelloWoodes - */ - -@Getter -public enum DataSourceKey { - /** - * Order data source key. - */ - ORDER, - /** - * Stock data source key. - */ - STOCK, - /** - * Pay data source key. - */ - PAY, -} \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DataSourceProxyConfig.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DataSourceProxyConfig.java deleted file mode 100644 index b4d6286de..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DataSourceProxyConfig.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.config; - -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import com.alibaba.druid.pool.DruidDataSource; - -import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; -import io.seata.rm.datasource.DataSourceProxy; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author HelloWoodes - */ -@Configuration -public class DataSourceProxyConfig { - - @Bean("originOrder") - @ConfigurationProperties(prefix = "spring.datasource.order") - public DataSource dataSourceMaster() { - return new DruidDataSource(); - } - - @Bean("originStock") - @ConfigurationProperties(prefix = "spring.datasource.stock") - public DataSource dataSourceStock() { - return new DruidDataSource(); - } - - @Bean("originPay") - @ConfigurationProperties(prefix = "spring.datasource.pay") - public DataSource dataSourcePay() { - return new DruidDataSource(); - } - - @Bean(name = "order") - public DataSourceProxy masterDataSourceProxy(@Qualifier("originOrder") DataSource dataSource) { - return new DataSourceProxy(dataSource); - } - - @Bean(name = "stock") - public DataSourceProxy stockDataSourceProxy(@Qualifier("originStock") DataSource dataSource) { - return new DataSourceProxy(dataSource); - } - - @Bean(name = "pay") - public DataSourceProxy payDataSourceProxy(@Qualifier("originPay") DataSource dataSource) { - return new DataSourceProxy(dataSource); - } - - @Bean("dynamicDataSource") - public DataSource dynamicDataSource(@Qualifier("order") DataSource dataSourceOrder, - @Qualifier("stock") DataSource dataSourceStock, - @Qualifier("pay") DataSource dataSourcePay) { - - DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource(); - - Map dataSourceMap = new HashMap<>(3); - dataSourceMap.put(DataSourceKey.ORDER.name(), dataSourceOrder); - dataSourceMap.put(DataSourceKey.STOCK.name(), dataSourceStock); - dataSourceMap.put(DataSourceKey.PAY.name(), dataSourcePay); - - dynamicRoutingDataSource.setDefaultTargetDataSource(dataSourceOrder); - dynamicRoutingDataSource.setTargetDataSources(dataSourceMap); - - DynamicDataSourceContextHolder.getDataSourceKeys().addAll(dataSourceMap.keySet()); - - return dynamicRoutingDataSource; - } - - @Bean - @ConfigurationProperties(prefix = "mybatis") - public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("dynamicDataSource") DataSource dataSource) { - // 这里用 MybatisSqlSessionFactoryBean 代替了 SqlSessionFactoryBean,否则 MyBatisPlus 不会生效 - MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); - mybatisSqlSessionFactoryBean.setDataSource(dataSource); - return mybatisSqlSessionFactoryBean; - } - -} \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DynamicDataSourceContextHolder.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DynamicDataSourceContextHolder.java deleted file mode 100644 index 2616ad17b..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DynamicDataSourceContextHolder.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.config; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author HelloWoodes - */ -public class DynamicDataSourceContextHolder { - - private static final ThreadLocal CONTEXT_HOLDER = ThreadLocal.withInitial(DataSourceKey.ORDER::name); - - private static List dataSourceKeys = new ArrayList<>(); - - public static void setDataSourceKey(DataSourceKey key) { - CONTEXT_HOLDER.set(key.name()); - } - - public static String getDataSourceKey() { - return CONTEXT_HOLDER.get(); - } - - public static void clearDataSourceKey() { - CONTEXT_HOLDER.remove(); - } - - public static List getDataSourceKeys() { - return dataSourceKeys; - } -} \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DynamicRoutingDataSource.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DynamicRoutingDataSource.java deleted file mode 100644 index a3e57f0a7..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/config/DynamicRoutingDataSource.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.config; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -/** - * @author HelloWoodes - */ -@Slf4j -public class DynamicRoutingDataSource extends AbstractRoutingDataSource { - - @Override - protected Object determineCurrentLookupKey() { - log.info("当前数据源 [{}]", DynamicDataSourceContextHolder.getDataSourceKey()); - return DynamicDataSourceContextHolder.getDataSourceKey(); - } -} \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/controller/OrderController.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/controller/OrderController.java deleted file mode 100644 index bad859930..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/controller/OrderController.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.controller; - -import io.seata.samples.mutiple.mybatisplus.common.OperationResponse; -import io.seata.samples.mutiple.mybatisplus.common.order.PlaceOrderRequestVO; -import io.seata.samples.mutiple.mybatisplus.service.OrderService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author HelloWoodes - */ -@RestController -@RequestMapping("/order") -@Slf4j -public class OrderController { - - @Autowired - private OrderService orderService; - - @PostMapping("/placeOrder") - @ResponseBody - public OperationResponse placeOrder(@RequestBody PlaceOrderRequestVO placeOrderRequestVO) throws Exception { - log.info("收到下单请求,用户:{}, 商品:{}", placeOrderRequestVO.getUserId(), placeOrderRequestVO.getProductId()); - return orderService.placeOrder(placeOrderRequestVO); - } -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/AccountDao.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/AccountDao.java deleted file mode 100644 index bb5bca9c6..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/AccountDao.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import io.seata.samples.mutiple.mybatisplus.common.pay.Account; -import org.apache.ibatis.annotations.Mapper; - -/** - * @author HelloWood - */ -@Mapper -public interface AccountDao extends BaseMapper { - -} \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/OrderDao.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/OrderDao.java deleted file mode 100644 index 92075f952..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/OrderDao.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import io.seata.samples.mutiple.mybatisplus.common.order.Order; -import org.apache.ibatis.annotations.Mapper; - -/** - * @author HelloWood - */ -@Mapper -public interface OrderDao extends BaseMapper { - -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/ProductDao.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/ProductDao.java deleted file mode 100644 index c5fb74596..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/dao/ProductDao.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import io.seata.samples.mutiple.mybatisplus.common.stock.Product; -import org.apache.ibatis.annotations.Mapper; - -/** - * @author HelloWood - */ -@Mapper -public interface ProductDao extends BaseMapper { - -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/OrderService.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/OrderService.java deleted file mode 100644 index 2b5142e77..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/OrderService.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.service; - -import io.seata.samples.mutiple.mybatisplus.common.OperationResponse; -import io.seata.samples.mutiple.mybatisplus.common.order.PlaceOrderRequestVO; - -/** - * @author HelloWoodes - */ -public interface OrderService { - - /** - * 下单 - * - * @param placeOrderRequestVO 请求参数 - * @return 下单结果 - */ - OperationResponse placeOrder(PlaceOrderRequestVO placeOrderRequestVO) throws Exception; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/PayService.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/PayService.java deleted file mode 100644 index 6a0365c9c..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/PayService.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.service; - -/** - * @author HelloWoodes - */ -public interface PayService { - /** - * @param userId 用户 ID - * @param price 扣减金额 - * @return 返回操作结果 - * @throws Exception 失败时抛出异常 - */ - boolean reduceBalance(Long userId, Integer price) throws Exception; - -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/StockService.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/StockService.java deleted file mode 100644 index 86b2ea842..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/StockService.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.service; - -/** - * @author HelloWoodes - */ -public interface StockService { - /** - * 扣减库存 - * - * @param productId 商品 ID - * @param amount 扣减数量 - * @return 操作结果 - * @throws Exception 扣减失败时抛出异常 - */ - boolean reduceStock(Long productId, Integer amount) throws Exception; -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/OrderServiceImpl.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/OrderServiceImpl.java deleted file mode 100644 index 313b9f5a3..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.mutiple.mybatisplus.common.OperationResponse; -import io.seata.samples.mutiple.mybatisplus.common.order.Order; -import io.seata.samples.mutiple.mybatisplus.common.order.OrderStatus; -import io.seata.samples.mutiple.mybatisplus.common.order.PlaceOrderRequestVO; -import io.seata.samples.mutiple.mybatisplus.config.DataSourceKey; -import io.seata.samples.mutiple.mybatisplus.config.DynamicDataSourceContextHolder; -import io.seata.samples.mutiple.mybatisplus.dao.OrderDao; -import io.seata.samples.mutiple.mybatisplus.service.OrderService; -import io.seata.samples.mutiple.mybatisplus.service.PayService; -import io.seata.samples.mutiple.mybatisplus.service.StockService; -import io.seata.spring.annotation.GlobalTransactional; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * @author HelloWoodes - */ -@Service -@Slf4j -public class OrderServiceImpl implements OrderService { - - @Autowired - private OrderDao orderDao; - - @Autowired - private PayService payService; - - @Autowired - private StockService stockService; - - @GlobalTransactional - @Override - public OperationResponse placeOrder(PlaceOrderRequestVO placeOrderRequestVO) throws Exception { - log.info("=============ORDER================="); - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.ORDER); - log.info("当前 XID: {}", RootContext.getXID()); - - Integer amount = 1; - Integer price = placeOrderRequestVO.getPrice(); - - Order order = Order.builder().userId(placeOrderRequestVO.getUserId()).productId( - placeOrderRequestVO.getProductId()).status(OrderStatus.INIT).payAmount(price).build(); - - Integer saveOrderRecord = orderDao.insert(order); - - log.info("保存订单{}", saveOrderRecord > 0 ? "成功" : "失败"); - - // 扣减库存 - boolean operationStockResult = stockService.reduceStock(placeOrderRequestVO.getProductId(), amount); - - // 扣减余额 - boolean operationBalanceResult = payService.reduceBalance(placeOrderRequestVO.getUserId(), price); - - log.info("=============ORDER================="); - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.ORDER); - - order.setStatus(OrderStatus.SUCCESS); - Integer updateOrderRecord = orderDao.updateById(order); - log.info("更新订单:{} {}", order.getId(), updateOrderRecord > 0 ? "成功" : "失败"); - - return OperationResponse.builder().success(operationStockResult && operationBalanceResult).build(); - } -} diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/PayServiceImpl.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/PayServiceImpl.java deleted file mode 100644 index 139d647da..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/PayServiceImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.mutiple.mybatisplus.common.pay.Account; -import io.seata.samples.mutiple.mybatisplus.config.DataSourceKey; -import io.seata.samples.mutiple.mybatisplus.config.DynamicDataSourceContextHolder; -import io.seata.samples.mutiple.mybatisplus.dao.AccountDao; -import io.seata.samples.mutiple.mybatisplus.service.PayService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -/** - * @author HelloWoodes - */ -@Service -@Slf4j -public class PayServiceImpl implements PayService { - - @Autowired - private AccountDao accountDao; - - /** - * 事务传播特性设置为 REQUIRES_NEW 开启新的事务 - * - * @param userId 用户 ID - * @param price 扣减金额 - * @return - * @throws Exception - */ - @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) - @Override - public boolean reduceBalance(Long userId, Integer price) throws Exception { - log.info("=============PAY================="); - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.PAY); - log.info("当前 XID: {}", RootContext.getXID()); - - checkBalance(userId, price); - - log.info("开始扣减用户 {} 余额", userId); - Account account = accountDao.selectById(userId); - - account.setBalance(account.getBalance() - price); - Integer record = accountDao.updateById(account); - log.info("扣减用户 {} 余额结果:{}", userId, record > 0 ? "操作成功" : "扣减余额失败"); - - return record > 0; - - } - - private void checkBalance(Long userId, Integer price) throws Exception { - log.info("检查用户 {} 余额", userId); - Account account = accountDao.selectById(userId); - - Integer balance = account.getBalance(); - - if (balance < price) { - log.warn("用户 {} 余额不足,当前余额:{}", userId, balance); - throw new Exception("余额不足"); - } - - } - -} - diff --git a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/StockServiceImpl.java b/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/StockServiceImpl.java deleted file mode 100644 index 70c1c0b73..000000000 --- a/multiple-datasource-mybatis-plus/src/main/java/io/seata/samples/mutiple/mybatisplus/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.mutiple.mybatisplus.common.stock.Product; -import io.seata.samples.mutiple.mybatisplus.config.DataSourceKey; -import io.seata.samples.mutiple.mybatisplus.config.DynamicDataSourceContextHolder; -import io.seata.samples.mutiple.mybatisplus.dao.ProductDao; -import io.seata.samples.mutiple.mybatisplus.service.StockService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -/** - * @author HelloWoodes - */ -@Service -@Slf4j -public class StockServiceImpl implements StockService { - - @Autowired - private ProductDao productDao; - - /** - * 事务传播特性设置为 REQUIRES_NEW 开启新的事务 - * - * @param productId 商品 ID - * @param amount 扣减数量 - * @return - * @throws Exception - */ - @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) - @Override - public boolean reduceStock(Long productId, Integer amount) throws Exception { - log.info("=============STOCK================="); - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.STOCK); - log.info("当前 XID: {}", RootContext.getXID()); - - // 检查库存 - checkStock(productId, amount); - - log.info("开始扣减 {} 库存", productId); - // 扣减库存 - Product product = productDao.selectById(productId); - product.setStock(product.getStock() - amount); - Integer record = productDao.updateById(product); - log.info("扣减 {} 库存结果:{}", productId, record > 0 ? "操作成功" : "扣减库存失败"); - - return record > 0; - - } - - private void checkStock(Long productId, Integer requiredAmount) throws Exception { - - log.info("检查 {} 库存", productId); - Product product = productDao.selectById(productId); - - if (product.getStock() < requiredAmount) { - log.warn("{} 库存不足,当前库存:{}", productId, product.getStock()); - throw new Exception("库存不足"); - } - } -} diff --git a/multiple-datasource-mybatis-plus/src/main/resources/application.properties b/multiple-datasource-mybatis-plus/src/main/resources/application.properties deleted file mode 100644 index 70bd499ea..000000000 --- a/multiple-datasource-mybatis-plus/src/main/resources/application.properties +++ /dev/null @@ -1,20 +0,0 @@ -server.port=8081 -spring.application.name=multi-datasource-service-mybatis-plus -# Order -spring.datasource.order.url=jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -spring.datasource.order.username=root -spring.datasource.order.password=123456 -spring.datasource.order.driver-class-name=com.mysql.cj.jdbc.Driver -# Stock -spring.datasource.stock.url=jdbc:mysql://localhost:3306/seata_stock?useUnicode=true&characterEncoding=utf8\ - &allowMultiQueries=true&useSSL=false -spring.datasource.stock.username=root -spring.datasource.stock.password=123456 -spring.datasource.stock.driver-class-name=com.mysql.cj.jdbc.Driver -# Pay -spring.datasource.pay.url=jdbc:mysql://localhost:3306/seata_pay?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -spring.datasource.pay.username=root -spring.datasource.pay.password=123456 -spring.datasource.pay.driver-class-name=com.mysql.cj.jdbc.Driver -# Seata -spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/src/main/resources/file.conf b/multiple-datasource-mybatis-plus/src/main/resources/file.conf deleted file mode 100644 index e38ee8290..000000000 --- a/multiple-datasource-mybatis-plus/src/main/resources/file.conf +++ /dev/null @@ -1,66 +0,0 @@ -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - # the client batch send request enable - enableClientBatchSendRequest = true - #thread factory for netty - threadFactory { - bossThreadPrefix = "NettyBoss" - workerThreadPrefix = "NettyServerNIOWorker" - serverExecutorThread-prefix = "NettyServerBizHandler" - shareBossWorker = false - clientSelectorThreadPrefix = "NettyClientSelector" - clientSelectorThreadSize = 1 - clientWorkerThreadPrefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - bossThreadSize = 1 - #auto default pin or 8 - workerThreadSize = "default" - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #transaction service group mapping - vgroupMapping.my_test_tx_group = "default" - #only support when registry.type=file, please don't set multiple addresses - default.grouplist = "127.0.0.1:8091" - #degrade, current not support - enableDegrade = false - #disable seata - disableGlobalTransaction = false -} - -client { - rm { - asyncCommitBufferLimit = 10000 - lock { - retryInterval = 10 - retryTimes = 30 - retryPolicyBranchRollbackOnConflict = true - } - reportRetryCount = 5 - tableMetaCheckEnable = false - reportSuccessEnable = false - } - tm { - commitRetryCount = 5 - rollbackRetryCount = 5 - } - undo { - dataValidation = true - logSerialization = "jackson" - logTable = "undo_log" - } - log { - exceptionRate = 100 - } -} \ No newline at end of file diff --git a/multiple-datasource-mybatis-plus/src/main/resources/registry.conf b/multiple-datasource-mybatis-plus/src/main/resources/registry.conf deleted file mode 100644 index cd2b7ac33..000000000 --- a/multiple-datasource-mybatis-plus/src/main/resources/registry.conf +++ /dev/null @@ -1,79 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "file" - - nacos { - application = "seata-server" - serverAddr = "localhost" - namespace = "" - username = "" - password = "" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - password = "" - timeout = "0" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - serverAddr = "127.0.0.1:8500" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig - type = "file" - - nacos { - serverAddr = "localhost" - namespace = "" - group = "SEATA_GROUP" - username = "" - password = "" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - appId = "seata-server" - apolloMeta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/multiple-datasource-mybatis-plus/src/test/java/io/seata/samples/mutiple/mybatisplus/MultipleDatasourceMyBatisPlusApplicationTests.java b/multiple-datasource-mybatis-plus/src/test/java/io/seata/samples/mutiple/mybatisplus/MultipleDatasourceMyBatisPlusApplicationTests.java deleted file mode 100644 index 2fb377f0d..000000000 --- a/multiple-datasource-mybatis-plus/src/test/java/io/seata/samples/mutiple/mybatisplus/MultipleDatasourceMyBatisPlusApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.seata.samples.mutiple.mybatisplus; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class MultipleDatasourceMyBatisPlusApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/multiple-datasource/README.md b/multiple-datasource/README.md deleted file mode 100644 index 1e6c6d732..000000000 --- a/multiple-datasource/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# Spring Cloud 使用 Seata 实现分布式事务 - 多数据源 - -> 使用 Seata 作为分布式事务组件,使用 MySQL 数据库,使用 MyBatis 作为数据访问层实现多数据源下事务一致 - -## 环境准备 - -### 创建数据库及表 - -执行 `data.sql` - -### 启动 Seata Server - -可以直接通过bash 脚本启动 Seata Server,也可以通过 Docker 镜像启动,但是 Docker 方式目前只支持使用 file 模式,不支持将 Seata-Server 注册到 Eureka 或 Nacos 等注册中心 - -- 通过脚本启动 - -在 [Seata Release](https://github.com/seata/seata/releases) 下载相应版本的 Seata Server,解压后执行以下命令启动,这里使用 file 配置 - -```bash -sh ./bin/seata-server.sh -``` - -- 通过 Docker 启动 - -```bash -docker run --name seata-file -d -p 8091:8091 hellowoodes/seata:0.9.0-file -``` - -## 测试 - -- 启动应用 - -- 测试成功场景 - -调用 placeOrder 接口,将 price 设置为 1,此时余额为 10,可以下单成功 - -```bash -curl -X POST \ - http://localhost:8081/order/placeOrder \ - -H 'Content-Type: application/json' \ - -d '{ - "userId": 1, - "productId": 1, - "price": 1 -}' -``` - -此时返回结果为: - -```json -{"success":true,"message":null,"data":null} -``` - -- 测试失败场景 - -设置 price 为 100,此时余额不足,会下单失败,pay-service会抛出异常,事务会回滚 - -```bash -curl -X POST \ - http://localhost:8081/order/placeOrder \ - -H 'Content-Type: application/json' \ - -d '{ - "userId": 1, - "productId": 1, - "price": 100 -}' -``` - -查看 undo_log 的日志或者主键,可以看到在执行过程中有保存数据 - -如查看主键自增的值,在执行前后的值会发生变化,在执行前是 1,执行后是 5 - -```sql -SELECT - auto_increment -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = 'seata_order' - AND TABLE_NAME = 'undo_log' -``` \ No newline at end of file diff --git a/multiple-datasource/data.sql b/multiple-datasource/data.sql deleted file mode 100644 index fc53d3ab4..000000000 --- a/multiple-datasource/data.sql +++ /dev/null @@ -1,106 +0,0 @@ -# -Order -DROP -DATABASE IF EXISTS seata_order; -CREATE -DATABASE seata_order; -CREATE TABLE seata_order.orders -( - id INT(11) NOT NULL AUTO_INCREMENT, - user_id INT(11) DEFAULT NULL, - product_id INT(11) DEFAULT NULL, - pay_amount DECIMAL(10, 0) DEFAULT NULL, - status VARCHAR(100) DEFAULT NULL, - add_time DATETIME DEFAULT CURRENT_TIMESTAMP, - last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -CREATE TABLE seata_order.undo_log -( - id BIGINT(20) NOT NULL AUTO_INCREMENT, - branch_id BIGINT(20) NOT NULL, - xid VARCHAR(100) NOT NULL, - context VARCHAR(128) NOT NULL, - rollback_info LONGBLOB NOT NULL, - log_status INT(11) NOT NULL, - log_created DATETIME NOT NULL, - log_modified DATETIME NOT NULL, - PRIMARY KEY (id), - UNIQUE KEY ux_undo_log (xid, branch_id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8 -; -# -Stock -DROP -DATABASE IF EXISTS seata_stock; -CREATE -DATABASE seata_stock; -CREATE TABLE seata_stock.product -( - id INT(11) NOT NULL AUTO_INCREMENT, - price DOUBLE DEFAULT NULL, - stock INT(11) DEFAULT NULL, - last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -INSERT INTO seata_stock.product (id, price, stock) -VALUES (1, 5, 10); -CREATE TABLE seata_stock.undo_log -( - id BIGINT(20) NOT NULL AUTO_INCREMENT, - branch_id BIGINT(20) NOT NULL, - xid VARCHAR(100) NOT NULL, - context VARCHAR(128) NOT NULL, - rollback_info LONGBLOB NOT NULL, - log_status INT(11) NOT NULL, - log_created DATETIME NOT NULL, - log_modified DATETIME NOT NULL, - PRIMARY KEY (id), - UNIQUE KEY ux_undo_log (xid, branch_id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; - -# -Pay -DROP -DATABASE IF EXISTS seata_pay; -CREATE -DATABASE seata_pay; -CREATE TABLE seata_pay.account -( - id INT(11) NOT NULL AUTO_INCREMENT, - balance DOUBLE DEFAULT NULL, - last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -CREATE TABLE seata_pay.undo_log -( - id BIGINT(20) NOT NULL AUTO_INCREMENT, - branch_id BIGINT(20) NOT NULL, - xid VARCHAR(100) NOT NULL, - context VARCHAR(128) NOT NULL, - rollback_info LONGBLOB NOT NULL, - log_status INT(11) NOT NULL, - log_created DATETIME NOT NULL, - log_modified DATETIME NOT NULL, - PRIMARY KEY (id), - UNIQUE KEY ux_undo_log (xid, branch_id) -) ENGINE = InnoDB - AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8; -INSERT INTO seata_pay.account (id, balance) -VALUES (1, 1); - -SELECT auto_increment -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = 'seata_order' - AND TABLE_NAME = 'undo_log' \ No newline at end of file diff --git a/multiple-datasource/pom.xml b/multiple-datasource/pom.xml deleted file mode 100644 index 04d7f5ec1..000000000 --- a/multiple-datasource/pom.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - 4.0.0 - - io.seata - multiple-datasource - 0.0.1-SNAPSHOT - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - - 1.4.2 - UTF-8 - 1.8 - 1.8 - 1.8 - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-seata - compile - - - io.seata - seata-all - - - - - io.seata - seata-all - ${seata.version} - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-web - - - org.mybatis.spring.boot - mybatis-spring-boot-starter - 1.3.2 - - - mysql - mysql-connector-java - runtime - 8.0.16 - - - org.projectlombok - lombok - true - 1.18.8 - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - com.alibaba.cloud - spring-cloud-alibaba-dependencies - 2.1.0.RELEASE - import - pom - - - org.springframework.boot - spring-boot-dependencies - 2.1.5.RELEASE - import - pom - - - - diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/MultipleDatasourceApplication.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/MultipleDatasourceApplication.java deleted file mode 100644 index 99fc6fcf7..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/MultipleDatasourceApplication.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.seata.samples.mutiple.datasource; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author HelloWoodes - */ -@SpringBootApplication -public class MultipleDatasourceApplication { - - public static void main(String[] args) { - SpringApplication.run(MultipleDatasourceApplication.class, args); - } - -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/OperationResponse.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/OperationResponse.java deleted file mode 100644 index a713f0f94..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/OperationResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.seata.samples.mutiple.datasource.common; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 操作返回结果 - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class OperationResponse { - - private boolean success; - - private String message; - - private Object data; -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/Order.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/Order.java deleted file mode 100644 index 5e1f8bdb0..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/Order.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.seata.samples.mutiple.datasource.common.order; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class Order { - - private Integer id; - - private Long userId; - - private Long productId; - - private OrderStatus status; - - private Integer payAmount; -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/OrderStatus.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/OrderStatus.java deleted file mode 100644 index 6e180563f..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/OrderStatus.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.seata.samples.mutiple.datasource.common.order; - -/** - * 订单状态 - * - * @author HelloWoodes - */ -public enum OrderStatus { - /** - * INIT - */ - INIT, - /** - * SUCCESS - */ - SUCCESS, - /** - * FAIL - */ - FAIL -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/PlaceOrderRequestVO.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/PlaceOrderRequestVO.java deleted file mode 100644 index c55085bec..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/order/PlaceOrderRequestVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.seata.samples.mutiple.datasource.common.order; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 下单请求 VO - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class PlaceOrderRequestVO { - private Long userId; - - private Long productId; - - private Integer price; -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/pay/ReduceBalanceRequestVO.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/pay/ReduceBalanceRequestVO.java deleted file mode 100644 index a09782ca9..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/pay/ReduceBalanceRequestVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.seata.samples.mutiple.datasource.common.pay; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 扣减余额请求 VO - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class ReduceBalanceRequestVO { - - private Long userId; - - private Integer price; -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/stock/ReduceStockRequestVO.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/stock/ReduceStockRequestVO.java deleted file mode 100644 index ac6415ed5..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/common/stock/ReduceStockRequestVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.seata.samples.mutiple.datasource.common.stock; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 扣减库存请求 VO - * - * @author HelloWoodes - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class ReduceStockRequestVO { - - private Long productId; - - private Integer amount; -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DataSourceKey.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DataSourceKey.java deleted file mode 100644 index 444266f09..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DataSourceKey.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.seata.samples.mutiple.datasource.config; - -import lombok.Getter; - -/** - * @author HelloWoodes - */ - -@Getter -public enum DataSourceKey { - /** - * Order data source key. - */ - ORDER, - /** - * Stock data source key. - */ - STOCK, - /** - * Pay data source key. - */ - PAY, -} \ No newline at end of file diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DataSourceProxyConfig.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DataSourceProxyConfig.java deleted file mode 100644 index b54b7c6dc..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DataSourceProxyConfig.java +++ /dev/null @@ -1,86 +0,0 @@ -package io.seata.samples.mutiple.datasource.config; - -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import com.alibaba.druid.pool.DruidDataSource; - -import io.seata.rm.datasource.DataSourceProxy; -import org.mybatis.spring.SqlSessionFactoryBean; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -/** - * @author HelloWoodes - */ -@Configuration -public class DataSourceProxyConfig { - - @Bean("originOrder") - @ConfigurationProperties(prefix = "spring.datasource.order") - public DataSource dataSourceMaster() { - return new DruidDataSource(); - } - - @Bean("originStock") - @ConfigurationProperties(prefix = "spring.datasource.stock") - public DataSource dataSourceStock() { - return new DruidDataSource(); - } - - @Bean("originPay") - @ConfigurationProperties(prefix = "spring.datasource.pay") - public DataSource dataSourcePay() { - return new DruidDataSource(); - } - - @Bean(name = "order") - public DataSourceProxy masterDataSourceProxy(@Qualifier("originOrder") DataSource dataSource) { - return new DataSourceProxy(dataSource); - } - - @Bean(name = "stock") - public DataSourceProxy stockDataSourceProxy(@Qualifier("originStock") DataSource dataSource) { - return new DataSourceProxy(dataSource); - } - - @Bean(name = "pay") - public DataSourceProxy payDataSourceProxy(@Qualifier("originPay") DataSource dataSource) { - return new DataSourceProxy(dataSource); - } - - @Primary - @Bean("dynamicDataSource") - public DataSource dynamicDataSource(@Qualifier("order") DataSource dataSourceOrder, - @Qualifier("stock") DataSource dataSourceStock, - @Qualifier("pay") DataSource dataSourcePay) { - - DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource(); - - Map dataSourceMap = new HashMap<>(3); - dataSourceMap.put(DataSourceKey.ORDER.name(), dataSourceOrder); - dataSourceMap.put(DataSourceKey.STOCK.name(), dataSourceStock); - dataSourceMap.put(DataSourceKey.PAY.name(), dataSourcePay); - - dynamicRoutingDataSource.setDefaultTargetDataSource(dataSourceOrder); - dynamicRoutingDataSource.setTargetDataSources(dataSourceMap); - - DynamicDataSourceContextHolder.getDataSourceKeys().addAll(dataSourceMap.keySet()); - - return dynamicRoutingDataSource; - } - - @Bean - @ConfigurationProperties(prefix = "mybatis") - public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("dynamicDataSource") DataSource dataSource) { - SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); - sqlSessionFactoryBean.setDataSource(dataSource); - return sqlSessionFactoryBean; - } - -} \ No newline at end of file diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DynamicDataSourceContextHolder.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DynamicDataSourceContextHolder.java deleted file mode 100644 index a2272c911..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DynamicDataSourceContextHolder.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.seata.samples.mutiple.datasource.config; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author HelloWoodes - */ -public class DynamicDataSourceContextHolder { - - private static final ThreadLocal CONTEXT_HOLDER = ThreadLocal.withInitial(DataSourceKey.ORDER::name); - - private static List dataSourceKeys = new ArrayList<>(); - - public static void setDataSourceKey(DataSourceKey key) { - CONTEXT_HOLDER.set(key.name()); - } - - public static String getDataSourceKey() { - return CONTEXT_HOLDER.get(); - } - - public static void clearDataSourceKey() { - CONTEXT_HOLDER.remove(); - } - - public static List getDataSourceKeys() { - return dataSourceKeys; - } -} \ No newline at end of file diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DynamicRoutingDataSource.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DynamicRoutingDataSource.java deleted file mode 100644 index 9e4959148..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/config/DynamicRoutingDataSource.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.seata.samples.mutiple.datasource.config; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -/** - * @author HelloWoodes - */ -@Slf4j -public class DynamicRoutingDataSource extends AbstractRoutingDataSource { - - @Override - protected Object determineCurrentLookupKey() { - log.info("当前数据源 [{}]", DynamicDataSourceContextHolder.getDataSourceKey()); - return DynamicDataSourceContextHolder.getDataSourceKey(); - } -} \ No newline at end of file diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/controller/OrderController.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/controller/OrderController.java deleted file mode 100644 index 42aec660b..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/controller/OrderController.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.seata.samples.mutiple.datasource.controller; - -import io.seata.samples.mutiple.datasource.common.OperationResponse; -import io.seata.samples.mutiple.datasource.common.order.PlaceOrderRequestVO; -import io.seata.samples.mutiple.datasource.service.OrderService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author HelloWoodes - */ -@RestController -@RequestMapping("/order") -@Slf4j -public class OrderController { - - @Autowired - private OrderService orderService; - - @PostMapping("/placeOrder") - @ResponseBody - public OperationResponse placeOrder(@RequestBody PlaceOrderRequestVO placeOrderRequestVO) throws Exception { - log.info("收到下单请求,用户:{}, 商品:{}", placeOrderRequestVO.getUserId(), placeOrderRequestVO.getProductId()); - return orderService.placeOrder(placeOrderRequestVO); - } -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/AccountDao.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/AccountDao.java deleted file mode 100644 index b09c81753..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/AccountDao.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.seata.samples.mutiple.datasource.dao; - -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; -import org.apache.ibatis.annotations.Update; - -/** - * @author HelloWoodes - */ -@Mapper -public interface AccountDao { - - /** - * 获取账户余额 - * - * @param userId 用户 ID - * @return 账户余额 - */ - @Select("SELECT balance FROM account WHERE id = #{userId}") - Integer getBalance(@Param("userId") Long userId); - - /** - * 扣减余额 - * - * @param price 需要扣减的数目 - * @return 影响记录行数 - */ - @Update("UPDATE account SET balance = balance - #{price} WHERE id = 1") - Integer reduceBalance(@Param("price") Integer price); -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/OrderDao.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/OrderDao.java deleted file mode 100644 index 1f296fcda..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/OrderDao.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.seata.samples.mutiple.datasource.dao; - -import io.seata.samples.mutiple.datasource.common.order.Order; -import io.seata.samples.mutiple.datasource.common.order.OrderStatus; -import org.apache.ibatis.annotations.Insert; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Options; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Update; - -/** - * @author HelloWoodes - */ -@Mapper -public interface OrderDao { - - /** - * 保存订单 - * - * @param order 订单 - * @return 影响行数 - */ - @Insert( - "INSERT INTO orders (user_id, product_id, pay_amount, status) VALUES (#{userId}, #{productId}, #{payAmount}, " - + "#{status})") - @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id") - Integer saveOrder(Order order); - - /** - * 更新订单状态 - * - * @param id 订单 ID - * @param status 状态 - * @return 影响行数 - */ - @Update("UPDATE orders SET status = #{status} WHERE id = #{id}") - Integer updateOrder(@Param("id") Integer id, @Param("status") OrderStatus status); - -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/ProductDao.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/ProductDao.java deleted file mode 100644 index fe8dd4358..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/dao/ProductDao.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.seata.samples.mutiple.datasource.dao; - -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; -import org.apache.ibatis.annotations.Update; - -/** - * @author HelloWoodes - */ -@Mapper -public interface ProductDao { - - /** - * 获取库存 - * - * @param productId 商品 ID - * @return 库存 - */ - @Select("SELECT stock FROM product WHERE id = #{productId}") - Integer getStock(@Param("productId") Long productId); - - /** - * 扣减库存 - * - * @param productId 商品 ID - * @param amount 扣减数量 - * @return 影响记录行数 - */ - @Update("UPDATE product SET stock = stock - #{amount} WHERE id = #{productId}") - Integer reduceStock(@Param("productId") Long productId, @Param("amount") Integer amount); -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/OrderService.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/OrderService.java deleted file mode 100644 index 1521623a6..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/OrderService.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.seata.samples.mutiple.datasource.service; - -import io.seata.samples.mutiple.datasource.common.OperationResponse; -import io.seata.samples.mutiple.datasource.common.order.PlaceOrderRequestVO; - -/** - * @author HelloWoodes - */ -public interface OrderService { - - /** - * 下单 - * - * @param placeOrderRequestVO 请求参数 - * @return 下单结果 - */ - OperationResponse placeOrder(PlaceOrderRequestVO placeOrderRequestVO) throws Exception; -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/PayService.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/PayService.java deleted file mode 100644 index 88d9f87ab..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/PayService.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.seata.samples.mutiple.datasource.service; - -/** - * @author HelloWoodes - */ -public interface PayService { - /** - * @param userId 用户 ID - * @param price 扣减金额 - * @return 返回操作结果 - * @throws Exception 失败时抛出异常 - */ - boolean reduceBalance(Long userId, Integer price) throws Exception; - -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/StockService.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/StockService.java deleted file mode 100644 index 4ae6cae70..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/StockService.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.seata.samples.mutiple.datasource.service; - -/** - * @author HelloWoodes - */ -public interface StockService { - /** - * 扣减库存 - * - * @param productId 商品 ID - * @param amount 扣减数量 - * @return 操作结果 - * @throws Exception 扣减失败时抛出异常 - */ - boolean reduceStock(Long productId, Integer amount) throws Exception; -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/OrderServiceImpl.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/OrderServiceImpl.java deleted file mode 100644 index 571b2fa79..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.seata.samples.mutiple.datasource.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.mutiple.datasource.common.OperationResponse; -import io.seata.samples.mutiple.datasource.common.order.Order; -import io.seata.samples.mutiple.datasource.common.order.OrderStatus; -import io.seata.samples.mutiple.datasource.common.order.PlaceOrderRequestVO; -import io.seata.samples.mutiple.datasource.config.DataSourceKey; -import io.seata.samples.mutiple.datasource.config.DynamicDataSourceContextHolder; -import io.seata.samples.mutiple.datasource.dao.OrderDao; -import io.seata.samples.mutiple.datasource.service.OrderService; -import io.seata.samples.mutiple.datasource.service.PayService; -import io.seata.samples.mutiple.datasource.service.StockService; -import io.seata.spring.annotation.GlobalTransactional; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * @author HelloWoodes - */ -@Service -@Slf4j -public class OrderServiceImpl implements OrderService { - - @Autowired - private OrderDao orderDao; - - @Autowired - private PayService payService; - - @Autowired - private StockService stockService; - - @GlobalTransactional - @Override - public OperationResponse placeOrder(PlaceOrderRequestVO placeOrderRequestVO) throws Exception { - log.info("=============ORDER================="); - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.ORDER); - log.info("当前 XID: {}", RootContext.getXID()); - - Integer amount = 1; - Integer price = placeOrderRequestVO.getPrice(); - - Order order = Order.builder().userId(placeOrderRequestVO.getUserId()).productId( - placeOrderRequestVO.getProductId()).status(OrderStatus.INIT).payAmount(price).build(); - - Integer saveOrderRecord = orderDao.saveOrder(order); - - log.info("保存订单{}", saveOrderRecord > 0 ? "成功" : "失败"); - - // 扣减库存 - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.STOCK); - boolean operationStockResult = stockService.reduceStock(placeOrderRequestVO.getProductId(), amount); - - // 扣减余额 - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.PAY); - boolean operationBalanceResult = payService.reduceBalance(placeOrderRequestVO.getUserId(), price); - - log.info("=============ORDER================="); - DynamicDataSourceContextHolder.setDataSourceKey(DataSourceKey.ORDER); - - Integer updateOrderRecord = orderDao.updateOrder(order.getId(), OrderStatus.SUCCESS); - log.info("更新订单:{} {}", order.getId(), updateOrderRecord > 0 ? "成功" : "失败"); - - return OperationResponse.builder().success(operationStockResult && operationBalanceResult).build(); - } -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/PayServiceImpl.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/PayServiceImpl.java deleted file mode 100644 index 89cc673be..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/PayServiceImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.seata.samples.mutiple.datasource.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.mutiple.datasource.dao.AccountDao; -import io.seata.samples.mutiple.datasource.service.PayService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -/** - * @author HelloWoodes - */ -@Service -@Slf4j -public class PayServiceImpl implements PayService { - - @Autowired - private AccountDao accountDao; - - /** - * 事务传播特性设置为 REQUIRES_NEW 开启新的事务 - * - * @param userId 用户 ID - * @param price 扣减金额 - * @return - * @throws Exception - */ - @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) - @Override - public boolean reduceBalance(Long userId, Integer price) throws Exception { - log.info("=============PAY================="); - log.info("当前 XID: {}", RootContext.getXID()); - - checkBalance(userId, price); - - log.info("开始扣减用户 {} 余额", userId); - Integer record = accountDao.reduceBalance(price); - log.info("扣减用户 {} 余额结果:{}", userId, record > 0 ? "操作成功" : "扣减余额失败"); - - return record > 0; - - } - - private void checkBalance(Long userId, Integer price) throws Exception { - log.info("检查用户 {} 余额", userId); - Integer balance = accountDao.getBalance(userId); - - if (balance < price) { - log.warn("用户 {} 余额不足,当前余额:{}", userId, balance); - throw new Exception("余额不足"); - } - - } - -} diff --git a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/StockServiceImpl.java b/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/StockServiceImpl.java deleted file mode 100644 index 6ef527630..000000000 --- a/multiple-datasource/src/main/java/io/seata/samples/mutiple/datasource/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.seata.samples.mutiple.datasource.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.mutiple.datasource.dao.ProductDao; -import io.seata.samples.mutiple.datasource.service.StockService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -/** - * @author HelloWoodes - */ -@Service -@Slf4j -public class StockServiceImpl implements StockService { - - @Autowired - private ProductDao productDao; - - /** - * 事务传播特性设置为 REQUIRES_NEW 开启新的事务 - * - * @param productId 商品 ID - * @param amount 扣减数量 - * @return - * @throws Exception - */ - @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) - @Override - public boolean reduceStock(Long productId, Integer amount) throws Exception { - log.info("=============STOCK================="); - log.info("当前 XID: {}", RootContext.getXID()); - - // 检查库存 - checkStock(productId, amount); - - log.info("开始扣减 {} 库存", productId); - // 扣减库存 - Integer record = productDao.reduceStock(productId, amount); - log.info("扣减 {} 库存结果:{}", productId, record > 0 ? "操作成功" : "扣减库存失败"); - - return record > 0; - - } - - private void checkStock(Long productId, Integer requiredAmount) throws Exception { - - log.info("检查 {} 库存", productId); - Integer stock = productDao.getStock(productId); - - if (stock < requiredAmount) { - log.warn("{} 库存不足,当前库存:{}", productId, stock); - throw new Exception("库存不足"); - } - } -} diff --git a/multiple-datasource/src/main/resources/application.properties b/multiple-datasource/src/main/resources/application.properties deleted file mode 100644 index 0d40d0ff9..000000000 --- a/multiple-datasource/src/main/resources/application.properties +++ /dev/null @@ -1,19 +0,0 @@ -server.port=8081 -spring.application.name=multi-datasource-service -# Order -spring.datasource.order.url=jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -spring.datasource.order.username=root -spring.datasource.order.password=123456 -spring.datasource.order.driver-class-name=com.mysql.cj.jdbc.Driver -# Stock -spring.datasource.stock.url=jdbc:mysql://localhost:3306/seata_stock?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -spring.datasource.stock.username=root -spring.datasource.stock.password=123456 -spring.datasource.stock.driver-class-name=com.mysql.cj.jdbc.Driver -# Pay -spring.datasource.pay.url=jdbc:mysql://localhost:3306/seata_pay?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -spring.datasource.pay.username=root -spring.datasource.pay.password=123456 -spring.datasource.pay.driver-class-name=com.mysql.cj.jdbc.Driver -# Seata -spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group \ No newline at end of file diff --git a/multiple-datasource/src/main/resources/file.conf b/multiple-datasource/src/main/resources/file.conf deleted file mode 100644 index e38ee8290..000000000 --- a/multiple-datasource/src/main/resources/file.conf +++ /dev/null @@ -1,66 +0,0 @@ -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - # the client batch send request enable - enableClientBatchSendRequest = true - #thread factory for netty - threadFactory { - bossThreadPrefix = "NettyBoss" - workerThreadPrefix = "NettyServerNIOWorker" - serverExecutorThread-prefix = "NettyServerBizHandler" - shareBossWorker = false - clientSelectorThreadPrefix = "NettyClientSelector" - clientSelectorThreadSize = 1 - clientWorkerThreadPrefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - bossThreadSize = 1 - #auto default pin or 8 - workerThreadSize = "default" - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #transaction service group mapping - vgroupMapping.my_test_tx_group = "default" - #only support when registry.type=file, please don't set multiple addresses - default.grouplist = "127.0.0.1:8091" - #degrade, current not support - enableDegrade = false - #disable seata - disableGlobalTransaction = false -} - -client { - rm { - asyncCommitBufferLimit = 10000 - lock { - retryInterval = 10 - retryTimes = 30 - retryPolicyBranchRollbackOnConflict = true - } - reportRetryCount = 5 - tableMetaCheckEnable = false - reportSuccessEnable = false - } - tm { - commitRetryCount = 5 - rollbackRetryCount = 5 - } - undo { - dataValidation = true - logSerialization = "jackson" - logTable = "undo_log" - } - log { - exceptionRate = 100 - } -} \ No newline at end of file diff --git a/multiple-datasource/src/main/resources/registry.conf b/multiple-datasource/src/main/resources/registry.conf deleted file mode 100644 index cd2b7ac33..000000000 --- a/multiple-datasource/src/main/resources/registry.conf +++ /dev/null @@ -1,79 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "file" - - nacos { - application = "seata-server" - serverAddr = "localhost" - namespace = "" - username = "" - password = "" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - password = "" - timeout = "0" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - serverAddr = "127.0.0.1:8500" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig - type = "file" - - nacos { - serverAddr = "localhost" - namespace = "" - group = "SEATA_GROUP" - username = "" - password = "" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - appId = "seata-server" - apolloMeta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/multiple-datasource/src/test/java/io/seata/samples/mutiple/datasource/MultipleDatasourceApplicationTests.java b/multiple-datasource/src/test/java/io/seata/samples/mutiple/datasource/MultipleDatasourceApplicationTests.java deleted file mode 100644 index eae4f6282..000000000 --- a/multiple-datasource/src/test/java/io/seata/samples/mutiple/datasource/MultipleDatasourceApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.seata.samples.mutiple.datasource; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class MultipleDatasourceApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/nacos/Readme.md b/nacos/Readme.md deleted file mode 100644 index c955e7425..000000000 --- a/nacos/Readme.md +++ /dev/null @@ -1,380 +0,0 @@ -# 基于 Seata 解决微服务架构下数据一致性的实践 - -[Seata](https://github.com/seata/seata) 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务。 - -随着业务的快速发展,应用单体架构暴露出代码可维护性差,容错率低,测试难度大,敏捷交付能力差等诸多问题,微服务应运而生。微服务的诞生一方面解决了上述问题,但是另一方面却引入新的问题,其中主要问题之一就是如何保证微服务间的业务数据一致性。 - -本文将通过一个简单的微服务架构的例子,说明业务如何step by step的使用 Seata、Dubbo 和 Nacos 来保证业务数据的一致性。本文所述的例子中 Dubbo 和 Seata 注册配置服务中心均使用 Nacos。Seata -0.2.1+ 开始支持 Nacos 注册配置服务中心。 - -## 业务案例 - -用户采购商品业务,整个业务包含3个微服务: - -- 库存服务: 扣减给定商品的库存数量。 -- 订单服务: 根据采购请求生成订单。 -- 账户服务: 用户账户金额扣减。 - -### 业务结构图 - - - -#### StockService - -```java -public interface StockService { - /** - * deduct stock count - */ - void deduct(String commodityCode, int count); -} -``` - -#### OrderService - -```java -public interface OrderService { - /** - * create order - */ - Order create(String userId, String commodityCode, int orderCount); -} -``` - -#### AccountService - -```java -public interface AccountService { - /** - * debit balance of user's account - */ - void debit(String userId, int money); -} -``` - -**说明:** 以上三个微服务独立部署。 - -### Seata、Dubbo和Nacos 集成 - -#### Step 1 初始化 MySQL 数据库(需要InnoDB 存储引擎) - -在 [resources/jdbc.properties](https://github.com/seata/seata-samples/blob/master/nacos/src/main/resources/jdbc. -properties) 修改StockService、OrderService、AccountService 对应的连接信息。 - -```properties -jdbc.account.url=jdbc:mysql://xxxx/xxxx -jdbc.account.username=xxxx -jdbc.account.password=xxxx -jdbc.account.driver=com.mysql.jdbc.Driver -# stock db config -jdbc.stock.url=jdbc:mysql://xxxx/xxxx -jdbc.stock.username=xxxx -jdbc.stock.password=xxxx -jdbc.stock.driver=com.mysql.jdbc.Driver -# order db config -jdbc.order.url=jdbc:mysql://xxxx/xxxx -jdbc.order.username=xxxx -jdbc.order.password=xxxx -jdbc.order.driver=com.mysql.jdbc.Driver -``` - -#### Step 2 创建 undo_log(用于 Seata AT 模式)表和相关业务表 - -相关建表脚本可在 [resources/sql/](https://github.com/seata/seata-samples/tree/master/nacos/src/main/resources/sql) -下获取,在相应数据库中执行 [dubbo_biz.sql](https://github.com/seata/seata-samples/blob/master/nacos/src/main/resources/sql/dubbo_biz.sql) -中的业务建表脚本,在每个数据库执行 [undo_log.sql](https://github.com/seata/seata-samples/blob/master/nacos/src/main/resources/sql/undo_log.sql) -建表脚本。 - -```sql --- 注意此处0.3.0+ 增加唯一索引 ux_undo_log -CREATE TABLE `undo_log` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `branch_id` bigint(20) NOT NULL, - `xid` varchar(100) NOT NULL, - `context` varchar(128) NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int(11) NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - `ext` varchar(100) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -``` - -```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; -``` - -**说明:** 需要保证每个物理库都包含 undo_log 表,此处可使用一个物理库来表示上述三个微服务对应的独立逻辑库。 - -#### Step 3 引入 Seata、Dubbo 和 Nacos 相关 POM 依赖 - -```xml - - x.x.x - 1.0.0 - 2.6.5 - 0.0.2 - - - - io.seata - seata-all - ${seata.version} - - - com.alibaba.nacos - nacos-client - ${nacos-client.version} - - - com.alibaba - dubbo - ${dubbo.alibaba.version} - - - com.alibaba - dubbo-registry-nacos - ${dubbo.registry.nacos.version} - -``` - -**说明:** 由于当前 apache-dubbo 与 dubbo-registry-nacos jar存在兼容性问题,需要手动引入 alibaba-dubbo,后续 apache-dubbo(2.7.1+) 将兼容 -dubbo-registry-nacos。在 Seata 中 seata-dubbo jar 支持 apache.dubbo,seata-dubbo-alibaba jar 支持 alibaba-dubbo。 - -#### Step 4 微服务 Provider Spring配置 - -分别在三个微服务Spring配置文件([dubbo-account-service.xml](https://github.com/seata/seata-samples/blob/master/nacos/src/main/resources/spring/dubbo-account-service.xml)、 -[dubbo-order-service](https://github.com/seata/seata-samples/blob/master/nacos/src/main/resources/spring/dubbo-order-service.xml) -和 -[dubbo-stock-service.xml](https://github.com/seata/seata-samples/blob/master/nacos/src/main/resources/spring/dubbo-stock-service.xml) -)进行如下配置: - -- 配置 Seata 代理数据源 - -```xml - - - - - - - -``` - -此处需要使用 io.seata.rm.datasource.DataSourceProxy 包装 Druid 数据源作为直接业务数据源,DataSourceProxy 用于业务 sql 的拦截解析并与 TC 交互协调事务操作状态。 - -- 配置 Dubbo 注册中心 - -```xml - -``` - -- 配置 Seata GlobalTransactionScanner - -```xml - - - - -``` - -此处构造方法的第一个参数为业务自定义 applicationId,若在单机部署多微服务需要保证 applicationId 唯一。 -构造方法的第二个参数为 Seata 事务服务逻辑分组,此分组通过配置中心配置项 service.vgroup_mapping.my_test_tx_group 映射到相应的 Seata-Server -集群名称,然后再根据集群名称.grouplist 获取到可用服务列表。 - -#### Step 5 事务发起方配置 - -在 [dubbo-business.xml](https://github.com/seata/seata-samples/blob/master/nacos/src/main/resources/spring/dubbo-business.xml) -配置以下配置: - -- 配置 Dubbo 注册中心 - -同 Step 4 - -- 配置 Seata GlobalTransactionScanner - -同 Step 4 - -- 在事务发起方 service 方法上添加 @GlobalTransactional 注解 - -```java -@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") -``` - -timeoutMills 为事务的总体超时时间默认60s,name 为事务方法签名的别名,默认为空。注解内参数均可省略。 - -#### Step 6 启动 Nacos-Server - -- 下载 Nacos-Server 最新 [release](https://github.com/alibaba/nacos/releases) 包并解压 - -- 运行 Nacos-server - -**Linux/Unix/Mac** - -```bash -sh startup.sh -m standalone -``` - -**Windows** - -```bash -cmd startup.cmd -m standalone -``` - -访问 Nacos 控制台:http://localhost:8848/nacos/index.html#/configurationManagement?dataId=&group=&appName=&namespace= - -若访问成功说明 Nacos-Server 服务运行成功(默认账号/密码: nacos/nacos) - -#### Step 7 启动 Seata-Server - -- 下载 Seata-Server 最新 [release](https://github.com/seata/seata/releases) 包并解压 - -- 初始化 Seata 配置 - -进入到 Seata-Server 解压目录 conf -文件夹下,确认 [nacos-config.txt](https://github.com/seata/seata/blob/develop/server/src/main/resources/nacos-config.txt) -的配置值(一般不需要修改),确认完成后运行 [nacos-config.sh](https://github.com/seata/seata/blob/develop/server/src/main/resources/nacos-config.sh) -脚本初始化配置。 - -```bash -sh nacos-config.sh $Nacos-Server-IP -``` - -**eg**: - -```bash - -sh nacos-config.sh localhost - -``` - -脚本执行最后输出 "**init nacos config finished, please start Seata-server.**" 说明推送配置成功。若想进一步确认可登陆Nacos 控制台 配置列表 筛选 -Group=SEATA_GROUP 的配置项。 - - - -- 修改 Seata-server 服务注册方式为 nacos - -进入到 Seata-Server 解压目录 conf -文件夹下 [registry.conf](https://github.com/seata/seata/blob/develop/server/src/main/resources/registry.conf) 修改 type=" -nacos" 并配置 Nacos 的相关属性。 - -```properties -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - serverAddr = "localhost" - namespace = "" - cluster = "default" - } -} - -config { - # file、nacos 、apollo、zk - type = "nacos" - - nacos { - serverAddr = "localhost" - namespace = "" - } -} - - -``` - -**type**: 可配置为注释中的类型,此处选择nacos类型,配置为 file 时无服务注册功能 -**nacos.serverAddr**: Nacos-Sever 服务地址(不含端口号) -**nacos.namespace**: Nacos 注册和配置隔离 namespace -**nacos.cluster**: 注册服务的集群名称 - -- 运行 Seata-server - -**Linux/Unix/Mac** - -```bash -sh seata-server.sh -p $LISTEN_PORT -m $STORE_MODE -h $IP(此参数可选) -``` - -**Windows** - -```bash -cmd seata-server.bat -p $LISTEN_PORT -m $STORE_MODE -h $IP(此参数可选) - -``` - -**$LISTEN_PORT**: Seata-Server 服务端口 -**$STORE_MODE**: 事务操作记录存储模式:file、db -**$IP(可选参数)**: 用于多 IP 环境下指定 Seata-Server 注册服务的IP - -**eg**: -sh seata-server.sh -p 8091 -m file - -运行成功后可在 Nacos 控制台看到 服务名 =serverAddr 服务注册列表: - - - -#### Step 8 启动微服务并测试 - -- 修改业务客户端发现注册方式为 nacos - 同Step 7 中[修改 Seata-server 服务注册方式为 nacos] 步骤 -- - -启动 [DubboAccountServiceStarter](https://github.com/seata/seata-samples/blob/master/nacos/src/main/java/io/seata/samples/nacos/starter/DubboAccountServiceStarter.java) -- -启动 [DubboOrderServiceStarter](https://github.com/seata/seata-samples/blob/master/nacos/src/main/java/io/seata/samples/nacos/starter/DubboOrderServiceStarter.java) -- -启动 [DubboStockServiceStarter](https://github.com/seata/seata-samples/blob/master/nacos/src/main/java/io/seata/samples/nacos/starter/DubboStockServiceStarter.java) - -启动完成可在 Nacos 控制台服务列表 看到启动完成的三个 provider - - - -- - -启动 [DubboBusinessTester](https://github.com/seata/seata-samples/blob/master/nacos/src/main/java/io/seata/samples/nacos/starter/DubboBusinessTester.java) -进行测试 - -**注意:** 在标注 @GlobalTransactional 注解方法内部显示的抛出异常才会进行事务的回滚。整个 Dubbo 服务调用链路只需要在事务最开始发起方的 service 方法标注注解即可。 - -## 相关链接: - -本文 sample 地址: https://github.com/seata/seata-samples/tree/master/nacos -Seata: https://github.com/seata/seata -Dubbo: https://github.com/apache/incubator-dubbo -Nacos: https://github.com/alibaba/nacos - - - - - diff --git a/nacos/pom.xml b/nacos/pom.xml deleted file mode 100644 index 78759e6af..000000000 --- a/nacos/pom.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - io.seata - seata-samples - 1.1.0 - - 4.0.0 - seata-samples-nacos - seata-samples-nacos ${project.version} - - 2.6.5 - 0.0.2 - 1.0.0 - - - - - io.seata - seata-all - ${seata.version} - - - com.alibaba.nacos - nacos-client - ${nacos-client.version} - - - com.alibaba - dubbo - ${dubbo.alibaba.version} - - - com.alibaba - dubbo-registry-nacos - ${dubbo.registry.nacos.version} - - - com.alibaba.spring - spring-context-support - - - com.101tec - zkclient - - - slf4j-log4j12 - org.slf4j - - - log4j - log4j - - - - - junit - junit - test - - - org.springframework - spring-jdbc - - - ch.qos.logback - logback-classic - - - mysql - mysql-connector-java - - - org.apache.curator - curator-recipes - - - - - - - mysql - mysql-connector-java - 8.0.28 - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - - \ No newline at end of file diff --git a/nacos/src/main/java/io/seata/samples/nacos/ApplicationKeeper.java b/nacos/src/main/java/io/seata/samples/nacos/ApplicationKeeper.java deleted file mode 100644 index a45e71416..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/ApplicationKeeper.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos; - -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.support.AbstractApplicationContext; - -/** - * The type Application keeper. - */ -public class ApplicationKeeper { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationKeeper.class); - - private final ReentrantLock LOCK = new ReentrantLock(); - private final Condition STOP = LOCK.newCondition(); - - /** - * Instantiates a new Application keeper. - * - * @param applicationContext the application context - */ - public ApplicationKeeper(AbstractApplicationContext applicationContext) { - addShutdownHook(applicationContext); - } - - private void addShutdownHook(final AbstractApplicationContext applicationContext) { - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { - @Override - public void run() { - try { - applicationContext.close(); - LOGGER.info("ApplicationContext " + applicationContext + " is closed."); - } catch (Exception e) { - LOGGER.error("Failed to close ApplicationContext", e); - } - - try { - LOCK.lock(); - STOP.signal(); - } finally { - LOCK.unlock(); - } - } - })); - } - - /** - * Keep. - */ - public void keep() { - synchronized (LOCK) { - try { - LOGGER.info("Application is keep running ... "); - LOCK.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/Order.java b/nacos/src/main/java/io/seata/samples/nacos/Order.java deleted file mode 100644 index 348692134..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/Order.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos; - -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/nacos/src/main/java/io/seata/samples/nacos/service/AccountService.java b/nacos/src/main/java/io/seata/samples/nacos/service/AccountService.java deleted file mode 100644 index a2d0217c5..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/AccountService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -/** - * The interface Account service. - */ -public interface AccountService { - - /** - * 余额扣款 - * - * @param userId 用户ID - * @param money 扣款金额 - */ - void debit(String userId, int money); -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/service/BusinessService.java b/nacos/src/main/java/io/seata/samples/nacos/service/BusinessService.java deleted file mode 100644 index 248405eaf..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/BusinessService.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -/** - * The interface Business service. - */ -public interface BusinessService { - - /** - * 用户订购商品 - * - * @param userId 用户ID - * @param commodityCode 商品编号 - * @param orderCount 订购数量 - */ - void purchase(String userId, String commodityCode, int orderCount); -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/service/OrderService.java b/nacos/src/main/java/io/seata/samples/nacos/service/OrderService.java deleted file mode 100644 index a5491859a..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/OrderService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -import io.seata.samples.nacos.Order; - -/** - * The interface Order service. - */ -public interface OrderService { - /** - * 创建订单 - * - * @param userId 用户ID - * @param commodityCode 商品编号 - * @param orderCount 订购数量 - * @return 生成的订单 order - */ - Order create(String userId, String commodityCode, int orderCount); -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/service/StockService.java b/nacos/src/main/java/io/seata/samples/nacos/service/StockService.java deleted file mode 100644 index c1d98e889..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/StockService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service; - -/** - * The interface Stock service. - */ -public interface StockService { - - /** - * 扣减库存 - * - * @param commodityCode 商品编号 - * @param count 扣减数量 - */ - void deduct(String commodityCode, int count); -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/service/impl/AccountServiceImpl.java b/nacos/src/main/java/io/seata/samples/nacos/service/impl/AccountServiceImpl.java deleted file mode 100644 index 2c7ac1555..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.service.AccountService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Account service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class AccountServiceImpl implements AccountService { - - private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); - - private JdbcTemplate jdbcTemplate; - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(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/nacos/src/main/java/io/seata/samples/nacos/service/impl/BusinessServiceImpl.java b/nacos/src/main/java/io/seata/samples/nacos/service/impl/BusinessServiceImpl.java deleted file mode 100644 index 3d49b4613..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/impl/BusinessServiceImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.service.BusinessService; -import io.seata.samples.nacos.service.OrderService; -import io.seata.samples.nacos.service.StockService; -import io.seata.spring.annotation.GlobalTransactional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Business service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class BusinessServiceImpl implements BusinessService { - - private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); - - private StockService stockService; - private OrderService orderService; - - @Override - @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") - public void purchase(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("xxx"); - } - - /** - * Sets stock service. - * - * @param stockService the stock service - */ - public void setStockService(StockService stockService) { - this.stockService = stockService; - } - - /** - * Sets order service. - * - * @param orderService the order service - */ - public void setOrderService(OrderService orderService) { - this.orderService = orderService; - } - -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/service/impl/OrderServiceImpl.java b/nacos/src/main/java/io/seata/samples/nacos/service/impl/OrderServiceImpl.java deleted file mode 100644 index 95722c5af..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.Order; -import io.seata.samples.nacos.service.AccountService; -import io.seata.samples.nacos.service.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; - -/** - * The type Order service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class OrderServiceImpl implements OrderService { - - private static final Logger LOGGER = LoggerFactory.getLogger(OrderService.class); - - private AccountService accountService; - - private 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; - } - - /** - * Sets account service. - * - * @param accountService the account service - */ - public void setAccountService(AccountService accountService) { - this.accountService = accountService; - } - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - private int calculate(String commodityId, int orderCount) { - return 200 * orderCount; - } - -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/service/impl/StockServiceImpl.java b/nacos/src/main/java/io/seata/samples/nacos/service/impl/StockServiceImpl.java deleted file mode 100644 index 19145846a..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.service.impl; - -import io.seata.core.context.RootContext; -import io.seata.samples.nacos.service.StockService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Stock service. - * - * @author jimin.jm @alibaba-inc.com - */ -public class StockServiceImpl implements StockService { - - private static final Logger LOGGER = LoggerFactory.getLogger(StockService.class); - - private JdbcTemplate jdbcTemplate; - - /** - * Sets jdbc template. - * - * @param jdbcTemplate the jdbc template - */ - public void setJdbcTemplate(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 ... "); - - } - -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboAccountServiceStarter.java b/nacos/src/main/java/io/seata/samples/nacos/starter/DubboAccountServiceStarter.java deleted file mode 100644 index 887b497c6..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboAccountServiceStarter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Dubbo account service starter. - */ -public class DubboAccountServiceStarter { - /** - * 2. Account service is ready . A buyer register an account: U100001 on my e-commerce platform - * - * @param args the input arguments - */ - public static void main(String[] args) { - ClassPathXmlApplicationContext accountContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-account-service.xml"}); - accountContext.getBean("service"); - JdbcTemplate accountJdbcTemplate = (JdbcTemplate)accountContext.getBean("jdbcTemplate"); - accountJdbcTemplate.update("delete from account_tbl where user_id = 'U100001'"); - accountJdbcTemplate.update("insert into account_tbl(user_id, money) values ('U100001', 999)"); - - new ApplicationKeeper(accountContext).keep(); - } -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboBusinessTester.java b/nacos/src/main/java/io/seata/samples/nacos/starter/DubboBusinessTester.java deleted file mode 100644 index 575e50d60..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboBusinessTester.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.service.BusinessService; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * The type Dubbo business tester. - */ -public class DubboBusinessTester { - /** - * The entry point of application. - * - * @param args the input arguments - */ - public static void main(String[] args) { - /** - * 4. The whole e-commerce platform is ready , The buyer(U100001) create an order on the sku(C00321) , the - * count is 2 - */ - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-business.xml"}); - final BusinessService business = (BusinessService)context.getBean("business"); - business.purchase("U100001", "C00321", 2); - } -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboOrderServiceStarter.java b/nacos/src/main/java/io/seata/samples/nacos/starter/DubboOrderServiceStarter.java deleted file mode 100644 index c3f86163f..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboOrderServiceStarter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * The type Dubbo order service starter. - */ -public class DubboOrderServiceStarter { - /** - * The entry point of application. - * - * @param args the input arguments - */ - public static void main(String[] args) { - /** - * 3. Order service is ready . Waiting for buyers to order - */ - ClassPathXmlApplicationContext orderContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-order-service.xml"}); - orderContext.getBean("service"); - new ApplicationKeeper(orderContext).keep(); - } -} diff --git a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboStockServiceStarter.java b/nacos/src/main/java/io/seata/samples/nacos/starter/DubboStockServiceStarter.java deleted file mode 100644 index 1cd2bf76e..000000000 --- a/nacos/src/main/java/io/seata/samples/nacos/starter/DubboStockServiceStarter.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2021 Seata.io Group. - * - * Licensed 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 io.seata.samples.nacos.starter; - -import io.seata.samples.nacos.ApplicationKeeper; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * The type Dubbo stock service starter. - */ -public class DubboStockServiceStarter { - /** - * 1. Stock service is ready . A seller add 100 stock to a sku: C00321 - * - * @param args the input arguments - */ - public static void main(String[] args) { - ClassPathXmlApplicationContext stockContext = new ClassPathXmlApplicationContext( - new String[] {"spring/dubbo-storage-service.xml"}); - stockContext.getBean("service"); - JdbcTemplate stockJdbcTemplate = (JdbcTemplate)stockContext.getBean("jdbcTemplate"); - stockJdbcTemplate.update("delete from stock_tbl where commodity_code = 'C00321'"); - stockJdbcTemplate.update("insert into stock_tbl(commodity_code, count) values ('C00321', 100)"); - new ApplicationKeeper(stockContext).keep(); - } -} diff --git a/nacos/src/main/resources/file.conf b/nacos/src/main/resources/file.conf deleted file mode 100644 index e38ee8290..000000000 --- a/nacos/src/main/resources/file.conf +++ /dev/null @@ -1,66 +0,0 @@ -transport { - # tcp udt unix-domain-socket - type = "TCP" - #NIO NATIVE - server = "NIO" - #enable heartbeat - heartbeat = true - # the client batch send request enable - enableClientBatchSendRequest = true - #thread factory for netty - threadFactory { - bossThreadPrefix = "NettyBoss" - workerThreadPrefix = "NettyServerNIOWorker" - serverExecutorThread-prefix = "NettyServerBizHandler" - shareBossWorker = false - clientSelectorThreadPrefix = "NettyClientSelector" - clientSelectorThreadSize = 1 - clientWorkerThreadPrefix = "NettyClientWorkerThread" - # netty boss thread size,will not be used for UDT - bossThreadSize = 1 - #auto default pin or 8 - workerThreadSize = "default" - } - shutdown { - # when destroy server, wait seconds - wait = 3 - } - serialization = "seata" - compressor = "none" -} -service { - #transaction service group mapping - vgroupMapping.my_test_tx_group = "default" - #only support when registry.type=file, please don't set multiple addresses - default.grouplist = "127.0.0.1:8091" - #degrade, current not support - enableDegrade = false - #disable seata - disableGlobalTransaction = false -} - -client { - rm { - asyncCommitBufferLimit = 10000 - lock { - retryInterval = 10 - retryTimes = 30 - retryPolicyBranchRollbackOnConflict = true - } - reportRetryCount = 5 - tableMetaCheckEnable = false - reportSuccessEnable = false - } - tm { - commitRetryCount = 5 - rollbackRetryCount = 5 - } - undo { - dataValidation = true - logSerialization = "jackson" - logTable = "undo_log" - } - log { - exceptionRate = 100 - } -} \ No newline at end of file diff --git a/nacos/src/main/resources/jdbc.properties b/nacos/src/main/resources/jdbc.properties deleted file mode 100644 index 7d2f07fa6..000000000 --- a/nacos/src/main/resources/jdbc.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 1999-2018 Alibaba Group Holding Ltd. -# -# Licensed 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. -# -# account db config -jdbc.account.url=jdbc:mysql://localhost:3306/seata_pay?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -jdbc.account.username=root -jdbc.account.password=123456 -jdbc.account.driver=com.mysql.cj.jdbc.Driver -# stock db config -jdbc.stock.url=jdbc:mysql://localhost:3306/seata_stock?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -jdbc.stock.username=root -jdbc.stock.password=123456 -jdbc.stock.driver=com.mysql.cj.jdbc.Driver -# order db config -jdbc.order.url=jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false -jdbc.order.username=root -jdbc.order.password=123456 -jdbc.order.driver=com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/nacos/src/main/resources/logback.xml b/nacos/src/main/resources/logback.xml deleted file mode 100644 index b5070753d..000000000 --- a/nacos/src/main/resources/logback.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n - - - - - - - - diff --git a/nacos/src/main/resources/registry.conf b/nacos/src/main/resources/registry.conf deleted file mode 100644 index 0c46e26a1..000000000 --- a/nacos/src/main/resources/registry.conf +++ /dev/null @@ -1,89 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - application = "seata-server" - serverAddr = "127.0.0.1:8848" - group = "SEATA_GROUP" - namespace = "" - cluster = "default" - username = "nacos" - password = "nacos" - } - eureka { - serviceUrl = "http://localhost:8761/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = 0 - password = "" - cluster = "default" - timeout = 0 - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul、etcd3 - type = "nacos" - - nacos { - serverAddr = "127.0.0.1:8848" - namespace = "" - group = "SEATA_GROUP" - username = "nacos" - password = "nacos" - dataId = "seataServer.properties" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - appId = "seata-server" - apolloMeta = "http://192.168.1.204:8801" - namespace = "application" - } - zk { - serverAddr = "127.0.0.1:2181" - sessionTimeout = 6000 - connectTimeout = 2000 - username = "" - password = "" - } - etcd3 { - serverAddr = "http://localhost:2379" - } - file { - name = "file.conf" - } -} diff --git a/nacos/src/main/resources/spring/dubbo-account-service.xml b/nacos/src/main/resources/spring/dubbo-account-service.xml deleted file mode 100644 index 26892fc71..000000000 --- a/nacos/src/main/resources/spring/dubbo-account-service.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/nacos/src/main/resources/spring/dubbo-business.xml b/nacos/src/main/resources/spring/dubbo-business.xml deleted file mode 100644 index 8fd9e15fe..000000000 --- a/nacos/src/main/resources/spring/dubbo-business.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/nacos/src/main/resources/spring/dubbo-order-service.xml b/nacos/src/main/resources/spring/dubbo-order-service.xml deleted file mode 100644 index cf1830447..000000000 --- a/nacos/src/main/resources/spring/dubbo-order-service.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/nacos/src/main/resources/spring/dubbo-storage-service.xml b/nacos/src/main/resources/spring/dubbo-storage-service.xml deleted file mode 100644 index 359abf734..000000000 --- a/nacos/src/main/resources/spring/dubbo-storage-service.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/nacos/src/main/resources/sql/dubbo_biz.sql b/nacos/src/main/resources/sql/dubbo_biz.sql deleted file mode 100644 index 3a97410c2..000000000 --- a/nacos/src/main/resources/sql/dubbo_biz.sql +++ /dev/null @@ -1,31 +0,0 @@ -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; \ No newline at end of file diff --git a/nacos/src/main/resources/sql/undo_log.sql b/nacos/src/main/resources/sql/undo_log.sql deleted file mode 100644 index 8ee88ab1e..000000000 --- a/nacos/src/main/resources/sql/undo_log.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 注意此处0.3.0+ 增加唯一索引 ux_undo_log -CREATE TABLE `undo_log` -( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `branch_id` bigint(20) NOT NULL, - `xid` varchar(100) NOT NULL, - `context` varchar(128) NOT NULL, - `rollback_info` longblob NOT NULL, - `log_status` int(11) NOT NULL, - `log_created` datetime NOT NULL, - `log_modified` datetime NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/.gitignore b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/.gitignore deleted file mode 100644 index b83d22266..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/pom.xml b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/pom.xml deleted file mode 100644 index d78fd9385..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - 4.0.0 - - io.seata - nutzboot-dubbo-seata - 1.1.0 - - nutzboot-dubbo-fescar-account - - - io.seata - nutzboot-dubbo-fescar-common - ${project.version} - - - \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarAccountServiceLauncher.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarAccountServiceLauncher.java deleted file mode 100644 index 0025dab2f..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarAccountServiceLauncher.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.nutz.demo.dubbo.rpc; - -import io.nutz.demo.bean.Account; -import org.nutz.boot.NbApp; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; - -@IocBean(create = "init") -public class DemoFescarAccountServiceLauncher { - - @Inject - Dao dao; - - public void init() { - dao.create(Account.class, false); - if (dao.count(Account.class, Cnd.where("userId", "=", "U100001")) == 0) { - Account account = new Account(); - account.setUserId("U100001"); - account.setMoney(1000); - dao.insert(account); - } - } - - public static void main(String[] args) throws Exception { - new NbApp().run(); - } - -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/AccountServiceImpl.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/AccountServiceImpl.java deleted file mode 100644 index e869ba169..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service.impl; - -import com.alibaba.dubbo.config.annotation.Service; -import com.alibaba.fescar.core.context.RootContext; - -import io.nutz.demo.bean.Account; -import io.nutz.demo.dubbo.rpc.service.AccountService; -import org.nutz.dao.Chain; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.log.Log; -import org.nutz.log.Logs; - -@IocBean -@Service(interfaceClass = AccountService.class) -public class AccountServiceImpl implements AccountService { - - private static final Log log = Logs.get(); - - @Inject - private Dao dao; - - @Override - public void debit(String userId, int money) { - log.info("Account Service ... xid: " + RootContext.getXID()); - log.infof("Deducting balance SQL: update account_tbl set money = money - %s where user_id = %s", money, userId); - - dao.update(Account.class, Chain.makeSpecial("money", "-" + money), Cnd.where("userId", "=", userId)); - log.info("Account Service End ... "); - } -} \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/resources/application.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/resources/application.properties deleted file mode 100644 index e00a04e9e..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/resources/application.properties +++ /dev/null @@ -1,11 +0,0 @@ -server.port=0 -jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo -jdbc.username=root -jdbc.password=root -fescar.enabled=true -fescar.applicationId=dubbo-fescar-account -fescar.txServiceGroup=my_test_tx_group -dubbo.application.name=dubbo-fescar-account -dubbo.registry.address=zookeeper://127.0.0.1:2181 -dubbo.protocol.name=dubbo -dubbo.application.qos.enable=false \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/resources/log4j.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/resources/log4j.properties deleted file mode 100644 index 5e849115b..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-account/src/main/resources/log4j.properties +++ /dev/null @@ -1,5 +0,0 @@ -log4j.rootLogger=debug,Console -log4j.logger.org.eclipse.jetty=info -log4j.appender.Console=org.apache.log4j.ConsoleAppender -log4j.appender.Console.layout=org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/.gitignore b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/.gitignore deleted file mode 100644 index b83d22266..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/bin/pom.xml b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/bin/pom.xml deleted file mode 100644 index 09bdaabee..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/bin/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - 4.0.0 - - org.nutz - nutzboot-demo-dubbo - 2.0 - - nutzboot-demo-dubbo-common - - - org.nutz - nutzboot-starter-dubbo - ${project.version} - provided - - - com.alibaba - dubbo - provided - - - \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/pom.xml b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/pom.xml deleted file mode 100644 index 933553bf3..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - 4.0.0 - - io.seata - nutzboot-dubbo-seata - 1.1.0 - - nutzboot-dubbo-fescar-common - - - \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Account.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Account.java deleted file mode 100644 index 3cd3b7319..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Account.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.nutz.demo.bean; - -import org.nutz.dao.entity.annotation.Column; -import org.nutz.dao.entity.annotation.Id; -import org.nutz.dao.entity.annotation.Index; -import org.nutz.dao.entity.annotation.Table; -import org.nutz.dao.entity.annotation.TableIndexes; - -@Table("account_tbl") -@TableIndexes(@Index(fields = "userId", unique = true)) -public class Account { - - @Id - private long id; - - @Column("user_id") - private String userId; - - @Column - private int money; - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public int getMoney() { - return money; - } - - public void setMoney(int money) { - this.money = money; - } - -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Order.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Order.java deleted file mode 100644 index a598b44cc..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Order.java +++ /dev/null @@ -1,63 +0,0 @@ -package io.nutz.demo.bean; - -import java.io.Serializable; - -import org.nutz.dao.entity.annotation.Column; -import org.nutz.dao.entity.annotation.Id; -import org.nutz.dao.entity.annotation.Table; - -@Table("order_tbl") -public class Order implements Serializable { - - private static final long serialVersionUID = 1L; - @Id - private long id; - @Column("user_id") - private String userId; - @Column("commodity_code") - private String commodityCode; - @Column - private int count; - @Column - private int money; - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getCommodityCode() { - return commodityCode; - } - - public void setCommodityCode(String commodityCode) { - this.commodityCode = commodityCode; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - - public int getMoney() { - return money; - } - - public void setMoney(int money) { - this.money = money; - } -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Stock.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Stock.java deleted file mode 100644 index b8b0cd668..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/bean/Stock.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.nutz.demo.bean; - -import org.nutz.dao.entity.annotation.Column; -import org.nutz.dao.entity.annotation.Id; -import org.nutz.dao.entity.annotation.Table; - -@Table("stock_tbl") -public class Stock { - - @Id - private long id; - @Column("commodity_code") - private String commodityCode; - @Column - private int count; - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getCommodityCode() { - return commodityCode; - } - - public void setCommodityCode(String commodityCode) { - this.commodityCode = commodityCode; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/AccountService.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/AccountService.java deleted file mode 100644 index 9dac203f6..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/AccountService.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service; - -public interface AccountService { - - /** - * debit balance of user's account - */ - void debit(String userId, int money); -} \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/BusinessService.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/BusinessService.java deleted file mode 100644 index 3c6bca2bd..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/BusinessService.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service; - -public interface BusinessService { - - void purchase(String userId, String commodityCode, int orderCount, boolean dofail); -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/OrderService.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/OrderService.java deleted file mode 100644 index 7510d2a87..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/OrderService.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service; - -import io.nutz.demo.bean.Order; - -public interface OrderService { - - /** - * create order - */ - Order create(String userId, String commodityCode, int orderCount); -} \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/StockService.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/StockService.java deleted file mode 100644 index 343bd0552..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-common/src/main/java/io/nutz/demo/dubbo/rpc/service/StockService.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service; - -public interface StockService { - - /** - * deduct stock count - */ - void deduct(String commodityCode, int count); -} \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/.gitignore b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/.gitignore deleted file mode 100644 index b83d22266..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/pom.xml b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/pom.xml deleted file mode 100644 index 32a61db89..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - 4.0.0 - - io.seata - nutzboot-dubbo-seata - 1.1.0 - - nutzboot-dubbo-fescar-order - - - io.seata - nutzboot-dubbo-fescar-common - ${project.version} - - - \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarOrderServiceLauncher.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarOrderServiceLauncher.java deleted file mode 100644 index ae01c5fea..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarOrderServiceLauncher.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.nutz.demo.dubbo.rpc; - -import io.nutz.demo.bean.Order; -import org.nutz.boot.NbApp; -import org.nutz.dao.Dao; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; - -@IocBean(create = "init") -public class DemoFescarOrderServiceLauncher { - - @Inject - Dao dao; - - public void init() { - dao.create(Order.class, false); - } - - public static void main(String[] args) throws Exception { - new NbApp().run(); - } - -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/OrderServiceImpl.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/OrderServiceImpl.java deleted file mode 100644 index f3e75c662..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/OrderServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service.impl; - -import com.alibaba.dubbo.config.annotation.Reference; -import com.alibaba.dubbo.config.annotation.Service; - -import io.nutz.demo.bean.Order; -import io.nutz.demo.dubbo.rpc.service.AccountService; -import io.nutz.demo.dubbo.rpc.service.OrderService; -import org.nutz.dao.Dao; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; - -@IocBean -@Service(interfaceClass = OrderService.class) -public class OrderServiceImpl implements OrderService { - - @Inject - private Dao dao; - - @Inject - @Reference - private AccountService accountService; - - public Order create(String userId, String commodityCode, int orderCount) { - - int orderMoney = calculate(commodityCode, orderCount); - - accountService.debit(userId, orderMoney); - - Order order = new Order(); - order.setUserId(userId); - order.setCommodityCode(commodityCode); - order.setCount(orderCount); - order.setMoney(orderMoney); - - // INSERT INTO orders ... - return dao.insert(order); - } - - protected int calculate(String commodityCode, int orderCount) { - return 100; - } -} \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/resources/application.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/resources/application.properties deleted file mode 100644 index 952437345..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/resources/application.properties +++ /dev/null @@ -1,11 +0,0 @@ -server.port=0 -dubbo.application.name=dubbo-fescar-order -dubbo.registry.address=zookeeper://127.0.0.1:2181 -dubbo.protocol.name=dubbo -dubbo.application.qos.enable=false -jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo -jdbc.username=root -jdbc.password=root -fescar.enabled=true -fescar.applicationId=dubbo-fescar-order -fescar.txServiceGroup=my_test_tx_group \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/resources/log4j.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/resources/log4j.properties deleted file mode 100644 index 5e849115b..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-order/src/main/resources/log4j.properties +++ /dev/null @@ -1,5 +0,0 @@ -log4j.rootLogger=debug,Console -log4j.logger.org.eclipse.jetty=info -log4j.appender.Console=org.apache.log4j.ConsoleAppender -log4j.appender.Console.layout=org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/.gitignore b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/.gitignore deleted file mode 100644 index b83d22266..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/pom.xml b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/pom.xml deleted file mode 100644 index 1239cfc91..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - 4.0.0 - - io.seata - nutzboot-dubbo-seata - 1.1.0 - - nutzboot-dubbo-fescar-stock - - - io.seata - nutzboot-dubbo-fescar-common - ${project.version} - - - \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarStockServiceLauncher.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarStockServiceLauncher.java deleted file mode 100644 index 9ced14fc5..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarStockServiceLauncher.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.nutz.demo.dubbo.rpc; - -import io.nutz.demo.bean.Stock; -import org.nutz.boot.NbApp; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; - -@IocBean(create = "init") -public class DemoFescarStockServiceLauncher { - - @Inject - Dao dao; - - public void init() { - dao.create(Stock.class, false); - if (dao.count(Stock.class, Cnd.where("commodityCode", "=", "C00321")) == 0) { - Stock stock = new Stock(); - stock.setCommodityCode("C00321"); - stock.setCount(100); - dao.insert(stock); - } - } - - public static void main(String[] args) throws Exception { - new NbApp().run(); - } - -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/StockServiceImpl.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/StockServiceImpl.java deleted file mode 100644 index b6ea21d87..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/StockServiceImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service.impl; - -import javax.sql.DataSource; - -import com.alibaba.dubbo.config.annotation.Service; -import com.alibaba.fescar.core.context.RootContext; - -import io.nutz.demo.bean.Stock; -import io.nutz.demo.dubbo.rpc.service.StockService; -import org.nutz.dao.Chain; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.log.Log; -import org.nutz.log.Logs; - -@IocBean -@Service(interfaceClass = StockService.class) -public class StockServiceImpl implements StockService { - - private static final Log log = Logs.get(); - - @Inject - private Dao dao; - - @Inject - private DataSource dataSource; - - @Override - public void deduct(String commodityCode, int count) { - log.info("Stock Service Begin ... xid: " + RootContext.getXID()); - log.infof("Deducting inventory SQL: update stock_tbl set count = count - %s where commodity_code = %s", count, - commodityCode); - - dao.update(Stock.class, Chain.makeSpecial("count", "-" + count), - Cnd.where("commodityCode", "=", commodityCode)); - log.info("Stock Service End ... "); - - } - -} \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/resources/application.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/resources/application.properties deleted file mode 100644 index 9cde5544c..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/resources/application.properties +++ /dev/null @@ -1,11 +0,0 @@ -server.port=0 -dubbo.application.name=dubbo-fescar-stock -dubbo.registry.address=zookeeper://127.0.0.1:2181 -dubbo.protocol.name=dubbo -dubbo.application.qos.enable=false -jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo -jdbc.username=root -jdbc.password=root -fescar.enabled=true -fescar.applicationId=dubbo-fescar-stock -fescar.txServiceGroup=my_test_tx_group \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/resources/log4j.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/resources/log4j.properties deleted file mode 100644 index 5e849115b..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-stock/src/main/resources/log4j.properties +++ /dev/null @@ -1,5 +0,0 @@ -log4j.rootLogger=debug,Console -log4j.logger.org.eclipse.jetty=info -log4j.appender.Console=org.apache.log4j.ConsoleAppender -log4j.appender.Console.layout=org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/.gitignore b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/.gitignore deleted file mode 100644 index b83d22266..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/pom.xml b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/pom.xml deleted file mode 100644 index f5ed68dbc..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - - io.seata - nutzboot-dubbo-seata - 1.1.0 - - nutzboot-dubbo-fescar-web - - - org.nutz - nutzboot-starter-nutz-mvc - ${nutzboot.version} - - - org.nutz - nutzboot-starter-jetty - ${nutzboot.version} - - - io.seata - nutzboot-dubbo-fescar-common - ${project.version} - - - \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarWebLauncher.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarWebLauncher.java deleted file mode 100644 index 0d122122b..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/java/io/nutz/demo/dubbo/rpc/DemoFescarWebLauncher.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.nutz.demo.dubbo.rpc; - -import io.nutz.demo.bean.Account; -import io.nutz.demo.bean.Stock; -import io.nutz.demo.dubbo.rpc.service.BusinessService; -import org.nutz.boot.NbApp; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.util.NutMap; -import org.nutz.log.Log; -import org.nutz.log.Logs; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; - -@IocBean -public class DemoFescarWebLauncher { - - private static final Log log = Logs.get(); - - @Inject - protected BusinessService businessService; - - // 订购信息 - @Ok("json:full") - @At("/api/purchase") - public NutMap purchase(String userId, String commodityCode, int orderCount, boolean dofail) { - try { - businessService.purchase(userId, commodityCode, orderCount, dofail); - return new NutMap("ok", true); - } catch (Throwable e) { - log.debug("purchase fail", e); - return new NutMap("ok", false); - } - } - - // -------------------------------------------- - @Inject - protected Dao dao; - - // 用于页面显示数据 - @Ok("json:full") - @At("/api/info") - public NutMap info() { - NutMap re = new NutMap(); - NutMap data = new NutMap(); - data.put("account", dao.fetch(Account.class, Cnd.where("userId", "=", "U100001"))); - data.put("stock", dao.fetch(Stock.class, Cnd.where("commodityCode", "=", "C00321"))); - return re.setv("data", data).setv("ok", true); - } - - // 要启动zk做dubbo注册服务, fescar-server也需要下载启动 - // 数据库名称 fescar_demo, 用户名密码均为root,可以在application.properties里面修改 - //启动顺序: account,stock,order,web, 服务启动完成后再启动下一个 - // 页面操作: http://127.0.0.1:8080/ - //正常操作: - // http://127.0.0.1:8080/api/purchase?userId=U100001&commodityCode=C00321&orderCount=1 - // 故意抛出异常: - // http://127.0.0.1:8080/api/purchase?userId=U100001&commodityCode=C00321&orderCount=1&dofail=true - public static void main(String[] args) throws Exception { - new NbApp().run(); - } - -} diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/BusinessServiceImpl.java b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/BusinessServiceImpl.java deleted file mode 100644 index c356b464d..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/java/io/nutz/demo/dubbo/rpc/service/impl/BusinessServiceImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.nutz.demo.dubbo.rpc.service.impl; - -import com.alibaba.dubbo.config.annotation.Reference; -import com.alibaba.fescar.core.context.RootContext; -import com.alibaba.fescar.spring.annotation.GlobalTransactional; - -import io.nutz.demo.dubbo.rpc.service.BusinessService; -import io.nutz.demo.dubbo.rpc.service.OrderService; -import io.nutz.demo.dubbo.rpc.service.StockService; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.log.Log; -import org.nutz.log.Logs; - -@IocBean -public class BusinessServiceImpl implements BusinessService { - - private static final Log log = Logs.get(); - - @Inject - @Reference - private StockService stockService; - - @Inject - @Reference - private OrderService orderService; - - /** - * purchase - */ - @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") - @Override - public void purchase(String userId, String commodityCode, int orderCount, boolean dofail) { - log.info("purchase begin ... xid: " + RootContext.getXID()); - - stockService.deduct(commodityCode, orderCount); - orderService.create(userId, commodityCode, orderCount); - - // for test - if (dofail) { - throw new RuntimeException("just make it failed"); - } - } -} \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/application.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/application.properties deleted file mode 100644 index 6a2ad40d9..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/application.properties +++ /dev/null @@ -1,12 +0,0 @@ -server.port=8080 -server.host=0.0.0.0 -dubbo.application.name=dubbo-fescar-web -dubbo.registry.address=zookeeper://127.0.0.1:2181 -dubbo.protocol.name=dubbo -dubbo.application.qos.enable=false -jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo -jdbc.username=root -jdbc.password=root -fescar.enabled=true -fescar.applicationId=dubbo-fescar-web -fescar.txServiceGroup=my_test_tx_group \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/log4j.properties b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/log4j.properties deleted file mode 100644 index 5e849115b..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/log4j.properties +++ /dev/null @@ -1,5 +0,0 @@ -log4j.rootLogger=debug,Console -log4j.logger.org.eclipse.jetty=info -log4j.appender.Console=org.apache.log4j.ConsoleAppender -log4j.appender.Console.layout=org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/static/index.html b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/static/index.html deleted file mode 100644 index 0f4c023fa..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/static/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Fescar分布式事务演示 - - - - -
-
- 当前余额: -
-
- 剩余库存: -
-
- -
-
- -
-
- -
-
- - - \ No newline at end of file diff --git a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/static/jquery-3.3.1.min.js b/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/static/jquery-3.3.1.min.js deleted file mode 100644 index 48adafc35..000000000 --- a/nutzboot-dubbo-fescar/nutzboot-dubbo-fescar-web/src/main/resources/static/jquery-3.3.1.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-stock|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("