From 2353a004a3a35085d5138f833e4bb95ea520b0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?WangLiang/=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Wed, 21 Dec 2022 23:21:36 +0800 Subject: [PATCH 01/76] test: fix `test-compile` fails when the version of the `spring-boot` is lower than `2.4.0` (#5188) --- build/pom.xml | 4 ++++ dependencies/pom.xml | 53 ++++++++------------------------------------ server/pom.xml | 9 ++++++++ 3 files changed, 22 insertions(+), 44 deletions(-) diff --git a/build/pom.xml b/build/pom.xml index 2241bb7ed14..60f52896fc9 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -76,6 +76,10 @@ 2.5.13 5.3.19 + + 5.8.2 + 1.8.2 + 1.0.5 diff --git a/dependencies/pom.xml b/dependencies/pom.xml index de852a77cb1..67db5b5a7f0 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -110,8 +110,6 @@ 1.4.3 - 5.8.2 - 1.8.2 2.23.4 3.12.2 9.4.38.v20210224 @@ -119,6 +117,15 @@ + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + org.springframework @@ -638,48 +645,6 @@ - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - - - org.junit.jupiter - junit-jupiter-params - ${junit-jupiter.version} - - - org.junit.platform - junit-platform-commons - ${junit-platform.version} - - - org.junit.platform - junit-platform-engine - ${junit-platform.version} - - - org.junit.platform - junit-platform-launcher - ${junit-platform.version} - org.mockito mockito-core diff --git a/server/pom.xml b/server/pom.xml index 9911f321a86..d260d1a99f9 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -35,6 +35,15 @@ + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + org.springframework From 083c718d2696d6a0adea60229da8b1ab078666d3 Mon Sep 17 00:00:00 2001 From: Richard Milllions <2234501359@qq.com> Date: Fri, 23 Dec 2022 14:27:06 +0800 Subject: [PATCH 02/76] bugfix: wrong keyword order for oracle when creating a table (#5194) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ script/server/db/oracle.sql | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 03ffeb016a1..109f590ea07 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -7,6 +7,7 @@ Add changes here for all PR submitted to the develop branch. ### bugfix: - [[#xxx](https://github.com/seata/seata/pull/xxx)] fix xxx +- [[#5194](https://github.com/seata/seata/pull/5194)] fix wrong keyword order for oracle when creating a table ### optimize: - [[#xxx](https://github.com/seata/seata/pull/xxx)] optimize xxx @@ -18,5 +19,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [slievrly](https://github.com/slievrly) +- [xssdpgy](https://github.com/xssdpgy) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 499d8e8c469..9095101fc81 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -7,6 +7,7 @@ ### bugfix: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 修复 xxx +- [[#5194](https://github.com/seata/seata/pull/5194)] 修复使用Oracle作为服务端DB存储时的建表失败问题 ### optimize: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 优化 xxx @@ -18,5 +19,6 @@ - [slievrly](https://github.com/slievrly) +- [xssdpgy](https://github.com/xssdpgy) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/script/server/db/oracle.sql b/script/server/db/oracle.sql index 6573135ffe9..829a1a804b0 100644 --- a/script/server/db/oracle.sql +++ b/script/server/db/oracle.sql @@ -48,7 +48,7 @@ CREATE TABLE lock_table resource_id VARCHAR2(256), table_name VARCHAR2(32), pk VARCHAR2(36), - status NUMBER(3) NOT NULL DEFAULT 0, + status NUMBER(3) DEFAULT 0 NOT NULL, gmt_create TIMESTAMP(0), gmt_modified TIMESTAMP(0), PRIMARY KEY (row_key) From 1bad3b86389f6b77d54a786603fe3eb8d1bb21d0 Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Mon, 26 Dec 2022 16:49:01 +0800 Subject: [PATCH 03/76] bugfix: Use Proxy.getInvocationHandler instead of reflection (#5201) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../java/io/seata/spring/util/SpringProxyUtils.java | 10 +++++----- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 109f590ea07..ad1bc17fd16 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -8,6 +8,7 @@ Add changes here for all PR submitted to the develop branch. ### bugfix: - [[#xxx](https://github.com/seata/seata/pull/xxx)] fix xxx - [[#5194](https://github.com/seata/seata/pull/5194)] fix wrong keyword order for oracle when creating a table +- [[#5021](https://github.com/seata/seata/pull/5201)] Fix JDK Reflection for Spring origin proxy failed in JDK17 ### optimize: - [[#xxx](https://github.com/seata/seata/pull/xxx)] optimize xxx @@ -20,5 +21,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [slievrly](https://github.com/slievrly) - [xssdpgy](https://github.com/xssdpgy) +- [albumenj](https://github.com/albumenj) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 9095101fc81..85bc34e0da1 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -8,6 +8,7 @@ ### bugfix: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 修复 xxx - [[#5194](https://github.com/seata/seata/pull/5194)] 修复使用Oracle作为服务端DB存储时的建表失败问题 +- [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 ### optimize: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 优化 xxx @@ -20,5 +21,6 @@ - [slievrly](https://github.com/slievrly) - [xssdpgy](https://github.com/xssdpgy) +- [albumenj](https://github.com/albumenj) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java b/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java index 567903b75ac..c07455b9b79 100644 --- a/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java +++ b/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java @@ -85,14 +85,14 @@ private static Class[] getInterfacesByAdvised(AdvisedSupport advised) { * @throws Exception the exception */ public static AdvisedSupport getAdvisedSupport(Object proxy) throws Exception { - Field h; + Object dynamicAdvisedInterceptor; if (AopUtils.isJdkDynamicProxy(proxy)) { - h = proxy.getClass().getSuperclass().getDeclaredField("h"); + dynamicAdvisedInterceptor = Proxy.getInvocationHandler(proxy); } else { - h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0"); + Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0"); + h.setAccessible(true); + dynamicAdvisedInterceptor = h.get(proxy); } - h.setAccessible(true); - Object dynamicAdvisedInterceptor = h.get(proxy); Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised"); advised.setAccessible(true); return (AdvisedSupport)advised.get(dynamicAdvisedInterceptor); From e423b38db24a34aaa958ef1b930c666bedbe5810 Mon Sep 17 00:00:00 2001 From: renliangyu857 <2918490262@qq.com> Date: Thu, 29 Dec 2022 11:34:13 +0800 Subject: [PATCH 04/76] optimize: log message level (#5212) --- changes/en-us/develop.md | 3 +-- changes/zh-cn/develop.md | 2 +- .../java/io/seata/console/utils/JwtTokenUtils.java | 10 +++++----- .../seata/core/exception/AbstractExceptionHandler.java | 4 ++-- .../java/io/seata/rm/datasource/DataSourceManager.java | 2 +- .../io/seata/rm/datasource/xa/ResourceManagerXA.java | 6 +++--- .../seata/server/coordinator/DefaultCoordinator.java | 4 ++-- .../java/io/seata/server/coordinator/DefaultCore.java | 5 +++-- .../java/io/seata/server/session/SessionHolder.java | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index ad1bc17fd16..d19fb1b8e54 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -6,12 +6,11 @@ Add changes here for all PR submitted to the develop branch. - [[#xxx](https://github.com/seata/seata/pull/xxx)] support xxx ### bugfix: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] fix xxx - [[#5194](https://github.com/seata/seata/pull/5194)] fix wrong keyword order for oracle when creating a table - [[#5021](https://github.com/seata/seata/pull/5201)] Fix JDK Reflection for Spring origin proxy failed in JDK17 ### optimize: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] optimize xxx +- [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] add test for xxx diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 85bc34e0da1..63921213087 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -11,7 +11,7 @@ - [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 ### optimize: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] 优化 xxx +- [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 增加 xxx 测试 diff --git a/console/src/main/java/io/seata/console/utils/JwtTokenUtils.java b/console/src/main/java/io/seata/console/utils/JwtTokenUtils.java index 1c5d46f2939..9166955882b 100644 --- a/console/src/main/java/io/seata/console/utils/JwtTokenUtils.java +++ b/console/src/main/java/io/seata/console/utils/JwtTokenUtils.java @@ -119,19 +119,19 @@ public boolean validateToken(String token) { Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); return true; } catch (SignatureException e) { - LOGGER.info("Invalid JWT signature."); + LOGGER.warn("Invalid JWT signature."); LOGGER.trace("Invalid JWT signature trace: {}", e); } catch (MalformedJwtException e) { - LOGGER.info("Invalid JWT token."); + LOGGER.warn("Invalid JWT token."); LOGGER.trace("Invalid JWT token trace: {}", e); } catch (ExpiredJwtException e) { - LOGGER.info("Expired JWT token."); + LOGGER.warn("Expired JWT token."); LOGGER.trace("Expired JWT token trace: {}", e); } catch (UnsupportedJwtException e) { - LOGGER.info("Unsupported JWT token."); + LOGGER.warn("Unsupported JWT token."); LOGGER.trace("Unsupported JWT token trace: {}", e); } catch (IllegalArgumentException e) { - LOGGER.info("JWT token compact of handler are invalid."); + LOGGER.warn("JWT token compact of handler are invalid."); LOGGER.trace("JWT token compact of handler are invalid trace: {}", e); } return false; diff --git a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java index 013fd901557..b859e984a69 100644 --- a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java +++ b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java @@ -132,10 +132,10 @@ public Date: Tue, 3 Jan 2023 14:59:54 +0800 Subject: [PATCH 05/76] bugfix: oracle initialize script index_name is duplicate (#5224) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ script/server/db/oracle.sql | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index d19fb1b8e54..6a6f7c8cde6 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -8,6 +8,7 @@ Add changes here for all PR submitted to the develop branch. ### bugfix: - [[#5194](https://github.com/seata/seata/pull/5194)] fix wrong keyword order for oracle when creating a table - [[#5021](https://github.com/seata/seata/pull/5201)] Fix JDK Reflection for Spring origin proxy failed in JDK17 +- [[#5224](https://github.com/seata/seata/pull/5224)] fix oracle initialize script index_name is duplicate ### optimize: - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level @@ -21,5 +22,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [slievrly](https://github.com/slievrly) - [xssdpgy](https://github.com/xssdpgy) - [albumenj](https://github.com/albumenj) +- [PeppaO](https://github.com/PeppaO) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 63921213087..1721a178503 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -9,6 +9,7 @@ - [[#xxx](https://github.com/seata/seata/pull/xxx)] 修复 xxx - [[#5194](https://github.com/seata/seata/pull/5194)] 修复使用Oracle作为服务端DB存储时的建表失败问题 - [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 +- [[#5224](https://github.com/seata/seata/pull/5224)] 修复 oracle初始化脚本索引名重复的问题 ### optimize: - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 @@ -22,5 +23,6 @@ - [slievrly](https://github.com/slievrly) - [xssdpgy](https://github.com/xssdpgy) - [albumenj](https://github.com/albumenj) +- [PeppaO](https://github.com/PeppaO) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/script/server/db/oracle.sql b/script/server/db/oracle.sql index 829a1a804b0..462d6b892ca 100644 --- a/script/server/db/oracle.sql +++ b/script/server/db/oracle.sql @@ -56,7 +56,7 @@ CREATE TABLE lock_table comment on column lock_table.status is '0:locked ,1:rollbacking'; CREATE INDEX idx_branch_id ON lock_table (branch_id); -CREATE INDEX idx_xid ON lock_table (xid); +CREATE INDEX idx_lock_table_xid ON lock_table (xid); CREATE INDEX idx_status ON lock_table (status); CREATE TABLE distributed_lock ( From 7291b41c9c566487003edfe41e241da34d70422d Mon Sep 17 00:00:00 2001 From: yuruixin Date: Sun, 8 Jan 2023 18:28:31 +0800 Subject: [PATCH 06/76] optimize: print Stack Trace in EnhancedServiceLoader.loadFile#catch (#5237) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../java/io/seata/common/loader/EnhancedServiceLoader.java | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 6a6f7c8cde6..c548a2c9073 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -12,6 +12,7 @@ Add changes here for all PR submitted to the develop branch. ### optimize: - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level +- [[#5237](https://github.com/seata/seata/pull/5237)] optimize exception log message print(EnhancedServiceLoader.loadFile#cahtch) ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] add test for xxx @@ -23,5 +24,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [xssdpgy](https://github.com/xssdpgy) - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) +- [yuruixin](https://github.com/yuruixin) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 1721a178503..93e746dd6fd 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -13,6 +13,7 @@ ### optimize: - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 +- [[#5237](https://github.com/seata/seata/pull/5237)] 优化异常日志打印(EnhancedServiceLoader.loadFile#cahtch) ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 增加 xxx 测试 @@ -24,5 +25,6 @@ - [xssdpgy](https://github.com/xssdpgy) - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) +- [yuruixin](https://github.com/yuruixin) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index d9be35d9212..547b7a9cc1a 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -540,7 +540,7 @@ private void loadFile(String dir, ClassLoader loader, List Date: Mon, 9 Jan 2023 17:44:41 +0800 Subject: [PATCH 07/76] optimize: Throwable#getCause once more (#5208) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 3 ++- .../java/io/seata/server/transaction/at/ATCore.java | 5 +++-- .../annotation/GlobalTransactionalInterceptor.java | 11 ++++++----- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index c548a2c9073..6eba3841094 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -11,9 +11,11 @@ Add changes here for all PR submitted to the develop branch. - [[#5224](https://github.com/seata/seata/pull/5224)] fix oracle initialize script index_name is duplicate ### optimize: +- [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level - [[#5237](https://github.com/seata/seata/pull/5237)] optimize exception log message print(EnhancedServiceLoader.loadFile#cahtch) + ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] add test for xxx diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 93e746dd6fd..1f93299345e 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -6,15 +6,16 @@ - [[#xxx](https://github.com/seata/seata/pull/xxx)] 支持 xxx ### bugfix: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] 修复 xxx - [[#5194](https://github.com/seata/seata/pull/5194)] 修复使用Oracle作为服务端DB存储时的建表失败问题 - [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 - [[#5224](https://github.com/seata/seata/pull/5224)] 修复 oracle初始化脚本索引名重复的问题 ### optimize: +- [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 - [[#5237](https://github.com/seata/seata/pull/5237)] 优化异常日志打印(EnhancedServiceLoader.loadFile#cahtch) + ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 增加 xxx 测试 diff --git a/server/src/main/java/io/seata/server/transaction/at/ATCore.java b/server/src/main/java/io/seata/server/transaction/at/ATCore.java index b26530d1ef1..81163b99f9c 100644 --- a/server/src/main/java/io/seata/server/transaction/at/ATCore.java +++ b/server/src/main/java/io/seata/server/transaction/at/ATCore.java @@ -80,8 +80,9 @@ protected void branchSessionLock(GlobalSession globalSession, BranchSession bran branchSession.getBranchId())); } } catch (StoreException e) { - if (e.getCause() instanceof BranchTransactionException) { - throw new BranchTransactionException(((BranchTransactionException)e.getCause()).getCode(), + Throwable cause = e.getCause(); + if (cause instanceof BranchTransactionException) { + throw new BranchTransactionException(((BranchTransactionException)cause).getCode(), String.format("Global lock acquire failed xid = %s branchId = %s", globalSession.getXid(), branchSession.getBranchId())); } diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java index 6011eced7c7..7bc8609ecad 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java @@ -246,17 +246,18 @@ public TransactionInfo getTransactionInfo() { }); } catch (TransactionalExecutor.ExecutionException e) { TransactionalExecutor.Code code = e.getCode(); + Throwable cause = e.getCause(); switch (code) { case RollbackDone: throw e.getOriginalException(); case BeginFailure: succeed = false; - failureHandler.onBeginFailure(e.getTransaction(), e.getCause()); - throw e.getCause(); + failureHandler.onBeginFailure(e.getTransaction(), cause); + throw cause; case CommitFailure: succeed = false; - failureHandler.onCommitFailure(e.getTransaction(), e.getCause()); - throw e.getCause(); + failureHandler.onCommitFailure(e.getTransaction(), cause); + throw cause; case RollbackFailure: failureHandler.onRollbackFailure(e.getTransaction(), e.getOriginalException()); throw e.getOriginalException(); @@ -265,7 +266,7 @@ public TransactionInfo getTransactionInfo() { throw e.getOriginalException(); case TimeoutRollback: failureHandler.onTimeoutRollback(e.getTransaction(), e.getOriginalException()); - throw e.getCause(); + throw cause; default: throw new ShouldNeverHappenException(String.format("Unknown TransactionalExecutor.Code: %s", code)); } From fc29936df32eb2f1e094388d48aa3b68e93b8e2f Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Tue, 10 Jan 2023 18:36:41 +0800 Subject: [PATCH 08/76] bugfix: seata-core dependency transitive conflict in seata-dubbo (#5203) --- all/pom.xml | 6 ++++++ changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ dependencies/pom.xml | 2 +- integration/dubbo/pom.xml | 9 ++++++--- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index b87fe16cec9..e0215683f9e 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -399,6 +399,12 @@ org.apache.dubbo.extensions dubbo-filter-seata + + + io.seata + seata-core + + com.google.protobuf diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 6eba3841094..2be0b0db0f3 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -8,8 +8,10 @@ Add changes here for all PR submitted to the develop branch. ### bugfix: - [[#5194](https://github.com/seata/seata/pull/5194)] fix wrong keyword order for oracle when creating a table - [[#5021](https://github.com/seata/seata/pull/5201)] Fix JDK Reflection for Spring origin proxy failed in JDK17 +- [[#5023](https://github.com/seata/seata/pull/5203)] Fix `seata-core` dependency transitive conflict in `seata-dubbo` - [[#5224](https://github.com/seata/seata/pull/5224)] fix oracle initialize script index_name is duplicate + ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 1f93299345e..3d9b326af77 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -8,8 +8,10 @@ ### bugfix: - [[#5194](https://github.com/seata/seata/pull/5194)] 修复使用Oracle作为服务端DB存储时的建表失败问题 - [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 +- [[#5023](https://github.com/seata/seata/pull/5203)] 修复 `seata-core` 模块传递依赖冲突 - [[#5224](https://github.com/seata/seata/pull/5224)] 修复 oracle初始化脚本索引名重复的问题 + ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 67db5b5a7f0..1b8364aa7a6 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -32,7 +32,7 @@ dependencies for Seata built with Maven - 1.0.0 + 1.0.2 2.5.9 1.8.3 1.12.13 diff --git a/integration/dubbo/pom.xml b/integration/dubbo/pom.xml index 2138072be8f..c146949ef9e 100644 --- a/integration/dubbo/pom.xml +++ b/integration/dubbo/pom.xml @@ -29,13 +29,16 @@ seata-dubbo ${project.version} apache dubbo integration for Seata built with Maven - - 1.0.0 - org.apache.dubbo.extensions dubbo-filter-seata + + + io.seata + seata-core + + From d19cfee0819befa633d611750cf6ad3f8d6bdc69 Mon Sep 17 00:00:00 2001 From: xingfudeshi Date: Thu, 12 Jan 2023 14:49:01 +0800 Subject: [PATCH 09/76] bugfix: fix the inconsistent configuration item names related to LoadBalance (#5233) --- changes/en-us/develop.md | 3 + changes/zh-cn/develop.md | 2 + .../java/io/seata/common/DefaultValues.java | 2 +- .../ConsistentHashLoadBalance.java | 6 +- .../config/ConfigurationFactoryTest.java | 8 +-- .../src/test/resources/file.conf | 6 +- script/client/conf/file.conf | 4 +- script/client/spring/application.properties | 2 +- script/client/spring/application.yml | 2 +- ...itional-spring-configuration-metadata.json | 9 ++- .../client/LoadBalancePropertiesTest.java | 70 +++++++++++++++++++ test/src/test/resources/file.conf | 4 +- 12 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 2be0b0db0f3..90c5f323cac 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -10,6 +10,8 @@ Add changes here for all PR submitted to the develop branch. - [[#5021](https://github.com/seata/seata/pull/5201)] Fix JDK Reflection for Spring origin proxy failed in JDK17 - [[#5023](https://github.com/seata/seata/pull/5203)] Fix `seata-core` dependency transitive conflict in `seata-dubbo` - [[#5224](https://github.com/seata/seata/pull/5224)] fix oracle initialize script index_name is duplicate +- [[#5233](https://github.com/seata/seata/pull/5233)] fix the inconsistent configuration item names related to LoadBalance + ### optimize: @@ -29,5 +31,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) +- [xingfudeshi](https://github.com/xingfudeshi) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 3d9b326af77..9248b04fc5e 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -10,6 +10,7 @@ - [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 - [[#5023](https://github.com/seata/seata/pull/5203)] 修复 `seata-core` 模块传递依赖冲突 - [[#5224](https://github.com/seata/seata/pull/5224)] 修复 oracle初始化脚本索引名重复的问题 +- [[#5233](https://github.com/seata/seata/pull/5233)] 修复LoadBalance相关配置不一致的问题 ### optimize: @@ -29,5 +30,6 @@ - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) +- [xingfudeshi](https://github.com/xingfudeshi) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/common/src/main/java/io/seata/common/DefaultValues.java b/common/src/main/java/io/seata/common/DefaultValues.java index 8ab3777d72e..a2086b27587 100644 --- a/common/src/main/java/io/seata/common/DefaultValues.java +++ b/common/src/main/java/io/seata/common/DefaultValues.java @@ -141,7 +141,7 @@ public interface DefaultValues { * the constant TM_INTERCEPTOR_ORDER */ int TM_INTERCEPTOR_ORDER = Integer.MIN_VALUE + 1000; - + /** * the constant TCC_ACTION_INTERCEPTOR_ORDER */ diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/ConsistentHashLoadBalance.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/ConsistentHashLoadBalance.java index 25aed09918a..421b57d3487 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/ConsistentHashLoadBalance.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/ConsistentHashLoadBalance.java @@ -37,13 +37,13 @@ public class ConsistentHashLoadBalance implements LoadBalance { /** - * The constant LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES. + * The constant LOAD_BALANCE_CONSISTENT_HASH_VIRTUAL_NODES. */ - public static final String LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES = LOAD_BALANCE_PREFIX + "visualNodes"; + public static final String LOAD_BALANCE_CONSISTENT_HASH_VIRTUAL_NODES = LOAD_BALANCE_PREFIX + "virtualNodes"; /** * The constant VIRTUAL_NODES_NUM. */ - private static final int VIRTUAL_NODES_NUM = ConfigurationFactory.getInstance().getInt(LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES, VIRTUAL_NODES_DEFAULT); + private static final int VIRTUAL_NODES_NUM = ConfigurationFactory.getInstance().getInt(LOAD_BALANCE_CONSISTENT_HASH_VIRTUAL_NODES, VIRTUAL_NODES_DEFAULT); @Override public T select(List invokers, String xid) { diff --git a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java index 2e26179202f..7b45ac9fac0 100644 --- a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java +++ b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java @@ -37,9 +37,9 @@ void getInstance() { void getLoadBalance() { Configuration configuration = ConfigurationFactory.getInstance(); String loadBalanceType = configuration.getConfig(LoadBalanceFactory.LOAD_BALANCE_TYPE); - int visualNode = configuration.getInt(ConsistentHashLoadBalance.LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES); - Assertions.assertEquals("RandomLoadBalance", loadBalanceType); - Assertions.assertEquals(10,visualNode); + int virtualNode = configuration.getInt(ConsistentHashLoadBalance.LOAD_BALANCE_CONSISTENT_HASH_VIRTUAL_NODES); + Assertions.assertEquals("XID", loadBalanceType); + Assertions.assertEquals(10,virtualNode); } -} \ No newline at end of file +} diff --git a/discovery/seata-discovery-core/src/test/resources/file.conf b/discovery/seata-discovery-core/src/test/resources/file.conf index 12e134002ba..908d7c2a89c 100644 --- a/discovery/seata-discovery-core/src/test/resources/file.conf +++ b/discovery/seata-discovery-core/src/test/resources/file.conf @@ -17,7 +17,7 @@ #loadBalance config client { loadBalance { - type = "RandomLoadBalance" - visualNodes = 10 + type = "XID" + virtualNodes = 10 } -} \ No newline at end of file +} diff --git a/script/client/conf/file.conf b/script/client/conf/file.conf index 7c99daa059a..a91822aaede 100644 --- a/script/client/conf/file.conf +++ b/script/client/conf/file.conf @@ -106,7 +106,7 @@ client { } } loadBalance { - type = "RandomLoadBalance" + type = "XID" virtualNodes = 10 } } @@ -120,4 +120,4 @@ tcc { # tcc fence log clean period cleanPeriod = 1h } -} \ No newline at end of file +} diff --git a/script/client/spring/application.properties b/script/client/spring/application.properties index 0c4d4b72d42..662b4de3ced 100755 --- a/script/client/spring/application.properties +++ b/script/client/spring/application.properties @@ -54,7 +54,7 @@ seata.client.undo.log-table=undo_log seata.client.undo.compress.enable=true seata.client.undo.compress.type=zip seata.client.undo.compress.threshold=64k -seata.client.load-balance.type=RandomLoadBalance +seata.client.load-balance.type=XID seata.client.load-balance.virtual-nodes=10 seata.log.exception-rate=100 seata.service.vgroup-mapping.default_tx_group=default diff --git a/script/client/spring/application.yml b/script/client/spring/application.yml index 9a547964d57..9a62f299e30 100755 --- a/script/client/spring/application.yml +++ b/script/client/spring/application.yml @@ -44,7 +44,7 @@ seata: type: zip threshold: 64k load-balance: - type: RandomLoadBalance + type: XID virtual-nodes: 10 service: vgroup-mapping: diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 5ca2a8de55c..6e13dff145a 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -214,7 +214,7 @@ "name": "seata.client.load-balance.type", "type": "java.lang.String", "sourceType": "io.seata.spring.boot.autoconfigure.properties.client.LoadBalanceProperties", - "defaultValue": "RandomLoadBalance" + "defaultValue": "XID" }, { "name": "seata.client.load-balance.virtual-nodes", @@ -348,7 +348,7 @@ "name": "seata.client.load-balance.type", "values": [ { - "value": "RandomLoadBalance", + "value": "XID", "description": "the default load balance." }, { @@ -359,6 +359,9 @@ }, { "value": "LeastActiveLoadBalance" + }, + { + "value": "RandomLoadBalance" } ] }, @@ -442,4 +445,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java new file mode 100644 index 00000000000..a427af72ae9 --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 1999-2019 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.spring.boot.autoconfigure.properties.client; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.config.Configuration; +import io.seata.config.ExtConfigurationProvider; +import io.seata.config.FileConfiguration; +import io.seata.config.springcloud.SpringApplicationContextProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +import static io.seata.spring.boot.autoconfigure.StarterConstants.LOAD_BALANCE_PREFIX; +import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +/** + * @author xingfudeshi@gmail.com + **/ +@Import(SpringApplicationContextProvider.class) +@org.springframework.context.annotation.Configuration +public class LoadBalancePropertiesTest { + private static AnnotationConfigApplicationContext applicationContext; + + @BeforeAll + public static void initContext() { + applicationContext = new AnnotationConfigApplicationContext(LoadBalancePropertiesTest.class); + } + + @Bean + LoadBalanceProperties loadBalanceProperties() { + LoadBalanceProperties loadBalanceProperties = new LoadBalanceProperties(); + PROPERTY_BEAN_MAP.put(LOAD_BALANCE_PREFIX, LoadBalanceProperties.class); + return loadBalanceProperties; + } + + @Test + public void testLoadBalanceProperties() { + FileConfiguration configuration = mock(FileConfiguration.class); + Configuration currentConfiguration = + EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + System.setProperty("seata.client.loadBalance.virtualNodes", "30"); + assertEquals(30, currentConfiguration.getInt("client.loadBalance.virtualNodes")); + System.setProperty("seata.client.loadBalance.type", "test"); + assertEquals("test", currentConfiguration.getConfig("client.loadBalance.type")); + } + + @AfterAll + public static void closeContext() { + applicationContext.close(); + } +} diff --git a/test/src/test/resources/file.conf b/test/src/test/resources/file.conf index f42eec4474b..249f11f9a27 100644 --- a/test/src/test/resources/file.conf +++ b/test/src/test/resources/file.conf @@ -63,7 +63,7 @@ client { sagaCompensatePersistModeUpdate = false } loadBalance { - type = "RandomLoadBalance" + type = "XID" virtualNodes = 10 } -} \ No newline at end of file +} From a84bbcc8cd77dbba4bfe377048169fb427079688 Mon Sep 17 00:00:00 2001 From: justabug Date: Tue, 17 Jan 2023 17:21:52 +0800 Subject: [PATCH 10/76] optimize: Only AT mode try to get channel with other app (#5153) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ core/src/main/java/io/seata/core/rpc/RemotingServer.java | 3 ++- .../seata/core/rpc/netty/AbstractNettyRemotingServer.java | 5 +++-- .../main/java/io/seata/core/rpc/netty/ChannelManager.java | 4 ++-- .../main/java/io/seata/server/coordinator/AbstractCore.java | 6 ++++-- .../main/java/io/seata/server/session/BranchSession.java | 4 ++++ .../io/seata/server/coordinator/DefaultCoordinatorTest.java | 3 ++- 8 files changed, 21 insertions(+), 8 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 90c5f323cac..e82d886cd5d 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -18,6 +18,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level - [[#5237](https://github.com/seata/seata/pull/5237)] optimize exception log message print(EnhancedServiceLoader.loadFile#cahtch) +- [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app ### test: @@ -32,5 +33,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) - [xingfudeshi](https://github.com/xingfudeshi) +- [Bughue](https://github.com/Bughue) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 9248b04fc5e..511597fe61a 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -17,6 +17,7 @@ - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 - [[#5237](https://github.com/seata/seata/pull/5237)] 优化异常日志打印(EnhancedServiceLoader.loadFile#cahtch) +- [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel ### test: @@ -31,5 +32,6 @@ - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) - [xingfudeshi](https://github.com/xingfudeshi) +- [Bughue](https://github.com/Bughue) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/core/src/main/java/io/seata/core/rpc/RemotingServer.java b/core/src/main/java/io/seata/core/rpc/RemotingServer.java index 4839e2fc0c5..fa388ed9e48 100644 --- a/core/src/main/java/io/seata/core/rpc/RemotingServer.java +++ b/core/src/main/java/io/seata/core/rpc/RemotingServer.java @@ -37,10 +37,11 @@ public interface RemotingServer { * @param resourceId rm client resourceId * @param clientId rm client id * @param msg transaction message {@code io.seata.core.protocol} + * @param tryOtherApp try other app * @return client result message * @throws TimeoutException TimeoutException */ - Object sendSyncRequest(String resourceId, String clientId, Object msg) throws TimeoutException; + Object sendSyncRequest(String resourceId, String clientId, Object msg, boolean tryOtherApp) throws TimeoutException; /** * server send sync request. diff --git a/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingServer.java b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingServer.java index 880b8f47308..4e67446b547 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingServer.java +++ b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingServer.java @@ -63,8 +63,9 @@ public AbstractNettyRemotingServer(ThreadPoolExecutor messageExecutor, NettyServ } @Override - public Object sendSyncRequest(String resourceId, String clientId, Object msg) throws TimeoutException { - Channel channel = ChannelManager.getChannel(resourceId, clientId); + public Object sendSyncRequest(String resourceId, String clientId, Object msg, boolean tryOtherApp) + throws TimeoutException { + Channel channel = ChannelManager.getChannel(resourceId, clientId, tryOtherApp); if (channel == null) { throw new RuntimeException("rm client is not connected. dbkey:" + resourceId + ",clientId:" + clientId); } diff --git a/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java b/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java index f5c93c3c56f..caaabba879b 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java @@ -276,7 +276,7 @@ private static Channel getChannelFromSameClientMap(Map clie * @param clientId Client ID - ApplicationId:IP:Port * @return Corresponding channel, NULL if not found. */ - public static Channel getChannel(String resourceId, String clientId) { + public static Channel getChannel(String resourceId, String clientId, boolean tryOtherApp) { Channel resultChannel = null; String[] clientIdInfo = readClientId(clientId); @@ -381,7 +381,7 @@ public static Channel getChannel(String resourceId, String clientId) { } } - if (resultChannel == null) { + if (resultChannel == null && tryOtherApp) { resultChannel = tryOtherApp(applicationIdMap, targetApplicationId); if (resultChannel == null) { diff --git a/server/src/main/java/io/seata/server/coordinator/AbstractCore.java b/server/src/main/java/io/seata/server/coordinator/AbstractCore.java index 84ab8036b2e..9b8f79ab39c 100644 --- a/server/src/main/java/io/seata/server/coordinator/AbstractCore.java +++ b/server/src/main/java/io/seata/server/coordinator/AbstractCore.java @@ -172,8 +172,9 @@ public BranchStatus branchCommit(GlobalSession globalSession, BranchSession bran protected BranchStatus branchCommitSend(BranchCommitRequest request, GlobalSession globalSession, BranchSession branchSession) throws IOException, TimeoutException { + BranchCommitResponse response = (BranchCommitResponse) remotingServer.sendSyncRequest( - branchSession.getResourceId(), branchSession.getClientId(), request); + branchSession.getResourceId(), branchSession.getClientId(), request, branchSession.isAT()); return response.getBranchStatus(); } @@ -196,8 +197,9 @@ public BranchStatus branchRollback(GlobalSession globalSession, BranchSession br protected BranchStatus branchRollbackSend(BranchRollbackRequest request, GlobalSession globalSession, BranchSession branchSession) throws IOException, TimeoutException { + BranchRollbackResponse response = (BranchRollbackResponse) remotingServer.sendSyncRequest( - branchSession.getResourceId(), branchSession.getClientId(), request); + branchSession.getResourceId(), branchSession.getClientId(), request, branchSession.isAT()); return response.getBranchStatus(); } diff --git a/server/src/main/java/io/seata/server/session/BranchSession.java b/server/src/main/java/io/seata/server/session/BranchSession.java index 402701f4493..af0bcf63295 100644 --- a/server/src/main/java/io/seata/server/session/BranchSession.java +++ b/server/src/main/java/io/seata/server/session/BranchSession.java @@ -297,6 +297,10 @@ public boolean unlock() throws TransactionException { return true; } + public boolean isAT() { + return this.getBranchType() == BranchType.AT; + } + public LockStatus getLockStatus() { return lockStatus; } diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java index 39ae7873c02..c83eefdc30c 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java @@ -249,7 +249,8 @@ static Stream xidAndBranchIdProviderForRollback() throws Exception { public static class MockServerMessageSender implements RemotingServer { @Override - public Object sendSyncRequest(String resourceId, String clientId, Object message) throws TimeoutException { + public Object sendSyncRequest(String resourceId, String clientId, Object message, boolean tryOtherApp) + throws TimeoutException { if (message instanceof BranchCommitRequest) { final BranchCommitResponse branchCommitResponse = new BranchCommitResponse(); branchCommitResponse.setBranchStatus(BranchStatus.PhaseTwo_Committed); From 24ccd9933e8a183cd5c6158e4a480e7b194255f1 Mon Sep 17 00:00:00 2001 From: justabug Date: Wed, 18 Jan 2023 00:12:52 +0800 Subject: [PATCH 11/76] security: fix some security vulnerabilities (#5172) --- build/pom.xml | 2 +- changes/en-us/develop.md | 3 +++ changes/zh-cn/develop.md | 2 ++ dependencies/pom.xml | 16 +++++++++++----- pom.xml | 2 +- server/pom.xml | 2 +- 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/build/pom.xml b/build/pom.xml index 60f52896fc9..899e27c268a 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -74,7 +74,7 @@ 2.5.13 - 5.3.19 + 5.3.20 5.8.2 diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index e82d886cd5d..3826f11910f 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -20,6 +20,9 @@ Add changes here for all PR submitted to the develop branch. - [[#5237](https://github.com/seata/seata/pull/5237)] optimize exception log message print(EnhancedServiceLoader.loadFile#cahtch) - [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app +### security: +- [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities + ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] add test for xxx diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 511597fe61a..80dbc2eb7e6 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -19,6 +19,8 @@ - [[#5237](https://github.com/seata/seata/pull/5237)] 优化异常日志打印(EnhancedServiceLoader.loadFile#cahtch) - [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel +### security: +- [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] 增加 xxx 测试 diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 1b8364aa7a6..bcb6dc37bca 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -36,7 +36,7 @@ 2.5.9 1.8.3 1.12.13 - 2.6.5 + 2.6.10 5.5.3 1.2.83 1.5.9 @@ -55,7 +55,7 @@ 1.4.2 0.5.0 1.11.2 - 27.0.1-jre + 30.1-jre 1 1.3.2 4.0.1 @@ -69,7 +69,7 @@ 1.10.12 1.7.1 - 3.11.4 + 3.16.3 1.27.1 5.3.0 0.45 @@ -80,6 +80,7 @@ 1.4.19 0.10.5 + 2.13.4.1 0.6.0 1.2.9 6.5 @@ -90,9 +91,9 @@ - 5.1.35 + 5.1.42 19.3.0.0 - 42.1.4 + 42.3.3 1.4.181 2.7.2 @@ -615,6 +616,11 @@ jjwt-jackson ${jwt.version} + + com.fasterxml.jackson.core + jackson-databind + ${jackson.databind.version} + io.prometheus simpleclient_httpserver diff --git a/pom.xml b/pom.xml index 764cb6e129a..90e31432011 100644 --- a/pom.xml +++ b/pom.xml @@ -157,7 +157,7 @@ false latest false - 5.1.35 + 5.1.42 8.0.27 diff --git a/server/pom.xml b/server/pom.xml index d260d1a99f9..c2e3589e33c 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -370,7 +370,7 @@ release-seata - 5.1.35 + 5.1.42 8.0.27 false From 6a7e1bb6b3a5cfde3b9ab4541923a8239de472e8 Mon Sep 17 00:00:00 2001 From: pengten <30648785+pengten@users.noreply.github.com> Date: Fri, 20 Jan 2023 19:19:33 +0800 Subject: [PATCH 12/76] optimize: unlock branch synchronously. (#5177) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../coordinator/DefaultCoordinator.java | 35 ++++++++++++++----- .../seata/server/session/GlobalSession.java | 12 ++++++- .../seata/server/session/SessionHelper.java | 27 ++++++++++---- .../server/session/SessionLifecycle.java | 16 +++++++++ .../server/session/GlobalSessionTest.java | 2 +- 7 files changed, 79 insertions(+), 17 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 3826f11910f..91fd519d47b 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -19,6 +19,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level - [[#5237](https://github.com/seata/seata/pull/5237)] optimize exception log message print(EnhancedServiceLoader.loadFile#cahtch) - [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app +- [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities @@ -37,5 +38,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [yuruixin](https://github.com/yuruixin) - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) +- [pengten](https://github.com/pengten) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 80dbc2eb7e6..dc962976881 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -18,6 +18,7 @@ - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 - [[#5237](https://github.com/seata/seata/pull/5237)] 优化异常日志打印(EnhancedServiceLoader.loadFile#cahtch) - [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel +- [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 @@ -35,5 +36,6 @@ - [yuruixin](https://github.com/yuruixin) - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) +- [pengten](https://github.com/pengten) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index e109ee4aa04..a4c8cb1b72c 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -66,6 +66,7 @@ import io.seata.server.session.SessionCondition; import io.seata.server.session.SessionHelper; import io.seata.server.session.SessionHolder; +import io.seata.server.store.StoreConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -77,6 +78,7 @@ import static io.seata.common.Constants.UNDOLOG_DELETE; import static io.seata.common.DefaultValues.DEFAULT_ASYNC_COMMITTING_RETRY_PERIOD; import static io.seata.common.DefaultValues.DEFAULT_COMMITING_RETRY_PERIOD; +import static io.seata.common.DefaultValues.DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE; import static io.seata.common.DefaultValues.DEFAULT_MAX_COMMIT_RETRY_TIMEOUT; import static io.seata.common.DefaultValues.DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT; import static io.seata.common.DefaultValues.DEFAULT_ROLLBACKING_RETRY_PERIOD; @@ -138,7 +140,7 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran /** * the pool size of branch asynchronous remove thread pool */ - private static final int BRANCH_ASYNC_POOL_SIZE = Runtime.getRuntime().availableProcessors(); + private static final int BRANCH_ASYNC_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; private static final Duration MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration( ConfigurationKeys.MAX_COMMIT_RETRY_TIMEOUT, DurationUtil.DEFAULT_DURATION, DEFAULT_MAX_COMMIT_RETRY_TIMEOUT); @@ -170,12 +172,7 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran private final GlobalStatus[] retryCommittingStatuses = new GlobalStatus[] {GlobalStatus.Committing, GlobalStatus.CommitRetrying}; - private final ThreadPoolExecutor branchRemoveExecutor = new ThreadPoolExecutor(BRANCH_ASYNC_POOL_SIZE, BRANCH_ASYNC_POOL_SIZE, - Integer.MAX_VALUE, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>( - CONFIG.getInt(ConfigurationKeys.SESSION_BRANCH_ASYNC_QUEUE_SIZE, DEFAULT_BRANCH_ASYNC_QUEUE_SIZE) - ), new NamedThreadFactory("branchSessionRemove", BRANCH_ASYNC_POOL_SIZE), - new ThreadPoolExecutor.CallerRunsPolicy()); + private final ThreadPoolExecutor branchRemoveExecutor; private RemotingServer remotingServer; @@ -194,6 +191,19 @@ private DefaultCoordinator(RemotingServer remotingServer) { } this.remotingServer = remotingServer; this.core = new DefaultCore(remotingServer); + boolean enableBranchAsyncRemove = CONFIG.getBoolean( + ConfigurationKeys.ENABLE_BRANCH_ASYNC_REMOVE, DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE); + // create branchRemoveExecutor + if (enableBranchAsyncRemove && StoreConfig.getSessionMode() != StoreConfig.SessionMode.FILE) { + branchRemoveExecutor = new ThreadPoolExecutor(BRANCH_ASYNC_POOL_SIZE, BRANCH_ASYNC_POOL_SIZE, + Integer.MAX_VALUE, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>( + CONFIG.getInt(ConfigurationKeys.SESSION_BRANCH_ASYNC_QUEUE_SIZE, DEFAULT_BRANCH_ASYNC_QUEUE_SIZE) + ), new NamedThreadFactory("branchSessionRemove", BRANCH_ASYNC_POOL_SIZE), + new ThreadPoolExecutor.CallerRunsPolicy()); + } else { + branchRemoveExecutor = null; + } } public static DefaultCoordinator getInstance(RemotingServer remotingServer) { @@ -533,14 +543,18 @@ public void destroy() { asyncCommitting.shutdown(); timeoutCheck.shutdown(); undoLogDelete.shutdown(); - branchRemoveExecutor.shutdown(); + if (branchRemoveExecutor != null) { + branchRemoveExecutor.shutdown(); + } try { retryRollbacking.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); undoLogDelete.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - branchRemoveExecutor.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); + if (branchRemoveExecutor != null) { + branchRemoveExecutor.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); + } } catch (InterruptedException ignore) { } @@ -582,6 +596,9 @@ static class BranchRemoveTask implements Runnable { */ public BranchRemoveTask(GlobalSession globalSession, BranchSession branchSession) { this.globalSession = globalSession; + if (branchSession == null) { + throw new IllegalArgumentException("BranchSession can`t be null!"); + } this.branchSession = branchSession; } diff --git a/server/src/main/java/io/seata/server/session/GlobalSession.java b/server/src/main/java/io/seata/server/session/GlobalSession.java index 8f510e98217..1f4c4c61821 100644 --- a/server/src/main/java/io/seata/server/session/GlobalSession.java +++ b/server/src/main/java/io/seata/server/session/GlobalSession.java @@ -312,7 +312,7 @@ public void loadBranchs() { } @Override - public void removeBranch(BranchSession branchSession) throws TransactionException { + public void unlockBranch(BranchSession branchSession) throws TransactionException { // do not unlock if global status in (Committing, CommitRetrying, AsyncCommitting), // because it's already unlocked in 'DefaultCore.commit()' if (status != Committing && status != CommitRetrying && status != AsyncCommitting) { @@ -320,12 +320,22 @@ public void removeBranch(BranchSession branchSession) throws TransactionExceptio throw new TransactionException("Unlock branch lock failed, xid = " + this.xid + ", branchId = " + branchSession.getBranchId()); } } + } + + @Override + public void removeBranch(BranchSession branchSession) throws TransactionException { for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { lifecycleListener.onRemoveBranch(this, branchSession); } remove(branchSession); } + @Override + public void removeAndUnlockBranch(BranchSession branchSession) throws TransactionException { + unlockBranch(branchSession); + removeBranch(branchSession); + } + /** * Gets branch. * diff --git a/server/src/main/java/io/seata/server/session/SessionHelper.java b/server/src/main/java/io/seata/server/session/SessionHelper.java index f1c85975a9d..e766893c732 100644 --- a/server/src/main/java/io/seata/server/session/SessionHelper.java +++ b/server/src/main/java/io/seata/server/session/SessionHelper.java @@ -294,7 +294,8 @@ public static Boolean forEach(Collection sessions, BranchSessionH */ public static void removeBranch(GlobalSession globalSession, BranchSession branchSession, boolean isAsync) throws TransactionException { - if (Objects.equals(Boolean.TRUE, ENABLE_BRANCH_ASYNC_REMOVE) && isAsync) { + globalSession.unlockBranch(branchSession); + if (isEnableBranchRemoveAsync() && isAsync) { COORDINATOR.doBranchRemoveAsync(globalSession, branchSession); } else { globalSession.removeBranch(branchSession); @@ -312,12 +313,26 @@ public static void removeAllBranch(GlobalSession globalSession, boolean isAsync) if (branchSessions == null || branchSessions.isEmpty()) { return; } - if (Objects.equals(Boolean.TRUE, ENABLE_BRANCH_ASYNC_REMOVE) && isAsync) { - COORDINATOR.doBranchRemoveAllAsync(globalSession); - } else { - for (BranchSession branchSession : branchSessions) { - globalSession.removeBranch(branchSession); + boolean isAsyncRemove = isEnableBranchRemoveAsync() && isAsync; + for (BranchSession branchSession : branchSessions) { + if (isAsyncRemove) { + globalSession.unlockBranch(branchSession); + } else { + globalSession.removeAndUnlockBranch(branchSession); } } + if (isAsyncRemove) { + COORDINATOR.doBranchRemoveAllAsync(globalSession); + } + } + + /** + * if true, enable delete the branch asynchronously + * + * @return the boolean + */ + private static boolean isEnableBranchRemoveAsync() { + return Objects.equals(Boolean.TRUE, DELAY_HANDLE_SESSION) + && Objects.equals(Boolean.TRUE, ENABLE_BRANCH_ASYNC_REMOVE); } } diff --git a/server/src/main/java/io/seata/server/session/SessionLifecycle.java b/server/src/main/java/io/seata/server/session/SessionLifecycle.java index 05cd87a3ab8..eb9bfcddfb9 100644 --- a/server/src/main/java/io/seata/server/session/SessionLifecycle.java +++ b/server/src/main/java/io/seata/server/session/SessionLifecycle.java @@ -58,6 +58,14 @@ public interface SessionLifecycle { */ void addBranch(BranchSession branchSession) throws TransactionException; + /** + * Release the lock of branch. + * + * @param branchSession the branch session + * @throws TransactionException the transaction exception + */ + void unlockBranch(BranchSession branchSession) throws TransactionException; + /** * Remove branch. * @@ -66,6 +74,14 @@ public interface SessionLifecycle { */ void removeBranch(BranchSession branchSession) throws TransactionException; + /** + * Remove branch and release the lock of branch. + * + * @param branchSession the branchSession + * @throws TransactionException the TransactionException + */ + void removeAndUnlockBranch(BranchSession branchSession) throws TransactionException; + /** * Is active boolean. * diff --git a/server/src/test/java/io/seata/server/session/GlobalSessionTest.java b/server/src/test/java/io/seata/server/session/GlobalSessionTest.java index 6a6b945c9a8..c4787ce69e6 100644 --- a/server/src/test/java/io/seata/server/session/GlobalSessionTest.java +++ b/server/src/test/java/io/seata/server/session/GlobalSessionTest.java @@ -144,7 +144,7 @@ public void addBranchTest(GlobalSession globalSession, BranchSession branchSessi @MethodSource("branchSessionProvider") public void removeBranchTest(GlobalSession globalSession, BranchSession branchSession) throws Exception { globalSession.addBranch(branchSession); - globalSession.removeBranch(branchSession); + globalSession.removeAndUnlockBranch(branchSession); } /** From fda8060779d00b1f985f156afb3d913a69357dcd Mon Sep 17 00:00:00 2001 From: HEIBAIJIE Date: Sun, 29 Jan 2023 15:03:03 +0800 Subject: [PATCH 13/76] bugfix: fix the incomplete dependency of distribution module (#5261) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + distribution/pom.xml | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 91fd519d47b..96e6e2c2007 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -11,6 +11,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5023](https://github.com/seata/seata/pull/5203)] Fix `seata-core` dependency transitive conflict in `seata-dubbo` - [[#5224](https://github.com/seata/seata/pull/5224)] fix oracle initialize script index_name is duplicate - [[#5233](https://github.com/seata/seata/pull/5233)] fix the inconsistent configuration item names related to LoadBalance +- [[#5245](https://github.com/seata/seata/pull/5245)] fix the incomplete dependency of distribution module diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index dc962976881..0e9e410f924 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -11,6 +11,7 @@ - [[#5023](https://github.com/seata/seata/pull/5203)] 修复 `seata-core` 模块传递依赖冲突 - [[#5224](https://github.com/seata/seata/pull/5224)] 修复 oracle初始化脚本索引名重复的问题 - [[#5233](https://github.com/seata/seata/pull/5233)] 修复LoadBalance相关配置不一致的问题 +- [[#5245](https://github.com/seata/seata/pull/5245)] 修复不完整的distribution模块依赖 ### optimize: diff --git a/distribution/pom.xml b/distribution/pom.xml index 891d610b041..f2f8f6e5b58 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -37,6 +37,11 @@ seata-server ${project.version} + + io.seata + apm-seata-skywalking-plugin + ${project.version} + seata From 63f685e204f75094e917b92fcf6da5ff06479d0c Mon Sep 17 00:00:00 2001 From: CrazyLionLi <31852897+JavaLionLi@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:24:18 +0800 Subject: [PATCH 14/76] optimize: kryo 5.4.0 compatibility with jdk17 (#5243) --- changes/en-us/develop.md | 3 +++ changes/zh-cn/develop.md | 3 +++ .../core/serializer/SerializerClassRegistry.java | 2 -- dependencies/pom.xml | 2 +- .../serializer/kryo/KryoSerializerFactory.java | 6 +----- .../seata/serializer/kryo/KryoSerializerTest.java | 13 +++++++++++++ 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 96e6e2c2007..3766764a22d 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -19,6 +19,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level - [[#5237](https://github.com/seata/seata/pull/5237)] optimize exception log message print(EnhancedServiceLoader.loadFile#cahtch) +- [[#5243](https://github.com/seata/seata/pull/5243)] optimize kryo 5.4.0 optimize compatibility with jdk17 - [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app - [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. @@ -37,8 +38,10 @@ Thanks to these contributors for their code commits. Please report an unintended - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) +- [CrazyLionLi](https://github.com/JavaLionLi) - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) - [pengten](https://github.com/pengten) + Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 0e9e410f924..e4cf69bbdab 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -18,6 +18,7 @@ - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 - [[#5237](https://github.com/seata/seata/pull/5237)] 优化异常日志打印(EnhancedServiceLoader.loadFile#cahtch) +- [[#5243](https://github.com/seata/seata/pull/5243)] 升级 kryo 5.4.0 优化对jdk17的兼容性 - [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel - [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 @@ -35,8 +36,10 @@ - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) +- [CrazyLionLi](https://github.com/JavaLionLi) - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) - [pengten](https://github.com/pengten) + 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/core/src/main/java/io/seata/core/serializer/SerializerClassRegistry.java b/core/src/main/java/io/seata/core/serializer/SerializerClassRegistry.java index 833b05e3c2f..6ffe71cd36a 100644 --- a/core/src/main/java/io/seata/core/serializer/SerializerClassRegistry.java +++ b/core/src/main/java/io/seata/core/serializer/SerializerClassRegistry.java @@ -15,7 +15,6 @@ */ package io.seata.core.serializer; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.BitSet; import java.util.Calendar; @@ -80,7 +79,6 @@ public class SerializerClassRegistry { registerClass(Date.class); registerClass(Calendar.class); registerClass(ConcurrentHashMap.class); - registerClass(SimpleDateFormat.class); registerClass(GregorianCalendar.class); registerClass(Vector.class); registerClass(BitSet.class); diff --git a/dependencies/pom.xml b/dependencies/pom.xml index bcb6dc37bca..e53f3475364 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -71,7 +71,7 @@ 3.16.3 1.27.1 - 5.3.0 + 5.4.0 0.45 4.0.63 2.57 diff --git a/serializer/seata-serializer-kryo/src/main/java/io/seata/serializer/kryo/KryoSerializerFactory.java b/serializer/seata-serializer-kryo/src/main/java/io/seata/serializer/kryo/KryoSerializerFactory.java index d23e46211f7..c9b3c93925f 100644 --- a/serializer/seata-serializer-kryo/src/main/java/io/seata/serializer/kryo/KryoSerializerFactory.java +++ b/serializer/seata-serializer-kryo/src/main/java/io/seata/serializer/kryo/KryoSerializerFactory.java @@ -21,15 +21,12 @@ import java.net.URI; import java.util.Arrays; import java.util.BitSet; -import java.util.GregorianCalendar; import java.util.UUID; import java.util.regex.Pattern; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.serializers.DefaultSerializers; import com.esotericsoftware.kryo.util.Pool; -import de.javakaffee.kryoserializers.ArraysAsListSerializer; import de.javakaffee.kryoserializers.BitSetSerializer; -import de.javakaffee.kryoserializers.GregorianCalendarSerializer; import de.javakaffee.kryoserializers.JdkProxySerializer; import de.javakaffee.kryoserializers.RegexSerializer; import de.javakaffee.kryoserializers.URISerializer; @@ -52,8 +49,7 @@ protected Kryo create() { kryo.setRegistrationRequired(false); // register serializer - kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer()); - kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer()); + kryo.register(Arrays.asList("").getClass()); kryo.register(InvocationHandler.class, new JdkProxySerializer()); kryo.register(BigDecimal.class, new DefaultSerializers.BigDecimalSerializer()); kryo.register(BigInteger.class, new DefaultSerializers.BigIntegerSerializer()); diff --git a/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java b/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java index bfc5f834978..b90ff04bb0a 100644 --- a/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java +++ b/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java @@ -15,6 +15,7 @@ */ package io.seata.serializer.kryo; +import com.esotericsoftware.kryo.Kryo; import io.seata.core.exception.TransactionExceptionCode; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; @@ -38,6 +39,18 @@ public static void before() { kryoCodec = new KryoSerializer(); } + /** + * 测试jdk版本对内置对象序列化的兼容性 + */ + @Test + public void testSerializerFactory() { + KryoSerializerFactory factory = KryoSerializerFactory.getInstance(); + KryoInnerSerializer kryoInnerSerializer = factory.get(); + Kryo kryo = kryoInnerSerializer.getKryo(); + assertThat(kryo).isNotNull(); + factory.returnKryo(kryoInnerSerializer); + } + @Test public void testBranchCommitRequest() { From 72347f255efc027bd9426a751b61a0cdbfead248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?WangLiang/=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Sun, 29 Jan 2023 19:58:12 +0800 Subject: [PATCH 15/76] bugfix: fix `getConfig` throw `ClassCastException` when use JDK proxy (#5239) --- changes/en-us/develop.md | 5 +- changes/zh-cn/develop.md | 3 +- .../java/io/seata/common/DefaultValues.java | 11 +- .../common/loader/EnhancedServiceLoader.java | 32 +++- .../io/seata/common/util/ReflectionUtil.java | 40 +++++ .../io/seata/config/ConfigurationCache.java | 8 +- .../io/seata/config/ConfigurationFactory.java | 8 +- .../struct/cache/AbstractTableMetaCache.java | 13 +- .../seata/rm/datasource/util/JdbcUtils.java | 6 +- .../properties/ShutdownProperties.java | 6 +- .../config/ConfigZooKeeperProperties.java | 10 +- .../registry/RegistryZooKeeperProperties.java | 12 +- .../SpringBootConfigurationProvider.java | 166 +++++++++++------- .../autoconfigure/BasePropertiesTest.java | 4 +- .../config/test/ZooKeeperPropertiesTest.java | 4 +- .../properties/server/ServerProperties.java | 15 +- .../server/ServerRecoveryProperties.java | 24 +-- .../server/ServerUndoProperties.java | 6 +- .../server/store/StoreDBProperties.java | 6 +- .../coordinator/DefaultCoordinator.java | 14 +- .../coordinator/DefaultCoordinatorTest.java | 12 +- .../annotation/GlobalTransactionScanner.java | 10 +- .../SeataAutoDataSourceProxyCreator.java | 1 + .../sqlparser/druid/DefaultDruidLoader.java | 6 +- 24 files changed, 265 insertions(+), 157 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 3766764a22d..af224973635 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -12,8 +12,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5224](https://github.com/seata/seata/pull/5224)] fix oracle initialize script index_name is duplicate - [[#5233](https://github.com/seata/seata/pull/5233)] fix the inconsistent configuration item names related to LoadBalance - [[#5245](https://github.com/seata/seata/pull/5245)] fix the incomplete dependency of distribution module - - +- [[#5239](https://github.com/seata/seata/pull/5239)] fix `getConfig` throw `ClassCastException` when use JDK proxy ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more @@ -26,7 +25,6 @@ Add changes here for all PR submitted to the develop branch. ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities - ### test: - [[#xxx](https://github.com/seata/seata/pull/xxx)] add test for xxx @@ -42,6 +40,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) - [pengten](https://github.com/pengten) +- [wangliang181230](https://github.com/wangliang181230) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index e4cf69bbdab..2d91a3337d7 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -12,7 +12,7 @@ - [[#5224](https://github.com/seata/seata/pull/5224)] 修复 oracle初始化脚本索引名重复的问题 - [[#5233](https://github.com/seata/seata/pull/5233)] 修复LoadBalance相关配置不一致的问题 - [[#5245](https://github.com/seata/seata/pull/5245)] 修复不完整的distribution模块依赖 - +- [[#5239](https://github.com/seata/seata/pull/5239)] 修复当使用JDK代理时,`getConfig` 方法获取部分配置时抛出 `ClassCastException` 异常的问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 @@ -40,6 +40,7 @@ - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) - [pengten](https://github.com/pengten) +- [wangliang181230](https://github.com/wangliang181230) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/common/src/main/java/io/seata/common/DefaultValues.java b/common/src/main/java/io/seata/common/DefaultValues.java index a2086b27587..bf12a6c3668 100644 --- a/common/src/main/java/io/seata/common/DefaultValues.java +++ b/common/src/main/java/io/seata/common/DefaultValues.java @@ -226,7 +226,7 @@ public interface DefaultValues { int DEFAULT_SERVICE_SESSION_RELOAD_READ_SIZE = 100; /** - *the constant DEFAULT_PROMETHEUS_PORT + * the constant DEFAULT_PROMETHEUS_PORT */ int DEFAULT_PROMETHEUS_PORT = 9898; @@ -248,12 +248,12 @@ public interface DefaultValues { /** * the const DEFAULT_MAX_COMMIT_RETRY_TIMEOUT */ - long DEFAULT_MAX_COMMIT_RETRY_TIMEOUT = 100; + long DEFAULT_MAX_COMMIT_RETRY_TIMEOUT = -1L; /** * the const DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT */ - long DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT = 100; + long DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT = -1L; /** * the const DEFAULT_ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE @@ -281,4 +281,9 @@ public interface DefaultValues { int DEFAULT_REDIS_MIN_IDLE = 10; int DEFAULT_QUERY_LIMIT = 1000; + + /** + * Default druid location in classpath + */ + String DRUID_LOCATION = "lib/sqlparser/druid.jar"; } diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index 547b7a9cc1a..3b6942c8a40 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -397,14 +397,12 @@ private S loadExtension(ClassLoader loader, Class[] argTypes, loadAllExtensionClass(loader); ExtensionDefinition defaultExtensionDefinition = getDefaultExtensionDefinition(); return getExtensionInstance(defaultExtensionDefinition, loader, argTypes, args); + } catch (EnhancedServiceNotFoundException e) { + throw e; } catch (Throwable e) { - if (e instanceof EnhancedServiceNotFoundException) { - throw (EnhancedServiceNotFoundException)e; - } else { - throw new EnhancedServiceNotFoundException( - "not found service provider for : " + type.getName() + " caused by " + ExceptionUtils - .getFullStackTrace(e)); - } + throw new EnhancedServiceNotFoundException( + "not found service provider for : " + type.getName() + + " caused by " + ExceptionUtils.getFullStackTrace(e)); } } @@ -519,7 +517,10 @@ private void loadFile(String dir, ClassLoader loader, List 0) { + hasClasses = true; try { ExtensionDefinition extensionDefinition = getUnloadedExtensionDefinition(line, loader); if (extensionDefinition == null) { @@ -540,7 +542,7 @@ private void loadFile(String dir, ClassLoader loader, List getClassByName(String className) throws ClassNotFoundExce return Class.forName(className, true, Thread.currentThread().getContextClassLoader()); } + /** + * Get the wrapped class + * + * @param clazz the class + * @return the wrapped class + */ + public static Class getWrappedClass(Class clazz) { + if (clazz.isPrimitive()) { + if (clazz.equals(byte.class)) { + return Byte.class; + } + if (clazz.equals(boolean.class)) { + return Boolean.class; + } + if (clazz.equals(char.class)) { + return Character.class; + } + if (clazz.equals(short.class)) { + return Short.class; + } + if (clazz.equals(int.class)) { + return Integer.class; + } + if (clazz.equals(long.class)) { + return Long.class; + } + if (clazz.equals(float.class)) { + return Float.class; + } + if (clazz.equals(double.class)) { + return Double.class; + } + if (clazz.equals(void.class)) { + return Void.class; + } + } + + return clazz; + } + //endregion diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java index f887f7810e5..e837ce78fae 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java @@ -104,18 +104,18 @@ public Configuration proxy(Configuration originalConfiguration) throws Exception return new ByteBuddy().subclass(Configuration.class).method(ElementMatchers.any()) .intercept(InvocationHandlerAdapter.of((proxy, method, args) -> { String methodName = method.getName(); - if (methodName.startsWith(METHOD_PREFIX) && !method.getName().equalsIgnoreCase(METHOD_LATEST_CONFIG)) { + if (methodName.startsWith(METHOD_PREFIX) && !methodName.equalsIgnoreCase(METHOD_LATEST_CONFIG)) { String rawDataId = (String)args[0]; ObjectWrapper wrapper = CONFIG_CACHE.get(rawDataId); ObjectWrapper.ConfigType type = - ObjectWrapper.getTypeByName(method.getName().substring(METHOD_PREFIX.length())); + ObjectWrapper.getTypeByName(methodName.substring(METHOD_PREFIX.length())); Object defaultValue = null; if (args.length > 1 - && method.getParameterTypes()[1].getSimpleName().equalsIgnoreCase(type.name())) { + && method.getParameterTypes()[1].getSimpleName().equalsIgnoreCase(type.name())) { defaultValue = args[1]; } if (null == wrapper - || (null != defaultValue && !Objects.equals(defaultValue, wrapper.lastDefaultValue))) { + || (null != defaultValue && !Objects.equals(defaultValue, wrapper.lastDefaultValue))) { Object result = method.invoke(originalConfiguration, args); // The wrapper.data only exists in the cache when it is not null. if (result != null) { diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java index f71f14198c3..55eb54d3fbc 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java @@ -69,10 +69,12 @@ private static void load() { LOGGER.info("load Configuration from :{}", extConfiguration == null ? configuration.getClass().getSimpleName() : "Spring Configuration"); } - } catch (EnhancedServiceNotFoundException ignore) { - + } catch (EnhancedServiceNotFoundException e) { + if (LOGGER.isDebugEnabled()) { + LOGGER.warn("failed to load extConfiguration: {}", e.getMessage(), e); + } } catch (Exception e) { - LOGGER.error("failed to load extConfiguration:{}", e.getMessage(), e); + LOGGER.error("failed to load extConfiguration: {}", e.getMessage(), e); } CURRENT_FILE_INSTANCE = extConfiguration == null ? configuration : extConfiguration; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java index dccd807f76f..2c1470447a7 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java @@ -44,8 +44,17 @@ public abstract class AbstractTableMetaCache implements TableMetaCache { private static final long EXPIRE_TIME = 900 * 1000; - private static final Cache TABLE_META_CACHE = Caffeine.newBuilder().maximumSize(CACHE_SIZE) - .expireAfterWrite(EXPIRE_TIME, TimeUnit.MILLISECONDS).softValues().build(); + private static final Cache TABLE_META_CACHE; + + static { + try { + TABLE_META_CACHE = Caffeine.newBuilder().maximumSize(CACHE_SIZE) + .expireAfterWrite(EXPIRE_TIME, TimeUnit.MILLISECONDS).softValues().build(); + } catch (Throwable t) { + LOGGER.error("Build the `TABLE_META_CACHE` failed:", t); + throw t; + } + } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/util/JdbcUtils.java b/rm-datasource/src/main/java/io/seata/rm/datasource/util/JdbcUtils.java index b462bc131dd..2f2e119dbeb 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/util/JdbcUtils.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/util/JdbcUtils.java @@ -104,7 +104,7 @@ public static String buildResourceId(String jdbcUrl) { } public static Driver loadDriver(String driverClassName) throws SQLException { - Class clazz = null; + Class clazz = null; try { ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); if (contextLoader != null) { @@ -124,9 +124,7 @@ public static Driver loadDriver(String driverClassName) throws SQLException { try { return (Driver)clazz.newInstance(); - } catch (IllegalAccessException e) { - throw new SQLException(e.getMessage(), e); - } catch (InstantiationException e) { + } catch (IllegalAccessException | InstantiationException e) { throw new SQLException(e.getMessage(), e); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/ShutdownProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/ShutdownProperties.java index 9010ede0942..8dec76f747a 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/ShutdownProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/ShutdownProperties.java @@ -30,13 +30,13 @@ public class ShutdownProperties { /** * when destroy server, wait seconds */ - private long wait = DEFAULT_SHUTDOWN_TIMEOUT_SEC; + private int wait = DEFAULT_SHUTDOWN_TIMEOUT_SEC; - public long getWait() { + public int getWait() { return wait; } - public ShutdownProperties setWait(long wait) { + public ShutdownProperties setWait(int wait) { this.wait = wait; return this; } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.java index 897f97eb5ac..e4c1556b588 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.java @@ -27,8 +27,8 @@ @ConfigurationProperties(prefix = CONFIG_ZK_PREFIX) public class ConfigZooKeeperProperties { private String serverAddr; - private long sessionTimeout = 6000L; - private long connectTimeout = 2000L; + private int sessionTimeout = 6000; + private int connectTimeout = 2000; private String username; private String password; private String nodePath = "/seata/seata.properties"; @@ -46,16 +46,16 @@ public long getSessionTimeout() { return sessionTimeout; } - public ConfigZooKeeperProperties setSessionTimeout(long sessionTimeout) { + public ConfigZooKeeperProperties setSessionTimeout(int sessionTimeout) { this.sessionTimeout = sessionTimeout; return this; } - public long getConnectTimeout() { + public int getConnectTimeout() { return connectTimeout; } - public ConfigZooKeeperProperties setConnectTimeout(long connectTimeout) { + public ConfigZooKeeperProperties setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; return this; } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryZooKeeperProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryZooKeeperProperties.java index dcb0c407a86..90c494a9f29 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryZooKeeperProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryZooKeeperProperties.java @@ -28,8 +28,8 @@ public class RegistryZooKeeperProperties { private String cluster = "default"; private String serverAddr = "127.0.0.1:2181"; - private long sessionTimeout = 6000L; - private long connectTimeout = 2000L; + private int sessionTimeout = 6000; + private int connectTimeout = 2000; private String username; private String password; @@ -51,20 +51,20 @@ public RegistryZooKeeperProperties setServerAddr(String serverAddr) { return this; } - public long getSessionTimeout() { + public int getSessionTimeout() { return sessionTimeout; } - public RegistryZooKeeperProperties setSessionTimeout(long sessionTimeout) { + public RegistryZooKeeperProperties setSessionTimeout(int sessionTimeout) { this.sessionTimeout = sessionTimeout; return this; } - public long getConnectTimeout() { + public int getConnectTimeout() { return connectTimeout; } - public RegistryZooKeeperProperties setConnectTimeout(long connectTimeout) { + public RegistryZooKeeperProperties setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; return this; } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java index c552a6f0792..5a3c4cdd07c 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java @@ -16,22 +16,26 @@ package io.seata.spring.boot.autoconfigure.provider; import java.lang.reflect.Field; -import java.util.HashMap; +import java.time.Duration; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.holder.ObjectHolder; +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.ReflectionUtil; import io.seata.config.Configuration; import io.seata.config.ExtConfigurationProvider; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.lang.Nullable; import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; import static io.seata.common.util.StringFormatUtils.DOT; @@ -52,7 +56,7 @@ public class SpringBootConfigurationProvider implements ExtConfigurationProvider private static final String INTERCEPT_METHOD_PREFIX = "get"; - private static final Map PROPERTY_BEAN_INSTANCE_MAP = new HashMap<>(64); + private static final Map PROPERTY_BEAN_INSTANCE_MAP = new ConcurrentHashMap<>(64); @Override public Configuration provide(Configuration originalConfiguration) { @@ -61,20 +65,49 @@ public Configuration provide(Configuration originalConfiguration) { if (method.getName().startsWith(INTERCEPT_METHOD_PREFIX) && args.length > 0) { Object result; String rawDataId = (String)args[0]; + Class dataType = ReflectionUtil.getWrappedClass(method.getReturnType()); + + // 1. Get config value from the system property result = originalConfiguration.getConfigFromSys(rawDataId); - if (null == result) { - if (args.length == 1) { - result = get(convertDataId(rawDataId)); - } else { - result = get(convertDataId(rawDataId), args[1]); + + if (result == null) { + String dataId = convertDataId(rawDataId); + + // 2. Get config value from the springboot environment + result = getConfigFromEnvironment(dataId, dataType); + if (result != null) { + return result; + } + + // 3. Get config defaultValue from the arguments + if (args.length > 1) { + result = args[1]; + + if (result != null) { + // See Configuration#getConfig(String dataId, long timeoutMills) + if (dataType.isAssignableFrom(result.getClass())) { + return result; + } else { + result = null; + } + } + } + + // 4. Get config defaultValue from the property object + try { + result = getDefaultValueFromPropertyObject(dataId); + } catch (Throwable t) { + LOGGER.error("Get config '{}' default value from the property object failed:", dataId, t); } } + if (result != null) { - // If the return type is String,need to convert the object to string - if (method.getReturnType().equals(String.class)) { - return String.valueOf(result); + if (dataType.isAssignableFrom(result.getClass())) { + return result; } - return result; + + // Convert type + return this.convertType(result, dataType); } } @@ -82,62 +115,53 @@ public Configuration provide(Configuration originalConfiguration) { }); } - private Object get(String dataId, Object defaultValue) throws IllegalAccessException, InstantiationException { - Object result = get(dataId); - if (result == null) { - return defaultValue; - } - return result; - } - - private Object get(String dataId) throws IllegalAccessException { + private Object getDefaultValueFromPropertyObject(String dataId) throws IllegalAccessException { String propertyPrefix = getPropertyPrefix(dataId); String propertySuffix = getPropertySuffix(dataId); - Class propertyClass = PROPERTY_BEAN_MAP.get(propertyPrefix); - Object valueObject = null; - if (propertyClass != null) { - try { - valueObject = getFieldValue( - Objects.requireNonNull(PROPERTY_BEAN_INSTANCE_MAP.computeIfAbsent(propertyPrefix, k -> { - try { - return propertyClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - LOGGER.error("PropertyClass for prefix: [" + propertyPrefix - + "] should not be null. error :" + e.getMessage(), e); - } - return null; - })), propertySuffix, dataId); - } catch (NoSuchBeanDefinitionException ignore) { - } - } else { + // Get the property class + final Class propertyClass = PROPERTY_BEAN_MAP.get(propertyPrefix); + if (propertyClass == null) { throw new ShouldNeverHappenException("PropertyClass for prefix: [" + propertyPrefix + "] should not be null."); } - return valueObject; + // Instantiate the property object + Object propertyObj = CollectionUtils.computeIfAbsent(PROPERTY_BEAN_INSTANCE_MAP, propertyPrefix, k -> { + try { + return propertyClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + LOGGER.warn("PropertyClass for prefix: [" + propertyPrefix + "] should not be null. error :" + e.getMessage(), e); + } + return null; + }); + Objects.requireNonNull(propertyObj, () -> "Instantiate the property object fail: " + propertyClass.getName()); + + // Get defaultValue from the property object + return getDefaultValueFromPropertyObject(propertyObj, propertySuffix); } /** - * get field value + * Get defaultValue from the property object * - * @param object - * @param fieldName - * @param dataId - * @return java.lang.Object + * @param propertyObj the property object + * @param fieldName the field name + * @return defaultValue * @author xingfudeshi@gmail.com */ - private Object getFieldValue(Object object, String fieldName, String dataId) throws IllegalAccessException { - Optional fieldOptional = Stream.of(object.getClass().getDeclaredFields()) + @Nullable + private Object getDefaultValueFromPropertyObject(Object propertyObj, String fieldName) throws IllegalAccessException { + Optional fieldOptional = Stream.of(propertyObj.getClass().getDeclaredFields()) .filter(f -> f.getName().equalsIgnoreCase(fieldName)).findAny(); + + // Get defaultValue from the field if (fieldOptional.isPresent()) { Field field = fieldOptional.get(); - if (Objects.equals(field.getType(), Map.class)) { - return getConfig(dataId, null, String.class); + if (!Map.class.isAssignableFrom(field.getType())) { + field.setAccessible(true); + return field.get(propertyObj); } - field.setAccessible(true); - Object defaultValue = field.get(object); - return getConfig(dataId, defaultValue, field.getType()); } + return null; } @@ -191,19 +215,41 @@ private String getPropertySuffix(String dataId) { /** * get spring config - * @param dataId data id - * @param defaultValue default value - * @param type type + * + * @param dataId data id + * @param dataType data type * @return object */ - private Object getConfig(String dataId, Object defaultValue, Class type) { - ConfigurableEnvironment environment = - (ConfigurableEnvironment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); - Object value = environment.getProperty(dataId, type); + @Nullable + private Object getConfigFromEnvironment(String dataId, Class dataType) { + ConfigurableEnvironment environment = (ConfigurableEnvironment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); + Object value = environment.getProperty(dataId, dataType); if (value == null) { - value = environment.getProperty(io.seata.common.util.StringUtils.hump2Line(dataId), type); + value = environment.getProperty(io.seata.common.util.StringUtils.hump2Line(dataId), dataType); + } + return value; + } + + private Object convertType(Object configValue, Class dataType) { + if (String.class.equals(dataType)) { + return String.valueOf(configValue); + } + if (Long.class.equals(dataType)) { + return Long.parseLong(String.valueOf(configValue)); + } + if (Integer.class.equals(dataType)) { + return Integer.parseInt(String.valueOf(configValue)); + } + if (Short.class.equals(dataType)) { + return Short.parseShort(String.valueOf(configValue)); + } + if (Boolean.class.equals(dataType)) { + return Boolean.parseBoolean(String.valueOf(configValue)); + } + if (Duration.class.equals(dataType)) { + return Duration.parse(String.valueOf(configValue)); } - return value != null ? value : defaultValue; + return configValue; } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java index 7501da2ef67..e450017a2bb 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java @@ -43,8 +43,8 @@ public class BasePropertiesTest { protected static final String STR_TEST_EEE = "eee"; protected static final String STR_TEST_FFF = "fff"; - protected static final long LONG_TEST_ONE = 1L; - protected static final long LONG_TEST_TWO = 2L; + protected static final int LONG_TEST_ONE = 1; + protected static final int LONG_TEST_TWO = 2; @BeforeEach public void setUp() throws IOException { diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java index 4a95734e907..a86afbae9ca 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java @@ -49,8 +49,8 @@ public void testConfigZooKeeperProperties() { assertEquals(STR_TEST_BBB, currentConfiguration.getConfig("config.zk.serverAddr")); assertEquals(STR_TEST_CCC, currentConfiguration.getConfig("config.zk.username")); assertEquals(STR_TEST_DDD, currentConfiguration.getConfig("config.zk.password")); - assertEquals(LONG_TEST_ONE, currentConfiguration.getLong("config.zk.connectTimeout")); - assertEquals(LONG_TEST_TWO, currentConfiguration.getLong("config.zk.sessionTimeout")); + assertEquals(LONG_TEST_ONE, currentConfiguration.getInt("config.zk.connectTimeout")); + assertEquals(LONG_TEST_TWO, currentConfiguration.getInt("config.zk.sessionTimeout")); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerProperties.java index 8bb69d771a9..7aec3ff5274 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerProperties.java @@ -15,9 +15,6 @@ */ package io.seata.spring.boot.autoconfigure.properties.server; -import java.time.Duration; - -import io.seata.common.util.DurationUtil; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -29,8 +26,8 @@ @Component @ConfigurationProperties(prefix = SERVER_PREFIX) public class ServerProperties { - private Duration maxCommitRetryTimeout = DurationUtil.DEFAULT_DURATION; - private Duration maxRollbackRetryTimeout = DurationUtil.DEFAULT_DURATION; + private long maxCommitRetryTimeout = -1L; + private long maxRollbackRetryTimeout = -1L; private Boolean rollbackRetryTimeoutUnlockEnable = false; private Boolean enableCheckAuth = true; private Boolean enableParallelRequestHandle = false; @@ -38,20 +35,20 @@ public class ServerProperties { private Integer servicePort; private Integer xaerNotaRetryTimeout = 60000; - public Duration getMaxCommitRetryTimeout() { + public long getMaxCommitRetryTimeout() { return maxCommitRetryTimeout; } - public ServerProperties setMaxCommitRetryTimeout(Duration maxCommitRetryTimeout) { + public ServerProperties setMaxCommitRetryTimeout(long maxCommitRetryTimeout) { this.maxCommitRetryTimeout = maxCommitRetryTimeout; return this; } - public Duration getMaxRollbackRetryTimeout() { + public long getMaxRollbackRetryTimeout() { return maxRollbackRetryTimeout; } - public ServerProperties setMaxRollbackRetryTimeout(Duration maxRollbackRetryTimeout) { + public ServerProperties setMaxRollbackRetryTimeout(long maxRollbackRetryTimeout) { this.maxRollbackRetryTimeout = maxRollbackRetryTimeout; return this; } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerRecoveryProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerRecoveryProperties.java index bd2eb2b0021..9935f1402e0 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerRecoveryProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerRecoveryProperties.java @@ -31,43 +31,43 @@ @ConfigurationProperties(prefix = SERVER_RECOVERY_PREFIX) public class ServerRecoveryProperties { - private int committingRetryPeriod = DEFAULT_COMMITING_RETRY_PERIOD; - private int asyncCommittingRetryPeriod = DEFAULT_ASYNC_COMMITTING_RETRY_PERIOD; - private int rollbackingRetryPeriod = DEFAULT_ROLLBACKING_RETRY_PERIOD; - private int timeoutRetryPeriod = DEFAULT_TIMEOUT_RETRY_PERIOD; + private long committingRetryPeriod = DEFAULT_COMMITING_RETRY_PERIOD; + private long asyncCommittingRetryPeriod = DEFAULT_ASYNC_COMMITTING_RETRY_PERIOD; + private long rollbackingRetryPeriod = DEFAULT_ROLLBACKING_RETRY_PERIOD; + private long timeoutRetryPeriod = DEFAULT_TIMEOUT_RETRY_PERIOD; - public int getCommittingRetryPeriod() { + public long getCommittingRetryPeriod() { return committingRetryPeriod; } - public ServerRecoveryProperties setCommittingRetryPeriod(int committingRetryPeriod) { + public ServerRecoveryProperties setCommittingRetryPeriod(long committingRetryPeriod) { this.committingRetryPeriod = committingRetryPeriod; return this; } - public int getAsyncCommittingRetryPeriod() { + public long getAsyncCommittingRetryPeriod() { return asyncCommittingRetryPeriod; } - public ServerRecoveryProperties setAsyncCommittingRetryPeriod(int asyncCommittingRetryPeriod) { + public ServerRecoveryProperties setAsyncCommittingRetryPeriod(long asyncCommittingRetryPeriod) { this.asyncCommittingRetryPeriod = asyncCommittingRetryPeriod; return this; } - public int getRollbackingRetryPeriod() { + public long getRollbackingRetryPeriod() { return rollbackingRetryPeriod; } - public ServerRecoveryProperties setRollbackingRetryPeriod(int rollbackingRetryPeriod) { + public ServerRecoveryProperties setRollbackingRetryPeriod(long rollbackingRetryPeriod) { this.rollbackingRetryPeriod = rollbackingRetryPeriod; return this; } - public Integer getTimeoutRetryPeriod() { + public long getTimeoutRetryPeriod() { return timeoutRetryPeriod; } - public ServerRecoveryProperties setTimeoutRetryPeriod(int timeoutRetryPeriod) { + public ServerRecoveryProperties setTimeoutRetryPeriod(long timeoutRetryPeriod) { this.timeoutRetryPeriod = timeoutRetryPeriod; return this; } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerUndoProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerUndoProperties.java index f1fc876ab3a..895b60d9216 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerUndoProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/ServerUndoProperties.java @@ -28,14 +28,14 @@ @Component @ConfigurationProperties(prefix = SERVER_UNDO_PREFIX) public class ServerUndoProperties { - private int logSaveDays = DEFAULT_SAVE_DAYS; + private short logSaveDays = DEFAULT_SAVE_DAYS; private long logDeletePeriod = DEFAULT_UNDO_LOG_DELETE_PERIOD; - public int getLogSaveDays() { + public short getLogSaveDays() { return logSaveDays; } - public ServerUndoProperties setLogSaveDays(int logSaveDays) { + public ServerUndoProperties setLogSaveDays(short logSaveDays) { this.logSaveDays = logSaveDays; return this; } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/store/StoreDBProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/store/StoreDBProperties.java index 0bd3c8db313..68771a0764a 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/store/StoreDBProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/properties/server/store/StoreDBProperties.java @@ -42,7 +42,7 @@ public class StoreDBProperties { private String lockTable = "lock_table"; private String distributedLockTable = "distributed_lock"; private Integer queryLimit = DEFAULT_QUERY_LIMIT; - private Integer maxWait = 5000; + private Long maxWait = 5000L; public String getDatasource() { return datasource; @@ -160,11 +160,11 @@ public StoreDBProperties setQueryLimit(Integer queryLimit) { return this; } - public Integer getMaxWait() { + public Long getMaxWait() { return maxWait; } - public StoreDBProperties setMaxWait(Integer maxWait) { + public StoreDBProperties setMaxWait(Long maxWait) { this.maxWait = maxWait; return this; } diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index a4c8cb1b72c..75c09ac2d2a 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -15,7 +15,6 @@ */ package io.seata.server.coordinator; -import java.time.Duration; import java.util.Collection; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; @@ -26,7 +25,6 @@ import io.netty.channel.Channel; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; -import io.seata.common.util.DurationUtil; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.context.RootContext; @@ -142,11 +140,11 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran */ private static final int BRANCH_ASYNC_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; - private static final Duration MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration( - ConfigurationKeys.MAX_COMMIT_RETRY_TIMEOUT, DurationUtil.DEFAULT_DURATION, DEFAULT_MAX_COMMIT_RETRY_TIMEOUT); + private static final long MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getLong( + ConfigurationKeys.MAX_COMMIT_RETRY_TIMEOUT, DEFAULT_MAX_COMMIT_RETRY_TIMEOUT); - private static final Duration MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration( - ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DurationUtil.DEFAULT_DURATION, DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT); + private static final long MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getLong( + ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT); private static final boolean ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE = ConfigurationFactory.getInstance().getBoolean( ConfigurationKeys.ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE, DEFAULT_ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE); @@ -381,7 +379,7 @@ protected void handleRetryRollbacking() { // The function of this 'return' is 'continue'. return; } - if (isRetryTimeout(now, MAX_ROLLBACK_RETRY_TIMEOUT.toMillis(), rollbackingSession.getBeginTime())) { + if (isRetryTimeout(now, MAX_ROLLBACK_RETRY_TIMEOUT, rollbackingSession.getBeginTime())) { if (ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE) { rollbackingSession.clean(); } @@ -422,7 +420,7 @@ protected void handleRetryCommitting() { // The function of this 'return' is 'continue'. return; } - if (isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT.toMillis(), committingSession.getBeginTime())) { + if (isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT, committingSession.getBeginTime())) { // Prevent thread safety issues SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(committingSession); LOGGER.error("Global transaction commit retry timeout and has removed [{}]", committingSession.getXid()); diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java index c83eefdc30c..594d92c0188 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java @@ -16,7 +16,6 @@ package io.seata.server.coordinator; import java.io.IOException; -import java.time.Duration; import java.util.Collection; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; @@ -24,9 +23,9 @@ import java.util.stream.Stream; import io.netty.channel.Channel; +import io.seata.common.DefaultValues; import io.seata.common.XID; import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.DurationUtil; import io.seata.common.util.NetUtil; import io.seata.common.util.ReflectionUtil; import io.seata.config.Configuration; @@ -61,6 +60,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; + /** * The type DefaultCoordinator test. * @@ -169,7 +169,7 @@ public void test_handleRetryRollbackingTimeOut() throws TransactionException, In Assertions.assertNotNull(globalSession.getBranchSessions()); Assertions.assertNotNull(branchId); - ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "MAX_ROLLBACK_RETRY_TIMEOUT", Duration.ofMillis(10)); + ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "MAX_ROLLBACK_RETRY_TIMEOUT", 10L); ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE", false); TimeUnit.MILLISECONDS.sleep(100); globalSession.queueToRetryRollback(); @@ -180,7 +180,7 @@ public void test_handleRetryRollbackingTimeOut() throws TransactionException, In } finally { globalSession.closeAndClean(); ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "MAX_ROLLBACK_RETRY_TIMEOUT", - ConfigurationFactory.getInstance().getDuration(ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DurationUtil.DEFAULT_DURATION, 100)); + ConfigurationFactory.getInstance().getLong(ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DefaultValues.DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT)); } } @@ -196,7 +196,7 @@ public void test_handleRetryRollbackingTimeOut_unlock() throws TransactionExcept Assertions.assertNotNull(globalSession.getBranchSessions()); Assertions.assertNotNull(branchId); - ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "MAX_ROLLBACK_RETRY_TIMEOUT", Duration.ofMillis(10)); + ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "MAX_ROLLBACK_RETRY_TIMEOUT", 10L); ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE", true); TimeUnit.MILLISECONDS.sleep(100); @@ -209,7 +209,7 @@ public void test_handleRetryRollbackingTimeOut_unlock() throws TransactionExcept } finally { globalSession.closeAndClean(); ReflectionUtil.modifyStaticFinalField(defaultCoordinator.getClass(), "MAX_ROLLBACK_RETRY_TIMEOUT", - ConfigurationFactory.getInstance().getDuration(ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DurationUtil.DEFAULT_DURATION, 100)); + ConfigurationFactory.getInstance().getLong(ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DefaultValues.DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT)); } } diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java index b8f74400ef8..ef455ea6e54 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -288,8 +288,8 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) Class serviceInterface = SpringProxyUtils.findTargetClass(bean); Class[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean); - if (!existsAnnotation(new Class[]{serviceInterface}) - && !existsAnnotation(interfacesIfJdk)) { + if (!existsAnnotation(serviceInterface) + && !existsAnnotation(interfacesIfJdk)) { return bean; } @@ -302,7 +302,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) interceptor = globalTransactionalInterceptor; } - LOGGER.info("Bean[{}] with name [{}] would use interceptor [{}]", bean.getClass().getName(), beanName, interceptor.getClass().getName()); + LOGGER.info("Bean [{}] with name [{}] would use interceptor [{}]", bean.getClass().getName(), beanName, interceptor.getClass().getName()); if (!AopUtils.isAopProxy(bean)) { bean = super.wrapIfNecessary(bean, beanName, cacheKey); } else { @@ -325,7 +325,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) private boolean doCheckers(Object bean, String beanName) { if (PROXYED_SET.contains(beanName) || EXCLUDE_BEAN_NAME_SET.contains(beanName) - || FactoryBean.class.isAssignableFrom(bean.getClass())) { + || FactoryBean.class.isAssignableFrom(bean.getClass())) { return false; } @@ -461,7 +461,7 @@ private boolean isTransactionInterceptor(Advisor advisor) { //endregion the methods about findAddSeataAdvisorPosition END - private boolean existsAnnotation(Class[] classes) { + private boolean existsAnnotation(Class... classes) { if (CollectionUtils.isNotEmpty(classes)) { for (Class clazz : classes) { if (clazz == null) { diff --git a/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java b/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java index a3b50c84119..b5fdb69d4d3 100644 --- a/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java +++ b/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java @@ -88,6 +88,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) DataSource origin = (DataSource) bean; SeataDataSourceProxy proxy = buildProxy(origin, dataSourceProxyMode); DataSourceProxyHolder.put(origin, proxy); + LOGGER.info("Auto proxy data source '{}' by '{}' mode.", beanName, dataSourceProxyMode); return enhancer; } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/DefaultDruidLoader.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/DefaultDruidLoader.java index a03904bf358..c19ca7d34af 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/DefaultDruidLoader.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/DefaultDruidLoader.java @@ -22,14 +22,12 @@ import java.net.URL; import java.security.CodeSource; +import static io.seata.common.DefaultValues.DRUID_LOCATION; + /** * @author ggndnn */ class DefaultDruidLoader implements DruidLoader { - /** - * Default druid location in classpath - */ - private final static String DRUID_LOCATION = "lib/sqlparser/druid.jar"; private final static DefaultDruidLoader DRUID_LOADER = new DefaultDruidLoader(DRUID_LOCATION); From 4527a41a756479e823e52048145f8759d8e6f3c2 Mon Sep 17 00:00:00 2001 From: jimin Date: Sun, 29 Jan 2023 21:02:47 +0800 Subject: [PATCH 16/76] optimize: optimize workflow for 2.x (#5268) --- .github/workflows/build.yml | 6 ++-- .github/workflows/codeql-analysis.yml | 4 +-- .github/workflows/license-checker.yaml | 6 ++-- .github/workflows/publishes.yml | 2 +- .licenserc.yaml | 1 + build/pom.xml | 2 +- .../java/io/seata/core/protocol/Version.java | 2 +- .../serializer/kryo/KryoSerializerTest.java | 34 +++++++++++++++++++ 8 files changed, 45 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 53a38906e9a..9c8db4f4d44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,14 +2,14 @@ name: "build" on: push: - branches: [ develop, master ] + branches: [ 2.x, develop, master ] pull_request: - branches: [ develop, master ] + branches: [ 2.x, develop, master ] jobs: build_arm64-binary: runs-on: ubuntu-latest - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/2.x') }} strategy: fail-fast: false steps: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d4dee337b2f..f7f2c925fac 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -12,11 +12,9 @@ name: "CodeQL" on: - push: - branches: [ develop, master ] pull_request: # The branches below must be a subset of the branches above - branches: [ develop ] + branches: [ 2.x, develop ] schedule: - cron: '36 19 * * 6' diff --git a/.github/workflows/license-checker.yaml b/.github/workflows/license-checker.yaml index 5b09707ccac..d3ac84bb88c 100644 --- a/.github/workflows/license-checker.yaml +++ b/.github/workflows/license-checker.yaml @@ -2,7 +2,7 @@ name: License checker on: pull_request: - branches: [ develop, master ] + branches: [ 2.x, develop, master ] jobs: check-license: @@ -13,14 +13,14 @@ jobs: uses: actions/checkout@v2.4.0 # step 2 - name: Check License Header - uses: apache/skywalking-eyes/header@25edfc2fd8d52fb266653fb5f6c42da633d85c07 + uses: apache/skywalking-eyes/header@8fc52baabc14c86294d96034bcc194cfa7f76b05 with: log: info config: .licenserc.yaml mode: check # step 3 - name: Check Dependencies' License - uses: apache/skywalking-eyes/dependency@25edfc2fd8d52fb266653fb5f6c42da633d85c07 + uses: apache/skywalking-eyes/dependency@8fc52baabc14c86294d96034bcc194cfa7f76b05 with: log: info config: .licenserc.yaml diff --git a/.github/workflows/publishes.yml b/.github/workflows/publishes.yml index 55ea8e55cf2..3ab37947947 100644 --- a/.github/workflows/publishes.yml +++ b/.github/workflows/publishes.yml @@ -50,7 +50,7 @@ jobs: REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | - if [ "${{ github.ref_name }}" == "develop" ] || [ "${{ github.ref_name }}" == "snapshot" ]; then + if [ "${{ github.ref_name }}" == "develop" ] || [ "${{ github.ref_name }}" == "snapshot" || [ "${{ github.ref_name }}" == "2.x" ]; then ./mvnw -T 4C clean package -Pimage -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; else ./mvnw -T 4C clean package -Pimage,release-image -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; diff --git a/.licenserc.yaml b/.licenserc.yaml index 4f49c31a6ae..699f39beee0 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -74,6 +74,7 @@ header: - 'console/src/main/resources/static/**' - 'ext/apm-seata-skywalking-plugin/config/agent.config' - 'server/src/main/resources/lua/redislocker/redislock.lua' + - 'server/src/main/resources/banner.txt' comment: on-failure diff --git a/build/pom.xml b/build/pom.xml index 899e27c268a..0e0e2514849 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -63,7 +63,7 @@ - 1.6.1 + 1.7.0-SNAPSHOT 1.8 diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java index ec64f8816d6..56e96f47c9e 100644 --- a/core/src/main/java/io/seata/core/protocol/Version.java +++ b/core/src/main/java/io/seata/core/protocol/Version.java @@ -36,7 +36,7 @@ public class Version { /** * The constant CURRENT. */ - private static final String CURRENT = "1.6.1"; + private static final String CURRENT = "1.7.0-SNAPSHOT"; private static final String VERSION_0_7_1 = "0.7.1"; private static final String VERSION_1_5_0 = "1.5.0"; private static final int MAX_VERSION_DOT = 3; diff --git a/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java b/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java index b90ff04bb0a..74eb4eac343 100644 --- a/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java +++ b/serializer/seata-serializer-kryo/src/test/java/io/seata/serializer/kryo/KryoSerializerTest.java @@ -15,7 +15,14 @@ */ package io.seata.serializer.kryo; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.HashMap; +import java.util.Map; + import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; import io.seata.core.exception.TransactionExceptionCode; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; @@ -95,4 +102,31 @@ public void testBranchCommitResponse() { } + @Test + public void testKryoBasic() { + Kryo kryo = new Kryo(); + kryo.setReferences(true); + kryo.setRegistrationRequired(false); + //kryo.register(HashMap.class); + + long beginMills=System.currentTimeMillis(); + for (int i = 0; i < 1; i++) { + Map map = new HashMap<>(); + map.put(String.valueOf(i), "test"); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Output output = new Output(outputStream); + kryo.writeClassAndObject(output, map); + output.close(); + byte[] outByte = outputStream.toByteArray(); + + ByteArrayInputStream inputStream = new ByteArrayInputStream(outByte); + Input input = new Input(inputStream); + input.close(); + Map result = (HashMap)kryo.readClassAndObject(input); + assertThat(result).isEqualTo(map); + } + //System.out.println(System.currentTimeMillis()-beginMills); + } + } From 851ed6d28b40719482ff7ac0dfc02a517d04f1e1 Mon Sep 17 00:00:00 2001 From: GoodBoyCoder <41784017+GoodBoyCoder@users.noreply.github.com> Date: Wed, 1 Feb 2023 10:40:58 +0800 Subject: [PATCH 17/76] =?UTF-8?q?optimize:=20fix=20the=20problem=20that=20?= =?UTF-8?q?protobuf=20compilation=20fails=EF=BC=88for=20dev=EF=BC=89=20(#5?= =?UTF-8?q?274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/pom.xml | 5 +++++ changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ 3 files changed, 9 insertions(+) diff --git a/build/pom.xml b/build/pom.xml index 0e0e2514849..6a94233df26 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -163,6 +163,11 @@ org.xolstice.maven.plugins protobuf-maven-plugin ${protobuf-maven-plugin.version} + + + true + com.mycila diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index af224973635..3809e01b36c 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -21,6 +21,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5243](https://github.com/seata/seata/pull/5243)] optimize kryo 5.4.0 optimize compatibility with jdk17 - [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app - [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. +- [[#5273](https://github.com/seata/seata/pull/5273)] Optimize the compilation configuration of the `protobuf-maven-plugin` plug-in to solve the problem of too long command lines in higher versions. ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities @@ -41,6 +42,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [Bughue](https://github.com/Bughue) - [pengten](https://github.com/pengten) - [wangliang181230](https://github.com/wangliang181230) +- [GoodBoyCoder](https://github.com/GoodBoyCoder) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 2d91a3337d7..ece3fb7db9d 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -21,6 +21,7 @@ - [[#5243](https://github.com/seata/seata/pull/5243)] 升级 kryo 5.4.0 优化对jdk17的兼容性 - [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel - [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 +- [[#5273](https://github.com/seata/seata/pull/5273)] 优化`protobuf-maven-plugin`插件的编译配置,解决高版本的命令行过长问题 ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 @@ -41,6 +42,7 @@ - [Bughue](https://github.com/Bughue) - [pengten](https://github.com/pengten) - [wangliang181230](https://github.com/wangliang181230) +- [GoodBoyCoder](https://github.com/GoodBoyCoder) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 From fb3d5c7104b8917caed8c85b8cf3e8441ca3a53d Mon Sep 17 00:00:00 2001 From: renliangyu857 <2918490262@qq.com> Date: Wed, 1 Feb 2023 17:35:43 +0800 Subject: [PATCH 18/76] bugfix: the console has queried the released lock (#5266) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../impl/file/GlobalLockFileServiceImpl.java | 3 +++ .../io/seata/server/lock/LockManagerTest.java | 27 +++++++++++++++++-- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 3809e01b36c..9372318c00f 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -11,6 +11,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5023](https://github.com/seata/seata/pull/5203)] Fix `seata-core` dependency transitive conflict in `seata-dubbo` - [[#5224](https://github.com/seata/seata/pull/5224)] fix oracle initialize script index_name is duplicate - [[#5233](https://github.com/seata/seata/pull/5233)] fix the inconsistent configuration item names related to LoadBalance +- [[#5266](https://github.com/seata/seata/pull/5265)] fix server console has queried the released lock - [[#5245](https://github.com/seata/seata/pull/5245)] fix the incomplete dependency of distribution module - [[#5239](https://github.com/seata/seata/pull/5239)] fix `getConfig` throw `ClassCastException` when use JDK proxy diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index ece3fb7db9d..f1cd49437be 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -11,6 +11,7 @@ - [[#5023](https://github.com/seata/seata/pull/5203)] 修复 `seata-core` 模块传递依赖冲突 - [[#5224](https://github.com/seata/seata/pull/5224)] 修复 oracle初始化脚本索引名重复的问题 - [[#5233](https://github.com/seata/seata/pull/5233)] 修复LoadBalance相关配置不一致的问题 +- [[#5266](https://github.com/seata/seata/pull/5265)] 修复控制台全局锁查询接口查到了已释放的锁 - [[#5245](https://github.com/seata/seata/pull/5245)] 修复不完整的distribution模块依赖 - [[#5239](https://github.com/seata/seata/pull/5239)] 修复当使用JDK代理时,`getConfig` 方法获取部分配置时抛出 `ClassCastException` 异常的问题 diff --git a/server/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java b/server/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java index edfdc633b30..60309581584 100644 --- a/server/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java +++ b/server/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java @@ -80,6 +80,9 @@ public PageResult query(GlobalLockParam param) { * @return the RowLock list */ private Stream filterAndMap(GlobalLockParam param, BranchSession branchSession) { + if (CollectionUtils.isEmpty(branchSession.getLockHolder())) { + return Stream.empty(); + } final String tableName = param.getTableName(); diff --git a/server/src/test/java/io/seata/server/lock/LockManagerTest.java b/server/src/test/java/io/seata/server/lock/LockManagerTest.java index fea75ba3fcc..d661455298f 100644 --- a/server/src/test/java/io/seata/server/lock/LockManagerTest.java +++ b/server/src/test/java/io/seata/server/lock/LockManagerTest.java @@ -236,10 +236,19 @@ public void lockQueryTest(GlobalSession globalSessions1, GlobalSession globalSes // wrong pageSize or pageNum Assertions.assertThrows( - IllegalArgumentException.class, - () -> globalLockService.query(param) + IllegalArgumentException.class, + () -> globalLockService.query(param) ); + LockManager lockManager = new FileLockManagerForTest(); + for (BranchSession branchSession : globalSessions1.getBranchSessions()) { + lockManager.acquireLock(branchSession); + } + + for (BranchSession branchSession : globalSessions2.getBranchSessions()) { + lockManager.acquireLock(branchSession); + } + param.setPageNum(1); param.setPageSize(10); @@ -318,6 +327,20 @@ public void lockQueryTest(GlobalSession globalSessions1, GlobalSession globalSes final PageResult timeTestResult4 = globalLockService.query(param); Assertions.assertEquals(4, timeTestResult4.getTotal()); + //test release lock + for (BranchSession branchSession : globalSessions1.getBranchSessions()) { + lockManager.releaseLock(branchSession); + } + + final GlobalLockParam param2 = new GlobalLockParam(); + param2.setPageNum(1); + param2.setPageSize(10); + + final PageResult fullQueryTestResult2 = globalLockService.query(param2); + Assertions.assertEquals(1,fullQueryTestResult2.getPages()); + Assertions.assertEquals(4,fullQueryTestResult2.getTotal()); + Assertions.assertEquals(4,fullQueryTestResult2.getData().size()); + } finally { sessionManager.removeGlobalSession(globalSessions1); sessionManager.removeGlobalSession(globalSessions2); From cee99cdf2cd56244bda017858404cf89863e8f9d Mon Sep 17 00:00:00 2001 From: FUNKYE <364176773@qq.com> Date: Thu, 2 Feb 2023 13:57:06 +0800 Subject: [PATCH 19/76] bugfix: parallel request handle throw IndexOutOfBoundsException (#5281) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../server/ServerOnRequestProcessor.java | 15 +++++++-------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 9372318c00f..dcf297f77fa 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -14,6 +14,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5266](https://github.com/seata/seata/pull/5265)] fix server console has queried the released lock - [[#5245](https://github.com/seata/seata/pull/5245)] fix the incomplete dependency of distribution module - [[#5239](https://github.com/seata/seata/pull/5239)] fix `getConfig` throw `ClassCastException` when use JDK proxy +- [[#5281](https://github.com/seata/seata/pull/5281)] parallel request handle throw IndexOutOfBoundsException ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more @@ -44,6 +45,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [pengten](https://github.com/pengten) - [wangliang181230](https://github.com/wangliang181230) - [GoodBoyCoder](https://github.com/GoodBoyCoder) +- [a364176773](https://github.com/a364176773) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index f1cd49437be..74646d2bb0b 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -14,6 +14,7 @@ - [[#5266](https://github.com/seata/seata/pull/5265)] 修复控制台全局锁查询接口查到了已释放的锁 - [[#5245](https://github.com/seata/seata/pull/5245)] 修复不完整的distribution模块依赖 - [[#5239](https://github.com/seata/seata/pull/5239)] 修复当使用JDK代理时,`getConfig` 方法获取部分配置时抛出 `ClassCastException` 异常的问题 +- [[#5281](https://github.com/seata/seata/pull/5281)] 修复并行rm请求处理时数组索引越界问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 @@ -44,6 +45,7 @@ - [pengten](https://github.com/pengten) - [wangliang181230](https://github.com/wangliang181230) - [GoodBoyCoder](https://github.com/GoodBoyCoder) +- [a364176773](https://github.com/a364176773) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java index b5933444384..5701de4b711 100644 --- a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java +++ b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java @@ -24,7 +24,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; @@ -179,18 +178,16 @@ private void onRequestMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) } } } else { - List results = new CopyOnWriteArrayList<>(); - List> completableFutures = null; + List results = new ArrayList<>(); + List> completableFutures = null; for (int i = 0; i < ((MergedWarpMessage)message).msgs.size(); i++) { if (PARALLEL_REQUEST_HANDLE) { if (completableFutures == null) { completableFutures = new ArrayList<>(); } int finalI = i; - completableFutures.add(CompletableFuture.runAsync(() -> { - results.add(finalI, handleRequestsByMergedWarpMessage( - ((MergedWarpMessage)message).msgs.get(finalI), rpcContext)); - })); + completableFutures.add(CompletableFuture.supplyAsync(() -> handleRequestsByMergedWarpMessage( + ((MergedWarpMessage)message).msgs.get(finalI), rpcContext))); } else { results.add(i, handleRequestsByMergedWarpMessage(((MergedWarpMessage)message).msgs.get(i), rpcContext)); @@ -198,7 +195,9 @@ private void onRequestMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) } if (CollectionUtils.isNotEmpty(completableFutures)) { try { - CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).get(); + for (CompletableFuture completableFuture : completableFutures) { + results.add(completableFuture.get()); + } } catch (InterruptedException | ExecutionException e) { LOGGER.error("handle request error: {}", e.getMessage(), e); } From 9464294cef9865051f217810265c0a883dc09c51 Mon Sep 17 00:00:00 2001 From: isharpever <36060365+isharpever@users.noreply.github.com> Date: Fri, 3 Feb 2023 11:30:25 +0800 Subject: [PATCH 20/76] bugfix: After 1.6.0, auto-increment of pgsql pk columns are no longer supported (#5287) --- changes/en-us/develop.md | 2 + changes/zh-cn/develop.md | 2 + .../postgresql/PostgresqlInsertExecutor.java | 52 ++++++- .../exec/PostgresqlInsertExecutorTest.java | 147 +++++++++++++++++- 4 files changed, 201 insertions(+), 2 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index dcf297f77fa..da1c53be175 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -15,6 +15,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5245](https://github.com/seata/seata/pull/5245)] fix the incomplete dependency of distribution module - [[#5239](https://github.com/seata/seata/pull/5239)] fix `getConfig` throw `ClassCastException` when use JDK proxy - [[#5281](https://github.com/seata/seata/pull/5281)] parallel request handle throw IndexOutOfBoundsException +- [[#5287](https://github.com/seata/seata/pull/5287)] fix auto-increment of pk columns in PostgreSQL in AT mode ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more @@ -46,6 +47,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [wangliang181230](https://github.com/wangliang181230) - [GoodBoyCoder](https://github.com/GoodBoyCoder) - [a364176773](https://github.com/a364176773) +- [isharpever](https://github.com/isharpever) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 74646d2bb0b..238f6492182 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -15,6 +15,7 @@ - [[#5245](https://github.com/seata/seata/pull/5245)] 修复不完整的distribution模块依赖 - [[#5239](https://github.com/seata/seata/pull/5239)] 修复当使用JDK代理时,`getConfig` 方法获取部分配置时抛出 `ClassCastException` 异常的问题 - [[#5281](https://github.com/seata/seata/pull/5281)] 修复并行rm请求处理时数组索引越界问题 +- [[#5287](https://github.com/seata/seata/pull/5287)] 修复AT模式下pgsql的主键列自增的问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 @@ -46,6 +47,7 @@ - [wangliang181230](https://github.com/wangliang181230) - [GoodBoyCoder](https://github.com/GoodBoyCoder) - [a364176773](https://github.com/a364176773) +- [isharpever](https://github.com/isharpever) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java index 5610b86f0cd..9f6ff0f8ef9 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java @@ -18,22 +18,26 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; import io.seata.common.loader.Scope; +import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.BaseInsertExecutor; import io.seata.rm.datasource.exec.StatementCallback; import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.struct.Defaultable; import io.seata.sqlparser.struct.Sequenceable; import io.seata.sqlparser.struct.SqlMethodExpr; import io.seata.sqlparser.struct.SqlSequenceExpr; import io.seata.sqlparser.struct.SqlDefaultExpr; +import io.seata.sqlparser.util.ColumnUtils; import io.seata.sqlparser.util.JdbcConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.SQLException; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -60,9 +64,55 @@ public PostgresqlInsertExecutor(StatementProxy statementProxy, StatementCallback super(statementProxy, statementCallback, sqlRecognizer); } + /** + * 1. If the insert columns are not empty and do not contain any pk columns, + * it means that there is no pk value in the insert rows, then all the pk values should come from auto-increment. + *

+ * 2. The pk value exists in insert rows. The possible situations are: + *

    + *
  • The insert columns are empty: all pk values can be obtained from insert rows
  • + *
  • The insert columns contain at least one pk column: first obtain the existing pk value from the insert rows, and other from auto-increment
  • + *
+ * + * @return {@link Map}<{@link String}, {@link List}<{@link Object}>> + * @throws SQLException the sql exception + */ @Override public Map> getPkValues() throws SQLException { - return getPkValuesByColumn(); + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + Map> pkValuesMap = new HashMap<>(pkColumnNameList.size()); + + // first obtain the existing pk value from the insert rows (if exists) + if (!containsColumns() || containsAnyPk()) { + pkValuesMap.putAll(getPkValuesByColumn()); + } + // other from auto-increment + for (String columnName : pkColumnNameList) { + if (!pkValuesMap.containsKey(columnName)) { + pkValuesMap.put(columnName, getGeneratedKeys(columnName)); + } + } + return pkValuesMap; + } + + /** + * Whether the insert columns contain any pk columns + * + * @return true: contain at least one pk column. false: do not contain any pk columns + */ + public boolean containsAnyPk() { + SQLInsertRecognizer recognizer = (SQLInsertRecognizer)sqlRecognizer; + List insertColumns = recognizer.getInsertColumns(); + if (CollectionUtils.isEmpty(insertColumns)) { + return false; + } + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + if (CollectionUtils.isEmpty(pkColumnNameList)) { + return false; + } + List newColumns = ColumnUtils.delEscape(insertColumns, getDbType()); + return pkColumnNameList.stream().anyMatch(pkColumn -> newColumns.contains(pkColumn) + || CollectionUtils.toUpperList(newColumns).contains(pkColumn.toUpperCase())); } @Override diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java index 198604f52ff..1acad8d40ab 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java @@ -29,7 +29,13 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import java.util.*; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -145,6 +151,145 @@ public void testInsertDefault_ByDefault_MultiPk() throws Exception { Assertions.assertEquals(pkValuesMap.get(USER_ID_COLUMN), pkValuesAutoUserId); } + @Test + public void testGetPkValues_SinglePk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock pk values from insert rows + Map> mockPkValuesFromColumn = new HashMap<>(); + mockPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + + // situation1: insert columns are empty + List columns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain the pk column + columns = new ArrayList<>(); + columns.add(ID_COLUMN); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns are not empty and do not contain the pk column + columns = new ArrayList<>(); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals( + Collections.singletonMap(ID_COLUMN, mockPkValuesAutoGenerated).entrySet(), + insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testGetPkValues_MultiPk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock all pk values from insert rows + Map> mockAllPkValuesFromColumn = new HashMap<>(); + mockAllPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + mockAllPkValuesFromColumn.put(USER_ID_COLUMN, Collections.singletonList(PK_VALUE_USER_ID + 1)); + doReturn(mockAllPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated_ID = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated_ID).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + List mockPkValuesAutoGenerated_USER_ID = Collections.singletonList(PK_VALUE_USER_ID); + doReturn(mockPkValuesAutoGenerated_USER_ID).when(insertExecutor).getGeneratedKeys(USER_ID_COLUMN); + + // situation1: insert columns are empty + List insertColumns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain all pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns contain partial pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + Map> mockPkValuesFromColumn_ID = new HashMap<>(); + mockPkValuesFromColumn_ID.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn_ID).when(insertExecutor).getPkValuesByColumn(); + + Map> expectPkValues = new HashMap<>(mockPkValuesFromColumn_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation4: insert columns are not empty and do not contain the pk column + insertColumns = new ArrayList<>(); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + doReturn(new HashMap<>()).when(insertExecutor).getPkValuesByColumn(); + + expectPkValues = new HashMap<>(); + expectPkValues.put(ID_COLUMN, mockPkValuesAutoGenerated_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testContainsAnyPK() { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + mockInsertColumns(); + doReturn(null).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + List pkColumns = new ArrayList<>(); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + } + private void mockParametersPkWithDefault() { Map> parameters = new HashMap<>(4); ArrayList arrayList0 = new ArrayList<>(); From 01a1ff98bd701c793fe970e1ce4ac70db48c5331 Mon Sep 17 00:00:00 2001 From: isharpever <36060365+isharpever@users.noreply.github.com> Date: Fri, 3 Feb 2023 12:31:38 +0800 Subject: [PATCH 21/76] bugfix: After 1.6.0, auto-increment of oracle pk columns are no longer supported (#5288) --- changes/en-us/develop.md | 2 + changes/zh-cn/develop.md | 2 + .../exec/oracle/OracleInsertExecutor.java | 52 ++++++- .../exec/OracleInsertExecutorTest.java | 140 ++++++++++++++++++ 4 files changed, 195 insertions(+), 1 deletion(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index da1c53be175..6780d3be941 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -15,8 +15,10 @@ Add changes here for all PR submitted to the develop branch. - [[#5245](https://github.com/seata/seata/pull/5245)] fix the incomplete dependency of distribution module - [[#5239](https://github.com/seata/seata/pull/5239)] fix `getConfig` throw `ClassCastException` when use JDK proxy - [[#5281](https://github.com/seata/seata/pull/5281)] parallel request handle throw IndexOutOfBoundsException +- [[#5288](https://github.com/seata/seata/pull/5288)] fix auto-increment of pk columns in Oracle in AT mode - [[#5287](https://github.com/seata/seata/pull/5287)] fix auto-increment of pk columns in PostgreSQL in AT mode + ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 238f6492182..4091ea8e7ab 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -15,8 +15,10 @@ - [[#5245](https://github.com/seata/seata/pull/5245)] 修复不完整的distribution模块依赖 - [[#5239](https://github.com/seata/seata/pull/5239)] 修复当使用JDK代理时,`getConfig` 方法获取部分配置时抛出 `ClassCastException` 异常的问题 - [[#5281](https://github.com/seata/seata/pull/5281)] 修复并行rm请求处理时数组索引越界问题 +- [[#5288](https://github.com/seata/seata/pull/5288)] 修复AT模式下oracle的主键列自增的问题 - [[#5287](https://github.com/seata/seata/pull/5287)] 修复AT模式下pgsql的主键列自增的问题 + ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/oracle/OracleInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/oracle/OracleInsertExecutor.java index e4220026c2e..deec875345e 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/oracle/OracleInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/oracle/OracleInsertExecutor.java @@ -17,19 +17,23 @@ import io.seata.common.loader.LoadLevel; import io.seata.common.loader.Scope; +import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.BaseInsertExecutor; import io.seata.rm.datasource.exec.StatementCallback; +import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.struct.Null; import io.seata.sqlparser.struct.Sequenceable; import io.seata.sqlparser.struct.SqlMethodExpr; import io.seata.sqlparser.struct.SqlSequenceExpr; +import io.seata.sqlparser.util.ColumnUtils; import io.seata.sqlparser.util.JdbcConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.SQLException; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -56,9 +60,55 @@ public OracleInsertExecutor(StatementProxy statementProxy, StatementCallback sta super(statementProxy, statementCallback, sqlRecognizer); } + /** + * 1. If the insert columns are not empty and do not contain any pk columns, + * it means that there is no pk value in the insert rows, then all the pk values should come from auto-increment. + *

+ * 2. The pk value exists in insert rows. The possible situations are: + *

    + *
  • The insert columns are empty: all pk values can be obtained from insert rows
  • + *
  • The insert columns contain at least one pk column: first obtain the existing pk value from the insert rows, and other from auto-increment
  • + *
+ * + * @return {@link Map}<{@link String}, {@link List}<{@link Object}>> + * @throws SQLException the sql exception + */ @Override public Map> getPkValues() throws SQLException { - return getPkValuesByColumn(); + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + Map> pkValuesMap = new HashMap<>(pkColumnNameList.size()); + + // first obtain the existing pk value from the insert rows (if exists) + if (!containsColumns() || containsAnyPk()) { + pkValuesMap.putAll(getPkValuesByColumn()); + } + // other from auto-increment + for (String columnName : pkColumnNameList) { + if (!pkValuesMap.containsKey(columnName)) { + pkValuesMap.put(columnName, getGeneratedKeys(columnName)); + } + } + return pkValuesMap; + } + + /** + * Whether the insert columns contain any pk columns + * + * @return true: contain at least one pk column. false: do not contain any pk columns + */ + public boolean containsAnyPk() { + SQLInsertRecognizer recognizer = (SQLInsertRecognizer)sqlRecognizer; + List insertColumns = recognizer.getInsertColumns(); + if (CollectionUtils.isEmpty(insertColumns)) { + return false; + } + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + if (CollectionUtils.isEmpty(pkColumnNameList)) { + return false; + } + List newColumns = ColumnUtils.delEscape(insertColumns, getDbType()); + return pkColumnNameList.stream().anyMatch(pkColumn -> newColumns.contains(pkColumn) + || CollectionUtils.toUpperList(newColumns).contains(pkColumn.toUpperCase())); } @Override diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java index 3397f9ab7bd..b6dcdde79bf 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java @@ -32,8 +32,10 @@ import org.mockito.Mockito; import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -198,6 +200,144 @@ public void testStatement_pkValueByAuto_NotSupportYetException() throws Exceptio } + @Test + public void testGetPkValues_SinglePk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock pk values from insert rows + Map> mockPkValuesFromColumn = new HashMap<>(); + mockPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + + // situation1: insert columns are empty + List columns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain the pk column + columns = new ArrayList<>(); + columns.add(ID_COLUMN); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns are not empty and do not contain the pk column + columns = new ArrayList<>(); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals( + Collections.singletonMap(ID_COLUMN, mockPkValuesAutoGenerated).entrySet(), + insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testGetPkValues_MultiPk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock all pk values from insert rows + Map> mockAllPkValuesFromColumn = new HashMap<>(); + mockAllPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + mockAllPkValuesFromColumn.put(USER_ID_COLUMN, Collections.singletonList(PK_VALUE_USER_ID + 1)); + doReturn(mockAllPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated_ID = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated_ID).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + List mockPkValuesAutoGenerated_USER_ID = Collections.singletonList(PK_VALUE_USER_ID); + doReturn(mockPkValuesAutoGenerated_USER_ID).when(insertExecutor).getGeneratedKeys(USER_ID_COLUMN); + + // situation1: insert columns are empty + List insertColumns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain all pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns contain partial pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + Map> mockPkValuesFromColumn_ID = new HashMap<>(); + mockPkValuesFromColumn_ID.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn_ID).when(insertExecutor).getPkValuesByColumn(); + + Map> expectPkValues = new HashMap<>(mockPkValuesFromColumn_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation4: insert columns are not empty and do not contain the pk column + insertColumns = new ArrayList<>(); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + doReturn(new HashMap<>()).when(insertExecutor).getPkValuesByColumn(); + + expectPkValues = new HashMap<>(); + expectPkValues.put(ID_COLUMN, mockPkValuesAutoGenerated_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testContainsAnyPK() { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + mockInsertColumns(); + doReturn(null).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + List pkColumns = new ArrayList<>(); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + } private List mockInsertColumns() { List columns = new ArrayList<>(); From bf5586f93b1b598fed6c67a6fe17991e6bb22cb1 Mon Sep 17 00:00:00 2001 From: mxsm Date: Mon, 6 Feb 2023 14:21:21 +0800 Subject: [PATCH 22/76] optimize: remove startup script the -Xmn configuration (#5303) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ distribution/bin/seata-server.bat | 2 +- distribution/bin/seata-server.sh | 3 +-- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 6780d3be941..531aa66ad5a 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -27,6 +27,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app - [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. - [[#5273](https://github.com/seata/seata/pull/5273)] Optimize the compilation configuration of the `protobuf-maven-plugin` plug-in to solve the problem of too long command lines in higher versions. +- [[#5303](https://github.com/seata/seata/pull/5303)] remove startup script the -Xmn configuration ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities @@ -50,6 +51,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [GoodBoyCoder](https://github.com/GoodBoyCoder) - [a364176773](https://github.com/a364176773) - [isharpever](https://github.com/isharpever) +- [mxsm](https://github.com/mxsm) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 4091ea8e7ab..c2d06243779 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -27,6 +27,7 @@ - [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel - [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 - [[#5273](https://github.com/seata/seata/pull/5273)] 优化`protobuf-maven-plugin`插件的编译配置,解决高版本的命令行过长问题 +- [[#5303](https://github.com/seata/seata/pull/5303)] 移除启动脚本的-Xmn参数 ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 @@ -50,6 +51,7 @@ - [GoodBoyCoder](https://github.com/GoodBoyCoder) - [a364176773](https://github.com/a364176773) - [isharpever](https://github.com/isharpever) +- [mxsm](https://github.com/mxsm) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/distribution/bin/seata-server.bat b/distribution/bin/seata-server.bat index 04c51a38d8e..d94527ab236 100644 --- a/distribution/bin/seata-server.bat +++ b/distribution/bin/seata-server.bat @@ -93,7 +93,7 @@ if "%SKYWALKING_ENABLE%"=="true" ( echo "apm-skywalking not enabled" ) -%JAVACMD% %JAVA_OPTS% %SKYWALKING_OPTS% -server -Dloader.path="%BASEDIR%"/lib -Xmx2048m -Xms2048m -Xmn1024m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="%BASEDIR%"/logs/java_heapdump.hprof -XX:+DisableExplicitGC -Xloggc:"%BASEDIR%"/logs/seata_gc.log -verbose:gc -Dio.netty.leakDetectionLevel=advanced -classpath %CLASSPATH% -Dapp.name="seata-server" -Dapp.repo="%REPO%" -Dapp.home="%BASEDIR%" -Dbasedir="%BASEDIR%" -Dspring.config.location="%BASEDIR%"/conf/application.yml -Dlogging.config="%BASEDIR%"/conf/logback-spring.xml -jar "%BASEDIR%"/target/seata-server.jar %CMD_LINE_ARGS% +%JAVACMD% %JAVA_OPTS% %SKYWALKING_OPTS% -server -Dloader.path="%BASEDIR%"/lib -Xmx2048m -Xms2048m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="%BASEDIR%"/logs/java_heapdump.hprof -XX:+DisableExplicitGC -Xloggc:"%BASEDIR%"/logs/seata_gc.log -verbose:gc -Dio.netty.leakDetectionLevel=advanced -classpath %CLASSPATH% -Dapp.name="seata-server" -Dapp.repo="%REPO%" -Dapp.home="%BASEDIR%" -Dbasedir="%BASEDIR%" -Dspring.config.location="%BASEDIR%"/conf/application.yml -Dlogging.config="%BASEDIR%"/conf/logback-spring.xml -jar "%BASEDIR%"/target/seata-server.jar %CMD_LINE_ARGS% if %ERRORLEVEL% NEQ 0 goto error goto end diff --git a/distribution/bin/seata-server.sh b/distribution/bin/seata-server.sh index bd181f395a8..2ed77251532 100644 --- a/distribution/bin/seata-server.sh +++ b/distribution/bin/seata-server.sh @@ -121,13 +121,12 @@ else fi JVM_XMX=$JVM_XMX JVM_XMS=$JVM_XMS -JVM_XMN=$JVM_XMN JVM_XSS=$JVM_XSS JVM_MetaspaceSize=$JVM_MetaspaceSize JVM_MaxMetaspaceSize=$JVM_MaxMetaspaceSize JVM_MaxDirectMemorySize=$JVM_MaxDirectMemorySize LOADER_PATH=$LOADER_PATH -JAVA_OPT="${JAVA_OPT} -server -Dloader.path=${LOADER_PATH:="$BASEDIR/lib"} -Xmx${JVM_XMX:="2048m"} -Xms${JVM_XMS:="2048m"} -Xmn${JVM_XMN:="1024m"} -Xss${JVM_XSS:="512k"} -XX:SurvivorRatio=10 -XX:MetaspaceSize=${JVM_MetaspaceSize:="128m"} -XX:MaxMetaspaceSize=${JVM_MaxMetaspaceSize:="256m"} -XX:MaxDirectMemorySize=${JVM_MaxDirectMemorySize:=1024m} -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy" +JAVA_OPT="${JAVA_OPT} -server -Dloader.path=${LOADER_PATH:="$BASEDIR/lib"} -Xmx${JVM_XMX:="2048m"} -Xms${JVM_XMS:="2048m"} -Xss${JVM_XSS:="512k"} -XX:SurvivorRatio=10 -XX:MetaspaceSize=${JVM_MetaspaceSize:="128m"} -XX:MaxMetaspaceSize=${JVM_MaxMetaspaceSize:="256m"} -XX:MaxDirectMemorySize=${JVM_MaxDirectMemorySize:=1024m} -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy" JAVA_OPT="${JAVA_OPT} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASEDIR}/logs/java_heapdump.hprof -XX:+DisableExplicitGC" JAVA_MAJOR_VERSION=$($JAVACMD -version 2>&1 | sed '1!d' | sed -e 's/"//g' | awk '{print $3}' | awk -F '.' '{print $1}') From 9a298fd1af6f6e1eb25a04190329818e601ea47b Mon Sep 17 00:00:00 2001 From: FUNKYE <364176773@qq.com> Date: Tue, 7 Feb 2023 13:31:19 +0800 Subject: [PATCH 23/76] bugfix: that keywords don't add escaped characters (#5307) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 2 +- .../rm/datasource/exec/UpdateExecutor.java | 30 +++++++++---------- .../exec/mysql/MySQLUpdateJoinExecutor.java | 10 ++----- .../datasource/exec/UpdateExecutorTest.java | 16 ++++++++-- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 531aa66ad5a..ae5e4336ca8 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -17,6 +17,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5281](https://github.com/seata/seata/pull/5281)] parallel request handle throw IndexOutOfBoundsException - [[#5288](https://github.com/seata/seata/pull/5288)] fix auto-increment of pk columns in Oracle in AT mode - [[#5287](https://github.com/seata/seata/pull/5287)] fix auto-increment of pk columns in PostgreSQL in AT mode +- [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index c2d06243779..f2dce728093 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -17,7 +17,7 @@ - [[#5281](https://github.com/seata/seata/pull/5281)] 修复并行rm请求处理时数组索引越界问题 - [[#5288](https://github.com/seata/seata/pull/5288)] 修复AT模式下oracle的主键列自增的问题 - [[#5287](https://github.com/seata/seata/pull/5287)] 修复AT模式下pgsql的主键列自增的问题 - +- [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java index 491ea23017b..44dee4eca56 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import java.util.StringJoiner; +import java.util.stream.Collectors; import io.seata.common.util.IOUtil; import io.seata.common.util.StringUtils; @@ -91,9 +92,7 @@ private String buildBeforeImageSQL(TableMeta tableMeta, ArrayList> suffix.append(" FOR UPDATE"); StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified()); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoin.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoin::add); return selectSQLJoin.toString(); } @@ -121,34 +120,33 @@ private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage) StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer; List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified()); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoiner.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoiner::add); return selectSQLJoiner.toString(); } - protected List getNeedUpdateColumns(String table, String tableAlias, List originUpdateColumns) { + protected List getNeedUpdateColumns(String table, String tableAlias, List unescapeUpdateColumns) { List needUpdateColumns = new ArrayList<>(); TableMeta tableMeta = getTableMeta(table); if (ONLY_CARE_UPDATE_COLUMNS) { - if (!containsPK(table, originUpdateColumns)) { + if (!containsPK(table, unescapeUpdateColumns)) { List pkNameList = tableMeta.getEscapePkNameList(getDbType()); if (CollectionUtils.isNotEmpty(pkNameList)) { needUpdateColumns.add(getColumnNamesWithTablePrefix(table,tableAlias,pkNameList)); } } - needUpdateColumns.addAll(originUpdateColumns); + needUpdateColumns.addAll(unescapeUpdateColumns.parallelStream() + .map(originUpdateColumn -> ColumnUtils.addEscape(originUpdateColumn, getDbType())) + .collect(Collectors.toList())); // The on update xxx columns will be auto update by db, so it's also the actually updated columns List onUpdateColumns = tableMeta.getOnUpdateColumnsOnlyName(); - onUpdateColumns.removeAll(originUpdateColumns); - for (String onUpdateColumn : onUpdateColumns) { - needUpdateColumns.add(ColumnUtils.addEscape(onUpdateColumn, getDbType())); - } + onUpdateColumns.removeAll(unescapeUpdateColumns); + needUpdateColumns.addAll(onUpdateColumns.parallelStream() + .map(onUpdateColumn -> ColumnUtils.addEscape(onUpdateColumn, getDbType())) + .collect(Collectors.toList())); } else { - for (String columnName : tableMeta.getAllColumns().keySet()) { - needUpdateColumns.add(ColumnUtils.addEscape(columnName, getDbType())); - } + needUpdateColumns.addAll(tableMeta.getAllColumns().keySet().parallelStream() + .map(columnName -> ColumnUtils.addEscape(columnName, getDbType())).collect(Collectors.toList())); } return needUpdateColumns; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java index 19ba2443548..8077e51078e 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java @@ -134,9 +134,7 @@ private String buildBeforeImageSQL(String joinTable, String itemTable,String suf suffix.append(buildGroupBy(pkColumnNames,needUpdateColumns)); suffix.append(" FOR UPDATE"); StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoin.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoin::add); return selectSQLJoin.toString(); } @@ -203,11 +201,9 @@ private String buildAfterImageSQL(String joinTable, String itemTable, suffix += GROUP_BY; List itemTableUpdateColumns = getItemUpdateColumns(itemTableMeta, recognizer.getUpdateColumns()); List needUpdateColumns = getNeedUpdateColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns); - suffix += buildGroupBy(pkColumns,needUpdateColumns); + suffix += buildGroupBy(pkColumns, needUpdateColumns); StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoiner.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoiner::add); return selectSQLJoiner.toString(); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java index 33271227073..07d353effe4 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java @@ -49,14 +49,15 @@ public class UpdateExecutorTest { @BeforeAll public static void init() { - List returnValueColumnLabels = Lists.newArrayList("id", "name"); + List returnValueColumnLabels = Lists.newArrayList("id", "name", "all"); Object[][] returnValue = new Object[][] { - new Object[] {1, "Tom"}, - new Object[] {2, "Jack"}, + new Object[] {1, "Tom", "keyword"}, + new Object[] {2, "Jack", "keyword"}, }; Object[][] columnMetas = new Object[][] { new Object[] {"", "", "table_update_executor_test", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, new Object[] {"", "", "table_update_executor_test", "name", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + new Object[] {"", "", "table_update_executor_test", "all", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, }; Object[][] indexMetas = new Object[][] { new Object[] {"PRIMARY", "id", false, "", 3, 1, "A", 34}, @@ -97,6 +98,15 @@ public void testBeforeImage() throws SQLException { Assertions.assertNotNull(updateExecutor.beforeImage()); } + @Test + public void testKeyword() throws SQLException { + String sql = "update table_update_executor_test set `all` = '1234' where id = 1"; + List asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0)); + updateExecutor = new UpdateExecutor(statementProxy, (statement, args) -> null, recognizer); + Assertions.assertNotNull(updateExecutor.beforeImage()); + } + @Test public void testAfterImage() throws SQLException { TableRecords beforeImage = updateExecutor.beforeImage(); From 83db2745e9000326d651ee6144854290755217cd Mon Sep 17 00:00:00 2001 From: ZhangShiYeChina <42596680+ZhangShiYeChina@users.noreply.github.com> Date: Tue, 7 Feb 2023 13:49:37 +0800 Subject: [PATCH 24/76] bugfix: don't remove GlobalSession when retry rollback or retry commit timeout (#5299) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java | 2 +- .../io/seata/server/coordinator/DefaultCoordinator.java | 6 ------ 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index ae5e4336ca8..2a871211b38 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -17,6 +17,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5281](https://github.com/seata/seata/pull/5281)] parallel request handle throw IndexOutOfBoundsException - [[#5288](https://github.com/seata/seata/pull/5288)] fix auto-increment of pk columns in Oracle in AT mode - [[#5287](https://github.com/seata/seata/pull/5287)] fix auto-increment of pk columns in PostgreSQL in AT mode +- [[#5299](https://github.com/seata/seata/pull/5299)] fix GlobalSession deletion when retry rollback or retry commit timeout - [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters @@ -52,6 +53,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [GoodBoyCoder](https://github.com/GoodBoyCoder) - [a364176773](https://github.com/a364176773) - [isharpever](https://github.com/isharpever) +- [ZhangShiYeChina](https://github.com/ZhangShiYeChina) - [mxsm](https://github.com/mxsm) diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index f2dce728093..0eb28867ed9 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -17,6 +17,7 @@ - [[#5281](https://github.com/seata/seata/pull/5281)] 修复并行rm请求处理时数组索引越界问题 - [[#5288](https://github.com/seata/seata/pull/5288)] 修复AT模式下oracle的主键列自增的问题 - [[#5287](https://github.com/seata/seata/pull/5287)] 修复AT模式下pgsql的主键列自增的问题 +- [[#5299](https://github.com/seata/seata/pull/5299)] 修复TC端重试回滚或重试提交超时GlobalSession的删除问题 - [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug ### optimize: @@ -51,6 +52,7 @@ - [GoodBoyCoder](https://github.com/GoodBoyCoder) - [a364176773](https://github.com/a364176773) - [isharpever](https://github.com/isharpever) +- [ZhangShiYeChina](https://github.com/ZhangShiYeChina) - [mxsm](https://github.com/mxsm) diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java index 52df100d047..50c59cf6bc5 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java @@ -37,7 +37,7 @@ public class MySQLUndoUpdateExecutor extends AbstractUndoExecutor { /** - * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 in (?) pk2 in (?) + * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 =? and pk2 =? */ private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s "; diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index 75c09ac2d2a..b1f41d64436 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -383,9 +383,6 @@ protected void handleRetryRollbacking() { if (ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE) { rollbackingSession.clean(); } - // Prevent thread safety issues - SessionHolder.getRetryRollbackingSessionManager().removeGlobalSession(rollbackingSession); - LOGGER.error("Global transaction rollback retry timeout and has removed [{}]", rollbackingSession.getXid()); SessionHelper.endRollbackFailed(rollbackingSession, true, true); @@ -421,9 +418,6 @@ protected void handleRetryCommitting() { return; } if (isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT, committingSession.getBeginTime())) { - // Prevent thread safety issues - SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(committingSession); - LOGGER.error("Global transaction commit retry timeout and has removed [{}]", committingSession.getXid()); // commit retry timeout event SessionHelper.endCommitFailed(committingSession, true, true); From eab8c9a2bda47f5b67c6b0b315c1c167783d2f5d Mon Sep 17 00:00:00 2001 From: jimin Date: Tue, 7 Feb 2023 14:08:23 +0800 Subject: [PATCH 25/76] bugfix: remove RollbackRetryTimeout sessions during in file storage recover (#5311) Signed-off-by: slievrly --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../main/java/io/seata/rm/datasource/exec/UpdateExecutor.java | 3 +-- .../rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java | 2 +- .../seata/server/storage/file/session/FileSessionManager.java | 1 + 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 2a871211b38..d70ebe1acdd 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -19,6 +19,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5287](https://github.com/seata/seata/pull/5287)] fix auto-increment of pk columns in PostgreSQL in AT mode - [[#5299](https://github.com/seata/seata/pull/5299)] fix GlobalSession deletion when retry rollback or retry commit timeout - [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters +- [[#5311](https://github.com/seata/seata/pull/5311)] remove RollbackRetryTimeout sessions during in file storage recover ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 0eb28867ed9..b2866a40593 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -19,6 +19,7 @@ - [[#5287](https://github.com/seata/seata/pull/5287)] 修复AT模式下pgsql的主键列自增的问题 - [[#5299](https://github.com/seata/seata/pull/5299)] 修复TC端重试回滚或重试提交超时GlobalSession的删除问题 - [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug +- [[#5311](https://github.com/seata/seata/pull/5311)] 移除基于文件存储恢复时的RollbackRetryTimeout事务 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java index 44dee4eca56..2200c771206 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java @@ -135,8 +135,7 @@ protected List getNeedUpdateColumns(String table, String tableAlias, Lis } } needUpdateColumns.addAll(unescapeUpdateColumns.parallelStream() - .map(originUpdateColumn -> ColumnUtils.addEscape(originUpdateColumn, getDbType())) - .collect(Collectors.toList())); + .map(unescapeUpdateColumn -> ColumnUtils.addEscape(unescapeUpdateColumn, getDbType())).collect(Collectors.toList())); // The on update xxx columns will be auto update by db, so it's also the actually updated columns List onUpdateColumns = tableMeta.getOnUpdateColumnsOnlyName(); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java index 50c59cf6bc5..e97387a99dd 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java @@ -37,7 +37,7 @@ public class MySQLUndoUpdateExecutor extends AbstractUndoExecutor { /** - * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 =? and pk2 =? + * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 = ? and pk2 = ? */ private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s "; diff --git a/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java b/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java index 5072cbb4512..7a95f70bd77 100644 --- a/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java +++ b/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java @@ -232,6 +232,7 @@ private boolean checkSessionStatus(GlobalSession globalSession) { case RollbackFailed: case TimeoutRollbacked: case TimeoutRollbackFailed: + case RollbackRetryTimeout: case Finished: return false; default: From e2ff0ee13973752ea0c1708141293bea2e835cea Mon Sep 17 00:00:00 2001 From: jimin Date: Thu, 9 Feb 2023 09:57:39 +0800 Subject: [PATCH 26/76] bugfix: fix G1 jvm parameter in jdk8 (#5316) Signed-off-by: slievrly --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + distribution/bin/seata-server.sh | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index d70ebe1acdd..2347109d972 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -20,6 +20,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5299](https://github.com/seata/seata/pull/5299)] fix GlobalSession deletion when retry rollback or retry commit timeout - [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters - [[#5311](https://github.com/seata/seata/pull/5311)] remove RollbackRetryTimeout sessions during in file storage recover +- [[#5316](https://github.com/seata/seata/pull/5316)] fix G1 jvm parameter in jdk8 ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index b2866a40593..318e0669ce8 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -20,6 +20,7 @@ - [[#5299](https://github.com/seata/seata/pull/5299)] 修复TC端重试回滚或重试提交超时GlobalSession的删除问题 - [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug - [[#5311](https://github.com/seata/seata/pull/5311)] 移除基于文件存储恢复时的RollbackRetryTimeout事务 +- [[#5316](https://github.com/seata/seata/pull/5316)] 修复jdk8 中 G1 参数 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/distribution/bin/seata-server.sh b/distribution/bin/seata-server.sh index 2ed77251532..512851e5372 100644 --- a/distribution/bin/seata-server.sh +++ b/distribution/bin/seata-server.sh @@ -138,7 +138,7 @@ if [[ "$JAVA_MAJOR_VERSION" -ge "9" ]] ; then elif [[ "$JAVA_MAJOR_VERSION" -ge "17" ]] ; then JAVA_OPT="${JAVA_OPT} -Xlog:gc=trace:file=${BASEDIR}/logs/seata_gc.log:time,tags:filecount=10,filesize=10M" else - JAVA_OPT="${JAVA_OPT} -Xloggc:${BASEDIR}/logs/seata_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+UseG1GC" + JAVA_OPT="${JAVA_OPT} -Xloggc:${BASEDIR}/logs/seata_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC" fi JAVA_OPT="${JAVA_OPT} -Dio.netty.leakDetectionLevel=advanced" From 8026bb6b3ff65df7d9fa5967de3d614d8bbc7bbe Mon Sep 17 00:00:00 2001 From: renliangyu857 <2918490262@qq.com> Date: Thu, 9 Feb 2023 15:51:52 +0800 Subject: [PATCH 27/76] optimize: add time info for transaction timeout log (#5323) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../java/io/seata/server/coordinator/DefaultCoordinator.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 2347109d972..68757d88361 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -32,6 +32,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. - [[#5273](https://github.com/seata/seata/pull/5273)] Optimize the compilation configuration of the `protobuf-maven-plugin` plug-in to solve the problem of too long command lines in higher versions. - [[#5303](https://github.com/seata/seata/pull/5303)] remove startup script the -Xmn configuration +- [[#5323](https://github.com/seata/seata/pull/5323)] add time info for global transaction timeout log ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 318e0669ce8..3ab48769325 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -31,6 +31,7 @@ - [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 - [[#5273](https://github.com/seata/seata/pull/5273)] 优化`protobuf-maven-plugin`插件的编译配置,解决高版本的命令行过长问题 - [[#5303](https://github.com/seata/seata/pull/5303)] 移除启动脚本的-Xmn参数 +- [[#5323](https://github.com/seata/seata/pull/5323)] 为全局事务超时日志添加时间信息 ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index b1f41d64436..2d605df4589 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -337,7 +337,7 @@ protected void timeoutCheck() { return false; } - LOGGER.info("Global transaction[{}] is timeout and will be rollback.", globalSession.getXid()); + LOGGER.warn("Global transaction[{}] is timeout and will be rollback,transaction begin time:{} and now:{}", globalSession.getXid(), globalSession.getBeginTime(), System.currentTimeMillis()); globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.close(); From 8a8310c882ab2077e2931fbfcdd49ca5ff0b04b1 Mon Sep 17 00:00:00 2001 From: will <349071347@qq.com> Date: Thu, 9 Feb 2023 16:05:51 +0800 Subject: [PATCH 28/76] optimize: optimize EnhancedServiceLoader log (#5315) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../common/loader/EnhancedServiceLoader.java | 15 +++++++-------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 68757d88361..e593160fb72 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -32,6 +32,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. - [[#5273](https://github.com/seata/seata/pull/5273)] Optimize the compilation configuration of the `protobuf-maven-plugin` plug-in to solve the problem of too long command lines in higher versions. - [[#5303](https://github.com/seata/seata/pull/5303)] remove startup script the -Xmn configuration +- [[#5315](https://github.com/seata/seata/pull/5315)] optimize the log of SPI - [[#5323](https://github.com/seata/seata/pull/5323)] add time info for global transaction timeout log ### security: @@ -58,6 +59,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [isharpever](https://github.com/isharpever) - [ZhangShiYeChina](https://github.com/ZhangShiYeChina) - [mxsm](https://github.com/mxsm) +- [l81893521](https://github.com/l81893521) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 3ab48769325..5a92cd7c94d 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -31,6 +31,7 @@ - [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 - [[#5273](https://github.com/seata/seata/pull/5273)] 优化`protobuf-maven-plugin`插件的编译配置,解决高版本的命令行过长问题 - [[#5303](https://github.com/seata/seata/pull/5303)] 移除启动脚本的-Xmn参数 +- [[#5315](https://github.com/seata/seata/pull/5315)] 优化SPI加载日志 - [[#5323](https://github.com/seata/seata/pull/5323)] 为全局事务超时日志添加时间信息 ### security: @@ -57,6 +58,7 @@ - [isharpever](https://github.com/isharpever) - [ZhangShiYeChina](https://github.com/ZhangShiYeChina) - [mxsm](https://github.com/mxsm) +- [l81893521](https://github.com/l81893521) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index 3b6942c8a40..dc56d50f76c 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -32,6 +32,7 @@ import io.seata.common.Constants; import io.seata.common.executor.Initialize; import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -283,7 +284,6 @@ private static InnerEnhancedServiceLoader removeServiceLoader(Class ty } private static void removeAllServiceLoader() { - SERVICE_LOADERS.clear(); } @@ -391,8 +391,7 @@ private List> getAllExtensionClass(ClassLoader loader) { return loadAllExtensionClass(loader); } - private S loadExtension(ClassLoader loader, Class[] argTypes, - Object[] args) { + private S loadExtension(ClassLoader loader, Class[] argTypes, Object[] args) { try { loadAllExtensionClass(loader); ExtensionDefinition defaultExtensionDefinition = getDefaultExtensionDefinition(); @@ -409,7 +408,7 @@ private S loadExtension(ClassLoader loader, Class[] argTypes, @SuppressWarnings("rawtypes") private S loadExtension(String activateName, ClassLoader loader, Class[] argTypes, Object[] args) { - if (io.seata.common.util.StringUtils.isEmpty(activateName)) { + if (StringUtils.isEmpty(activateName)) { throw new IllegalArgumentException("the name of service provider for [" + type.getName() + "] name is null"); } try { @@ -496,9 +495,9 @@ private List> findAllExtensionDefinition(ClassLoader load } if (!extensionDefinitions.isEmpty()) { - extensionDefinitions.sort((definition1, definition2) -> { - int o1 = definition1.getOrder(); - int o2 = definition2.getOrder(); + extensionDefinitions.sort((def1, def2) -> { + int o1 = def1.getOrder(); + int o2 = def2.getOrder(); return Integer.compare(o1, o2); }); } @@ -542,7 +541,7 @@ private void loadFile(String dir, ClassLoader loader, List Date: Sun, 12 Feb 2023 22:05:18 +0800 Subject: [PATCH 29/76] bugfix: fix some tiny bugs (#5332) --- changes/en-us/develop.md | 3 ++- changes/zh-cn/develop.md | 2 ++ .../main/java/io/seata/common/loader/ExtensionDefinition.java | 2 +- .../main/java/io/seata/common/util/LowerCaseLinkHashMap.java | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index e593160fb72..d88ae477fbe 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -21,7 +21,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters - [[#5311](https://github.com/seata/seata/pull/5311)] remove RollbackRetryTimeout sessions during in file storage recover - [[#5316](https://github.com/seata/seata/pull/5316)] fix G1 jvm parameter in jdk8 - +- [[#5332](https://github.com/seata/seata/pull/5332)] fix bugs found in unit tests ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more @@ -60,6 +60,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [ZhangShiYeChina](https://github.com/ZhangShiYeChina) - [mxsm](https://github.com/mxsm) - [l81893521](https://github.com/l81893521) +- [liuqiufeng](https://github.com/liuqiufeng) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 5a92cd7c94d..99f6b12e030 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -21,6 +21,7 @@ - [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug - [[#5311](https://github.com/seata/seata/pull/5311)] 移除基于文件存储恢复时的RollbackRetryTimeout事务 - [[#5316](https://github.com/seata/seata/pull/5316)] 修复jdk8 中 G1 参数 +- [[#5332](https://github.com/seata/seata/pull/5332)] 修复单元测试中发现的bug ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 @@ -59,6 +60,7 @@ - [ZhangShiYeChina](https://github.com/ZhangShiYeChina) - [mxsm](https://github.com/mxsm) - [l81893521](https://github.com/l81893521) +- [liuqiufeng](https://github.com/liuqiufeng) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/common/src/main/java/io/seata/common/loader/ExtensionDefinition.java b/common/src/main/java/io/seata/common/loader/ExtensionDefinition.java index 9b47d71a0d9..ea8b4790c1a 100644 --- a/common/src/main/java/io/seata/common/loader/ExtensionDefinition.java +++ b/common/src/main/java/io/seata/common/loader/ExtensionDefinition.java @@ -82,7 +82,7 @@ public boolean equals(Object obj) { if (!order.equals(other.order)) { return false; } - return !scope.equals(other.scope); + return scope.equals(other.scope); } public String getName() { diff --git a/common/src/main/java/io/seata/common/util/LowerCaseLinkHashMap.java b/common/src/main/java/io/seata/common/util/LowerCaseLinkHashMap.java index ac9b17f2473..d95344d6d8d 100644 --- a/common/src/main/java/io/seata/common/util/LowerCaseLinkHashMap.java +++ b/common/src/main/java/io/seata/common/util/LowerCaseLinkHashMap.java @@ -68,7 +68,7 @@ public boolean containsKey(Object o) { @Override public boolean containsValue(Object o) { - return targetMap.containsKey(o); + return targetMap.containsValue(o); } @Override From 357f8e8c6d899537403605ad0b5dab3e80e4f0d8 Mon Sep 17 00:00:00 2001 From: Dmego Date: Tue, 14 Feb 2023 23:56:28 +0800 Subject: [PATCH 30/76] optimize: add tcc fence log clean task delay check (#5089) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 3 +++ tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index d88ae477fbe..1a2ed17f6d5 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -27,6 +27,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level - [[#5237](https://github.com/seata/seata/pull/5237)] optimize exception log message print(EnhancedServiceLoader.loadFile#cahtch) +- [[#5089](https://github.com/seata/seata/pull/5089)] optimize the check of the delay value of the TCC fence log clean task - [[#5243](https://github.com/seata/seata/pull/5243)] optimize kryo 5.4.0 optimize compatibility with jdk17 - [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app - [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. @@ -49,6 +50,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) +- [dmego](https://github.com/dmego) - [CrazyLionLi](https://github.com/JavaLionLi) - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 99f6b12e030..0294be24552 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -27,6 +27,7 @@ - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 - [[#5237](https://github.com/seata/seata/pull/5237)] 优化异常日志打印(EnhancedServiceLoader.loadFile#cahtch) +- [[#5089](https://github.com/seata/seata/pull/5089)] 优化 TCC fence log 清理定时任务的 delay 参数值检查 - [[#5243](https://github.com/seata/seata/pull/5243)] 升级 kryo 5.4.0 优化对jdk17的兼容性 - [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel - [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 @@ -35,6 +36,7 @@ - [[#5315](https://github.com/seata/seata/pull/5315)] 优化SPI加载日志 - [[#5323](https://github.com/seata/seata/pull/5323)] 为全局事务超时日志添加时间信息 + ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 @@ -49,6 +51,7 @@ - [albumenj](https://github.com/albumenj) - [PeppaO](https://github.com/PeppaO) - [yuruixin](https://github.com/yuruixin) +- [dmego](https://github.com/dmego) - [CrazyLionLi](https://github.com/JavaLionLi) - [xingfudeshi](https://github.com/xingfudeshi) - [Bughue](https://github.com/Bughue) diff --git a/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java b/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java index fffc08ab993..15e570c039c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java +++ b/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java @@ -109,6 +109,11 @@ public void setLogTableName(String logTableName) { */ public void initCleanTask() { try { + // disable clear task when cleanPeriod <= 0 + if (cleanPeriod.isZero() || cleanPeriod.isNegative()) { + LOGGER.info("TCC fence log clean task is not started, cleanPeriod is:{}", cleanPeriod); + return; + } // convert to second level. maximum interval is 68 years long periodSeconds = cleanPeriod.compareTo(MAX_PERIOD) >= 0 ? Integer.MAX_VALUE : cleanPeriod.toMillis() / 1000; // start tcc fence clean schedule From b4f6fb7567fb2c57779a2676deaac11ce37cf6f1 Mon Sep 17 00:00:00 2001 From: renliangyu857 <2918490262@qq.com> Date: Wed, 15 Feb 2023 11:35:32 +0800 Subject: [PATCH 31/76] optimize: add store mode,config type and registry type log info (#5325) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../src/main/java/io/seata/config/ConfigurationFactory.java | 2 +- .../io/seata/discovery/registry/MultiRegistryFactory.java | 5 +++++ .../java/io/seata/discovery/registry/RegistryFactory.java | 5 +++++ .../java/io/seata/server/coordinator/DefaultCoordinator.java | 4 +++- .../main/java/io/seata/server/lock/LockerManagerFactory.java | 4 ++++ .../src/main/java/io/seata/server/session/SessionHolder.java | 1 + 8 files changed, 21 insertions(+), 2 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 1a2ed17f6d5..008ea833828 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -33,6 +33,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously. - [[#5273](https://github.com/seata/seata/pull/5273)] Optimize the compilation configuration of the `protobuf-maven-plugin` plug-in to solve the problem of too long command lines in higher versions. - [[#5303](https://github.com/seata/seata/pull/5303)] remove startup script the -Xmn configuration +- [[#5325](https://github.com/seata/seata/pull/5325)] add store mode,config type and registry type log info - [[#5315](https://github.com/seata/seata/pull/5315)] optimize the log of SPI - [[#5323](https://github.com/seata/seata/pull/5323)] add time info for global transaction timeout log diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 0294be24552..f9021bf90e1 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -33,6 +33,7 @@ - [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。 - [[#5273](https://github.com/seata/seata/pull/5273)] 优化`protobuf-maven-plugin`插件的编译配置,解决高版本的命令行过长问题 - [[#5303](https://github.com/seata/seata/pull/5303)] 移除启动脚本的-Xmn参数 +- [[#5325](https://github.com/seata/seata/pull/5325)] 添加配置中心、注册中心类型以及存储模式日志信息 - [[#5315](https://github.com/seata/seata/pull/5315)] 优化SPI加载日志 - [[#5323](https://github.com/seata/seata/pull/5323)] 为全局事务超时日志添加时间信息 diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java index 55eb54d3fbc..38edf0c7ec4 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java @@ -104,7 +104,7 @@ private static Configuration buildConfiguration() { String configTypeName = CURRENT_FILE_INSTANCE.getConfig( ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + ConfigurationKeys.FILE_ROOT_TYPE); - + LOGGER.info("use configuration center type: {}", configTypeName); if (StringUtils.isBlank(configTypeName)) { throw new NotSupportYetException("config type can not be null"); } diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java index 2ded7a176ad..cbb4a98dc09 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java @@ -25,6 +25,8 @@ import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The type multiple Registry factory. @@ -33,6 +35,8 @@ */ public class MultiRegistryFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(MultiRegistryFactory.class); + /** * Gets instances. * @@ -50,6 +54,7 @@ private static List buildRegistryServices() { if (StringUtils.isBlank(registryTypeNamesStr)) { registryTypeNamesStr = RegistryType.File.name(); } + LOGGER.info("use multi registry center type: {}", registryTypeNamesStr); String[] registryTypeNames = registryTypeNamesStr.split(Constants.REGISTRY_TYPE_SPLIT_CHAR); for (String registryTypeName : registryTypeNames) { RegistryType registryType; diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java index d1084ec19ef..9f8cd2e4f4a 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java @@ -21,6 +21,8 @@ import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.ConfigurationFactory; import io.seata.config.ConfigurationKeys; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The type Registry factory. @@ -29,6 +31,8 @@ */ public class RegistryFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(RegistryFactory.class); + /** * Gets instance. * @@ -43,6 +47,7 @@ private static RegistryService buildRegistryService() { String registryTypeName = ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig( ConfigurationKeys.FILE_ROOT_REGISTRY + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + ConfigurationKeys.FILE_ROOT_TYPE); + LOGGER.info("use registry center type: {}", registryTypeName); try { registryType = RegistryType.getType(registryTypeName); } catch (Exception exx) { diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index 2d605df4589..8b4a9fa10ba 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -65,6 +65,7 @@ import io.seata.server.session.SessionHelper; import io.seata.server.session.SessionHolder; import io.seata.server.store.StoreConfig; +import org.apache.commons.lang.time.DateFormatUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -337,7 +338,8 @@ protected void timeoutCheck() { return false; } - LOGGER.warn("Global transaction[{}] is timeout and will be rollback,transaction begin time:{} and now:{}", globalSession.getXid(), globalSession.getBeginTime(), System.currentTimeMillis()); + LOGGER.warn("Global transaction[{}] is timeout and will be rollback,transaction begin time:{} and now:{}", globalSession.getXid(), + DateFormatUtils.ISO_DATE_FORMAT.format(globalSession.getBeginTime()), DateFormatUtils.ISO_DATE_FORMAT.format(System.currentTimeMillis())); globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.close(); diff --git a/server/src/main/java/io/seata/server/lock/LockerManagerFactory.java b/server/src/main/java/io/seata/server/lock/LockerManagerFactory.java index cec4f0daf53..b4aef8478b6 100644 --- a/server/src/main/java/io/seata/server/lock/LockerManagerFactory.java +++ b/server/src/main/java/io/seata/server/lock/LockerManagerFactory.java @@ -20,6 +20,8 @@ import io.seata.config.ConfigurationFactory; import io.seata.server.store.StoreConfig; import io.seata.server.store.StoreConfig.LockMode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The type Lock manager factory. @@ -28,6 +30,7 @@ */ public class LockerManagerFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(LockerManagerFactory.class); private static final Configuration CONFIG = ConfigurationFactory.getInstance(); /** @@ -58,6 +61,7 @@ public static void init(LockMode lockMode) { if (null == lockMode) { lockMode = StoreConfig.getLockMode(); } + LOGGER.info("use lock store mode: {}", lockMode.getName()); //if not exist the lock mode, throw exception if (null != StoreConfig.StoreMode.get(lockMode.name())) { LOCK_MANAGER = EnhancedServiceLoader.load(LockManager.class, lockMode.getName()); diff --git a/server/src/main/java/io/seata/server/session/SessionHolder.java b/server/src/main/java/io/seata/server/session/SessionHolder.java index b8f530042a4..df366274f96 100644 --- a/server/src/main/java/io/seata/server/session/SessionHolder.java +++ b/server/src/main/java/io/seata/server/session/SessionHolder.java @@ -102,6 +102,7 @@ public static void init(SessionMode sessionMode) { if (null == sessionMode) { sessionMode = StoreConfig.getSessionMode(); } + LOGGER.info("use session store mode: {}", sessionMode.getName()); if (SessionMode.DB.equals(sessionMode)) { ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, SessionMode.DB.getName()); ASYNC_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, SessionMode.DB.getName(), From 97bad4b74a16e0efbc4fee099b30c3b9d3940b7e Mon Sep 17 00:00:00 2001 From: ZhangShiYeChina <42596680+ZhangShiYeChina@users.noreply.github.com> Date: Fri, 17 Feb 2023 20:54:28 +0800 Subject: [PATCH 32/76] bugfix: fix when TC returns RollbackFailed FailureHandler not executed (#5321) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../seata/tm/api/TransactionalTemplate.java | 28 ++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 008ea833828..b675488425a 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -21,8 +21,10 @@ Add changes here for all PR submitted to the develop branch. - [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters - [[#5311](https://github.com/seata/seata/pull/5311)] remove RollbackRetryTimeout sessions during in file storage recover - [[#5316](https://github.com/seata/seata/pull/5316)] fix G1 jvm parameter in jdk8 +- [[#5321](https://github.com/seata/seata/pull/5321)] fix When the rollback logic on the TC side returns RollbackFailed, the custom FailureHandler is not executed - [[#5332](https://github.com/seata/seata/pull/5332)] fix bugs found in unit tests + ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more - [[#5212](https://github.com/seata/seata/pull/5212)] optimize log message level diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index f9021bf90e1..57b9105c910 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -21,8 +21,10 @@ - [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug - [[#5311](https://github.com/seata/seata/pull/5311)] 移除基于文件存储恢复时的RollbackRetryTimeout事务 - [[#5316](https://github.com/seata/seata/pull/5316)] 修复jdk8 中 G1 参数 +- [[#5321](https://github.com/seata/seata/pull/5321)] 修复当TC端回滚返回RollbackFailed时,自定义FailureHandler的方法未执行 - [[#5332](https://github.com/seata/seata/pull/5332)] 修复单元测试中发现的bug + ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 - [[#5212](https://github.com/seata/seata/pull/5212)] 优化不合理的日志信息级别 diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java index e6b4edf40d7..0cf360a8d0d 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java @@ -156,7 +156,7 @@ public Object execute(TransactionalExecutor business) throws Throwable { * Judge whether timeout * * @param beginTime the beginTime - * @param txInfo the transaction info + * @param txInfo the transaction info * @return is timeout */ private boolean isTimeout(long beginTime, TransactionInfo txInfo) { @@ -239,9 +239,29 @@ private void rollbackTransaction(GlobalTransaction tx, Throwable originalExcepti TransactionalExecutor.Code.RollbackFailure, originalException); } - // 3.1 Successfully rolled back - throw new TransactionalExecutor.ExecutionException(tx, GlobalStatus.RollbackRetrying.equals(tx.getLocalStatus()) - ? TransactionalExecutor.Code.RollbackRetrying : TransactionalExecutor.Code.RollbackDone, originalException); + //# fix #5231 + TransactionalExecutor.Code code; + switch (tx.getLocalStatus()) { + case RollbackFailed: + case TimeoutRollbackFailed: + case RollbackRetryTimeout: + code = TransactionalExecutor.Code.RollbackFailure; + break; + case Rollbacking: + case RollbackRetrying: + code = TransactionalExecutor.Code.RollbackRetrying; + break; + case TimeoutRollbacking: + case TimeoutRollbackRetrying: + case TimeoutRollbacked: + code = TransactionalExecutor.Code.TimeoutRollback; + break; + case Rollbacked: + default: + code = TransactionalExecutor.Code.RollbackDone; + } + throw new TransactionalExecutor.ExecutionException(tx, code, originalException); + } private void beginTransaction(TransactionInfo txInfo, GlobalTransaction tx) throws TransactionalExecutor.ExecutionException { From e0a02fb53ef6212e20c075449ce3870fd418b9a7 Mon Sep 17 00:00:00 2001 From: zsp419 <592366758@qq.com> Date: Tue, 21 Feb 2023 18:28:15 +0800 Subject: [PATCH 33/76] feature: support http put (#5070) --- .../http/AbstractHttpExecutor.java | 40 +++++++++++++------ .../seata/integration/http/HttpExecutor.java | 14 +++++++ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/integration/http/src/main/java/io/seata/integration/http/AbstractHttpExecutor.java b/integration/http/src/main/java/io/seata/integration/http/AbstractHttpExecutor.java index 8acac4a0d9e..2958def37ec 100644 --- a/integration/http/src/main/java/io/seata/integration/http/AbstractHttpExecutor.java +++ b/integration/http/src/main/java/io/seata/integration/http/AbstractHttpExecutor.java @@ -26,6 +26,7 @@ import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; @@ -50,13 +51,35 @@ public abstract class AbstractHttpExecutor implements HttpExecutor { @Override public K executePost(String host, String path, T paramObject, Class returnType) throws IOException { + Args.notNull(returnType, "returnType"); + HttpPost httpPost = new HttpPost(host + path); + StringEntity entity = execute(host, path, paramObject); + if (entity != null) { + httpPost.setEntity(entity); + } + Map headers = new HashMap<>(); + buildPostHeaders(headers, paramObject); + CloseableHttpClient httpClient = initHttpClientInstance(paramObject); + return wrapHttpExecute(returnType, httpClient, httpPost, headers); + } + @Override + public K executePut(String host, String path, T paramObject, Class returnType) throws IOException { Args.notNull(returnType, "returnType"); + HttpPut httpPut = new HttpPut(host + path); + StringEntity entity = execute(host, path, paramObject); + if (entity != null) { + httpPut.setEntity(entity); + } + Map headers = new HashMap<>(); + buildPostHeaders(headers, paramObject); + CloseableHttpClient httpClient = initHttpClientInstance(paramObject); + return wrapHttpExecute(returnType, httpClient, httpPut, headers); + } + + private StringEntity execute(String host, String path, T paramObject) { Args.notNull(host, "host"); Args.notNull(path, "path"); - - CloseableHttpClient httpClient = initHttpClientInstance(paramObject); - HttpPost httpPost = new HttpPost(host + path); StringEntity entity = null; if (paramObject != null) { String content; @@ -80,14 +103,7 @@ public K executePost(String host, String path, T paramObject, Class re entity = new StringEntity(content, ContentType.APPLICATION_JSON); } - entity = buildEntity(entity, paramObject); - if (entity != null) { - httpPost.setEntity(entity); - } - Map headers = new HashMap<>(); - - buildPostHeaders(headers, paramObject); - return wrapHttpExecute(returnType, httpClient, httpPost, headers); + return buildEntity(entity, paramObject); } @Override @@ -115,7 +131,7 @@ private CloseableHttpClient initHttpClientInstance(T paramObject) { protected abstract void buildClientEntity(CloseableHttpClient httpClient, T paramObject); private K wrapHttpExecute(Class returnType, CloseableHttpClient httpClient, HttpUriRequest httpUriRequest, - Map headers) throws IOException { + Map headers) throws IOException { CloseableHttpResponse response; String xid = RootContext.getXID(); if (xid != null) { diff --git a/integration/http/src/main/java/io/seata/integration/http/HttpExecutor.java b/integration/http/src/main/java/io/seata/integration/http/HttpExecutor.java index 50d52a7b10a..991a1df060f 100644 --- a/integration/http/src/main/java/io/seata/integration/http/HttpExecutor.java +++ b/integration/http/src/main/java/io/seata/integration/http/HttpExecutor.java @@ -52,4 +52,18 @@ public interface HttpExecutor { */ K executeGet(String host, String path, Map paramObject, Class returnType) throws IOException; + /** + * Execute put k. + * + * @param the type parameter + * @param the type parameter + * @param host the host + * @param path the path + * @param paramObject the param object + * @param returnType the return type + * @return the k + * @throws IOException the io exception + */ + K executePut(String host, String path, T paramObject, Class returnType) throws IOException; + } From 9194aa06f6c1401613c15eadcb8f078822466131 Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 22 Feb 2023 13:52:15 +0800 Subject: [PATCH 34/76] test: fix UpdateExecutorTest failed (#5380) --- changes/en-us/develop.md | 2 +- changes/zh-cn/develop.md | 2 +- .../rm/datasource/exec/MultiExecutorTest.java | 36 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index b675488425a..ac9a77fce01 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -43,7 +43,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities ### test: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] add test for xxx +- [[#5380](https://github.com/seata/seata/pull/5380)] fix UpdateExecutorTest failed Thanks to these contributors for their code commits. Please report an unintended omission. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 57b9105c910..2be63ea969c 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -44,7 +44,7 @@ - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 ### test: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] 增加 xxx 测试 +- [[#5380](https://github.com/seata/seata/pull/5380)] 修复 UpdateExecutorTest 单测失败问题 非常感谢以下 contributors 的代码贡献。若有无意遗漏,请报告。 diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MultiExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MultiExecutorTest.java index b33c4b50653..332bde4985d 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MultiExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MultiExecutorTest.java @@ -61,8 +61,8 @@ public static void init() throws Throwable { new Object[]{2, "Jack"}, }; Object[][] columnMetas = new Object[][]{ - new Object[]{"", "", "table_update_executor_test", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, - new Object[]{"", "", "table_update_executor_test", "name", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + new Object[]{"", "", "table_multi_executor_test", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, + new Object[]{"", "", "table_multi_executor_test", "name", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, }; Object[][] indexMetas = new Object[][]{ new Object[]{"PRIMARY", "id", false, "", 3, 1, "A", 34}, @@ -91,8 +91,8 @@ public static void init() throws Throwable { @Test public void testBeforeImageAndAfterImages() throws SQLException { //same table and same type - String sql = "update table_update_executor_test set name = 'WILL' where id = 1;" + - "update table_update_executor_test set name = 'WILL2' where id = 2"; + String sql = "update table_multi_executor_test set name = 'WILL' where id = 1;" + + "update table_multi_executor_test set name = 'WILL2' where id = 2"; List multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; @@ -106,14 +106,14 @@ public void testBeforeImageAndAfterImages() throws SQLException { Assertions.assertEquals(executor.getAfterImagesMap().size(), 1); executor.prepareUndoLog(beforeImage, afterImage); List items = connectionProxy.getContext().getUndoItems(); - Assertions.assertTrue(items.stream().allMatch(t -> Objects.equals(t.getSqlType(), SQLType.UPDATE) && Objects.equals(t.getTableName(), "table_update_executor_test"))); + Assertions.assertTrue(items.stream().allMatch(t -> Objects.equals(t.getSqlType(), SQLType.UPDATE) && Objects.equals(t.getTableName(), "table_multi_executor_test"))); Assertions.assertEquals(items.size(), 1); connectionProxy.getContext().reset(); //same table delete - sql = "delete from table_update_executor_test where id = 2;" + - "delete from table_update_executor_test where id = 3"; + sql = "delete from table_multi_executor_test where id = 2;" + + "delete from table_multi_executor_test where id = 3"; multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; @@ -128,13 +128,13 @@ public void testBeforeImageAndAfterImages() throws SQLException { executor.prepareUndoLog(beforeImage, afterImage); items = connectionProxy.getContext().getUndoItems(); Set itemSet = items.stream().map(t -> t.getTableName()).collect(Collectors.toSet()); - Assertions.assertTrue(itemSet.contains("table_update_executor_test")); + Assertions.assertTrue(itemSet.contains("table_multi_executor_test")); Assertions.assertEquals(items.size(), 1); connectionProxy.getContext().reset(); //multi table update - sql = "update table_update_executor_test set name = 'WILL' where id = 1;update table_update_executor_test2 set name = 'WILL' where id = 1;update table_update_executor_test2 set name = 'WILL' where id = 3;"; + sql = "update table_multi_executor_test set name = 'WILL' where id = 1;update table_multi_executor_test2 set name = 'WILL' where id = 1;update table_multi_executor_test2 set name = 'WILL' where id = 3;"; multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; @@ -149,14 +149,14 @@ public void testBeforeImageAndAfterImages() throws SQLException { executor.prepareUndoLog(beforeImage, afterImage); items = connectionProxy.getContext().getUndoItems(); itemSet = items.stream().map(t -> t.getTableName()).collect(Collectors.toSet()); - Assertions.assertTrue(itemSet.contains("table_update_executor_test")); - Assertions.assertTrue(itemSet.contains("table_update_executor_test2")); + Assertions.assertTrue(itemSet.contains("table_multi_executor_test")); + Assertions.assertTrue(itemSet.contains("table_multi_executor_test2")); Assertions.assertEquals(items.size(), 2); connectionProxy.getContext().reset(); // multi table delete - sql = "delete from table_update_executor_test2 where id = 2;delete from table_update_executor_test where id = 3;delete from table_update_executor_test where id = 4;delete from table_update_executor_test"; + sql = "delete from table_multi_executor_test2 where id = 2;delete from table_multi_executor_test where id = 3;delete from table_multi_executor_test where id = 4;delete from table_multi_executor_test"; multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; @@ -171,12 +171,12 @@ public void testBeforeImageAndAfterImages() throws SQLException { executor.prepareUndoLog(beforeImage, afterImage); items = connectionProxy.getContext().getUndoItems(); itemSet = items.stream().map(t -> t.getTableName()).collect(Collectors.toSet()); - Assertions.assertTrue(itemSet.contains("table_update_executor_test")); - Assertions.assertTrue(itemSet.contains("table_update_executor_test2")); + Assertions.assertTrue(itemSet.contains("table_multi_executor_test")); + Assertions.assertTrue(itemSet.contains("table_multi_executor_test2")); Assertions.assertEquals(items.size(), 2); // contains limit delete - sql = "delete from table_update_executor_test2 where id = 2;delete from table_update_executor_test2 where id = 2 limit 1;"; + sql = "delete from table_multi_executor_test2 where id = 2;delete from table_multi_executor_test2 where id = 2 limit 1;"; multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; @@ -184,7 +184,7 @@ public void testBeforeImageAndAfterImages() throws SQLException { Assertions.assertThrows(NotSupportYetException.class, executor::beforeImage); // contains order by and limit delete - sql = "delete from table_update_executor_test2 where id = 2;delete from table_update_executor_test2 where id = 2 order by id desc limit 1;"; + sql = "delete from table_multi_executor_test2 where id = 2;delete from table_multi_executor_test2 where id = 2 order by id desc limit 1;"; multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; @@ -193,7 +193,7 @@ public void testBeforeImageAndAfterImages() throws SQLException { //contains order by update - sql = "update table_update_executor_test set name = 'WILL' where id = 1;update table_update_executor_test set name = 'WILL' where id = 1 order by id desc;"; + sql = "update table_multi_executor_test set name = 'WILL' where id = 1;update table_multi_executor_test set name = 'WILL' where id = 1 order by id desc;"; multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; @@ -201,7 +201,7 @@ public void testBeforeImageAndAfterImages() throws SQLException { Assertions.assertThrows(NotSupportYetException.class, executor::beforeImage); //contains order by and limit update - sql = "update table_update_executor_test set name = 'WILL' where id = 1;update table_update_executor_test set name = 'WILL' where id = 1 order by id desc limit 1;"; + sql = "update table_multi_executor_test set name = 'WILL' where id = 1;update table_multi_executor_test set name = 'WILL' where id = 1 order by id desc limit 1;"; multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL); executor = new MultiExecutor(statementProxy, (statement, args) -> { return null; From 85b2f345196559019b2f819c2b4fb39f83307fee Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 22 Feb 2023 15:08:29 +0800 Subject: [PATCH 35/76] test: fix multi spring version test failed (#5382) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + dependencies/pom.xml | 6 ------ 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index ac9a77fce01..3db7e446a4b 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -44,6 +44,7 @@ Add changes here for all PR submitted to the develop branch. ### test: - [[#5380](https://github.com/seata/seata/pull/5380)] fix UpdateExecutorTest failed +- [[#5382](https://github.com/seata/seata/pull/5382)] fix multi spring version test failed Thanks to these contributors for their code commits. Please report an unintended omission. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 2be63ea969c..ace7cdd9c08 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -45,6 +45,7 @@ ### test: - [[#5380](https://github.com/seata/seata/pull/5380)] 修复 UpdateExecutorTest 单测失败问题 +- [[#5382](https://github.com/seata/seata/pull/5382)] 修复多Spring版本测试失败 非常感谢以下 contributors 的代码贡献。若有无意遗漏,请报告。 diff --git a/dependencies/pom.xml b/dependencies/pom.xml index e53f3475364..3137c5818c6 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -80,7 +80,6 @@ 1.4.19 0.10.5 - 2.13.4.1 0.6.0 1.2.9 6.5 @@ -616,11 +615,6 @@ jjwt-jackson ${jwt.version} - - com.fasterxml.jackson.core - jackson-databind - ${jackson.databind.version} - io.prometheus simpleclient_httpserver From 00ca98c7ce316bde6c08488e997dcc565169d30f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?WangLiang/=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Wed, 22 Feb 2023 16:06:07 +0800 Subject: [PATCH 36/76] optimize: unified project version (#5372) --- build/pom.xml | 2 +- core/pom.xml | 21 ++++++ .../java/io/seata/core/protocol/Version.java | 13 ++-- .../core/protocol/VersionInfo.java.template | 27 ++++++++ .../io/seata/core/protocol/VersionTest.java | 66 +++++++++++++++++++ 5 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/io/seata/core/protocol/VersionInfo.java.template create mode 100644 core/src/test/java/io/seata/core/protocol/VersionTest.java diff --git a/build/pom.xml b/build/pom.xml index 6a94233df26..6029f23b448 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -82,7 +82,7 @@ - 1.0.5 + 1.1.2 3.1.0 3.8.1 diff --git a/core/pom.xml b/core/pom.xml index 011bfba9dd3..ed099dce135 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -69,4 +69,25 @@ + + + + icu.easyj.maven.plugins + easyj-maven-plugin + + + io/seata/core/protocol/VersionInfo.java.template + + + + + generate-java-by-template + + replace-java + + + + + + diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java index 56e96f47c9e..2d17156c02c 100644 --- a/core/src/main/java/io/seata/core/protocol/Version.java +++ b/core/src/main/java/io/seata/core/protocol/Version.java @@ -36,7 +36,7 @@ public class Version { /** * The constant CURRENT. */ - private static final String CURRENT = "1.7.0-SNAPSHOT"; + private static final String CURRENT = VersionInfo.VERSION; private static final String VERSION_0_7_1 = "0.7.1"; private static final String VERSION_1_5_0 = "1.5.0"; private static final int MAX_VERSION_DOT = 3; @@ -113,13 +113,18 @@ public static boolean isAboveOrEqualVersion150(String version) { } public static long convertVersion(String version) throws IncompatibleVersionException { + if (StringUtils.isBlank(version)) { + throw new IllegalArgumentException("The version must not be blank."); + } + String[] parts = StringUtils.split(version, '.'); - long result = 0L; - int i = 1; int size = parts.length; if (size > MAX_VERSION_DOT + 1) { throw new IncompatibleVersionException("incompatible version format:" + version); } + + long result = 0L; + int i = 1; size = MAX_VERSION_DOT + 1; for (String part : parts) { if (StringUtils.isNumeric(part)) { @@ -140,7 +145,7 @@ public static long convertVersionNotThrowException(String version) { try { return convertVersion(version); } catch (Exception e) { - LOGGER.error("convert version error,version:{}",version,e); + LOGGER.error("convert version error,version:{}", version, e); } return -1; } diff --git a/core/src/main/java/io/seata/core/protocol/VersionInfo.java.template b/core/src/main/java/io/seata/core/protocol/VersionInfo.java.template new file mode 100644 index 00000000000..218631b6e4d --- /dev/null +++ b/core/src/main/java/io/seata/core/protocol/VersionInfo.java.template @@ -0,0 +1,27 @@ +/* + * Copyright 1999-2019 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.core.protocol; + +/** + * The interface VersionInfo. + * + * @author wang.liang + */ +interface VersionInfo { + + String VERSION = "${project.version}"; + +} diff --git a/core/src/test/java/io/seata/core/protocol/VersionTest.java b/core/src/test/java/io/seata/core/protocol/VersionTest.java new file mode 100644 index 00000000000..442da8a0658 --- /dev/null +++ b/core/src/test/java/io/seata/core/protocol/VersionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2019 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.core.protocol; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test {@link Version}. + * + * @author wang.liang + */ +public class VersionTest { + + @Test + public void testConvertVersion() { + // case: success + Assertions.assertDoesNotThrow(() -> { + long v = Version.convertVersion(Version.getCurrent()); + Assertions.assertTrue(v > 0); + }); + Assertions.assertDoesNotThrow(() -> { + long v = Version.convertVersion("1.7.0-SNAPSHOT"); + Assertions.assertEquals(1070000, v); + }); + Assertions.assertDoesNotThrow(() -> { + long v = Version.convertVersion("1.7.0"); + Assertions.assertEquals(1070000, v); + }); + Assertions.assertDoesNotThrow(() -> { + long v = Version.convertVersion("1.7.0-native-rc1-SNAPSHOT"); + Assertions.assertEquals(1070000, v); + }); + Assertions.assertDoesNotThrow(() -> { + long v = Version.convertVersion("1.7.0-native-rc1"); + Assertions.assertEquals(1070000, v); + }); + + // case: fail + Assertions.assertThrows(IllegalArgumentException.class, () -> { + Version.convertVersion(null); + }); + Assertions.assertThrows(IllegalArgumentException.class, () -> { + Version.convertVersion(" "); + }); + Assertions.assertThrows(IncompatibleVersionException.class, () -> { + Version.convertVersion("1.7.0.native.rc1-SNAPSHOT"); + }); + Assertions.assertThrows(IncompatibleVersionException.class, () -> { + Version.convertVersion("1.7.0.native.rc1"); + }); + } +} From 28b3413171108e80796e483a755e2c64e41fe164 Mon Sep 17 00:00:00 2001 From: justabug Date: Tue, 28 Feb 2023 11:06:20 +0800 Subject: [PATCH 37/76] bugfix : check if table meta cache should be refreshed in AT mode (#4734) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../seata/rm/datasource/DataSourceProxy.java | 48 ++------ .../exception/TableMetaException.java | 38 +++++++ .../exec/AbstractDMLBaseExecutor.java | 18 ++- .../exec/mysql/MySQLUpdateJoinExecutor.java | 1 + .../sql/struct/TableMetaCacheFactory.java | 104 ++++++++++++++++++ .../datasource/sql/struct/TableRecords.java | 17 ++- .../rm/datasource/DataSourceProxyTest.java | 3 +- .../sql/struct/TableRecordsTest.java | 37 +++++++ 10 files changed, 225 insertions(+), 43 deletions(-) create mode 100644 rm-datasource/src/main/java/io/seata/rm/datasource/exception/TableMetaException.java diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 3db7e446a4b..b0e026bd3ac 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -20,6 +20,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5299](https://github.com/seata/seata/pull/5299)] fix GlobalSession deletion when retry rollback or retry commit timeout - [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters - [[#5311](https://github.com/seata/seata/pull/5311)] remove RollbackRetryTimeout sessions during in file storage recover +- [[#4734](https://github.com/seata/seata/pull/4734)] check if table meta cache should be refreshed in AT mode - [[#5316](https://github.com/seata/seata/pull/5316)] fix G1 jvm parameter in jdk8 - [[#5321](https://github.com/seata/seata/pull/5321)] fix When the rollback logic on the TC side returns RollbackFailed, the custom FailureHandler is not executed - [[#5332](https://github.com/seata/seata/pull/5332)] fix bugs found in unit tests diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index ace7cdd9c08..d7ce2e04580 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -20,6 +20,7 @@ - [[#5299](https://github.com/seata/seata/pull/5299)] 修复TC端重试回滚或重试提交超时GlobalSession的删除问题 - [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug - [[#5311](https://github.com/seata/seata/pull/5311)] 移除基于文件存储恢复时的RollbackRetryTimeout事务 +- [[#4734](https://github.com/seata/seata/pull/4734)] 修复AT模式下新增字段产生的字段找不到 - [[#5316](https://github.com/seata/seata/pull/5316)] 修复jdk8 中 G1 参数 - [[#5321](https://github.com/seata/seata/pull/5321)] 修复当TC端回滚返回RollbackFailed时,自定义FailureHandler的方法未执行 - [[#5332](https://github.com/seata/seata/pull/5332)] 修复单元测试中发现的bug diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java index d0bcad362fd..4e87b9eac0f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java @@ -19,15 +19,13 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; + import javax.sql.DataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.seata.common.Constants; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.config.ConfigurationFactory; -import io.seata.common.ConfigurationKeys; import io.seata.core.constants.DBType; import io.seata.core.context.RootContext; import io.seata.core.model.BranchType; @@ -36,11 +34,6 @@ import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.rm.datasource.util.JdbcUtils; import io.seata.sqlparser.util.JdbcConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE; -import static io.seata.common.DefaultValues.DEFAULT_TABLE_META_CHECKER_INTERVAL; /** * The type Data source proxy. @@ -65,21 +58,6 @@ public class DataSourceProxy extends AbstractDataSourceProxy implements Resource private String version; - /** - * Enable the table meta checker - */ - private static boolean ENABLE_TABLE_META_CHECKER_ENABLE = ConfigurationFactory.getInstance().getBoolean( - ConfigurationKeys.CLIENT_TABLE_META_CHECK_ENABLE, DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE); - - /** - * Table meta checker interval - */ - private static final long TABLE_META_CHECKER_INTERVAL = ConfigurationFactory.getInstance().getLong( - ConfigurationKeys.CLIENT_TABLE_META_CHECKER_INTERVAL, DEFAULT_TABLE_META_CHECKER_INTERVAL); - - private final ScheduledExecutorService tableMetaExecutor = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("tableMetaChecker", 1, true)); - /** * Instantiates a new Data source proxy. * @@ -120,20 +98,18 @@ private void init(DataSource dataSource, String resourceGroupId) { } initResourceId(); DefaultResourceManager.get().registerResource(this); - if (ENABLE_TABLE_META_CHECKER_ENABLE) { - tableMetaExecutor.scheduleAtFixedRate(() -> { - try (Connection connection = dataSource.getConnection()) { - TableMetaCacheFactory.getTableMetaCache(DataSourceProxy.this.getDbType()) - .refresh(connection, DataSourceProxy.this.getResourceId()); - } catch (Exception ignore) { - } - }, 0, TABLE_META_CHECKER_INTERVAL, TimeUnit.MILLISECONDS); - } - + TableMetaCacheFactory.registerTableMeta(this); //Set the default branch type to 'AT' in the RootContext. RootContext.setDefaultBranchType(this.getBranchType()); } + /** + * publish tableMeta refresh event + */ + public void tableMetaRefreshEvent() { + TableMetaCacheFactory.tableMetaRefreshEvent(this.getResourceId()); + } + /** * Gets plain connection. * diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exception/TableMetaException.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exception/TableMetaException.java new file mode 100644 index 00000000000..7d321f2b60e --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exception/TableMetaException.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2019 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.rm.datasource.exception; + +import java.sql.SQLException; + +/** + * The type TableMetaException exception. + * + * @author Bughue + */ +public class TableMetaException extends SQLException { + private String columnName; + private String tableName; + + public TableMetaException(String tableName, String columnName) { + this.columnName = columnName; + this.tableName = tableName; + } + + public String getTableName() { + return tableName; + } + + public String getColumnName() { + return columnName; + } +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java index f1d5ebbce0a..305ef95622b 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java @@ -30,6 +30,7 @@ import io.seata.rm.datasource.ConnectionContext; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.exception.TableMetaException; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLRecognizer; import org.slf4j.Logger; @@ -93,11 +94,18 @@ public T doExecute(Object... args) throws Throwable { * @throws Exception the exception */ protected T executeAutoCommitFalse(Object[] args) throws Exception { - TableRecords beforeImage = beforeImage(); - T result = statementCallback.execute(statementProxy.getTargetStatement(), args); - TableRecords afterImage = afterImage(beforeImage); - prepareUndoLog(beforeImage, afterImage); - return result; + try { + TableRecords beforeImage = beforeImage(); + T result = statementCallback.execute(statementProxy.getTargetStatement(), args); + TableRecords afterImage = afterImage(beforeImage); + prepareUndoLog(beforeImage, afterImage); + return result; + } catch (TableMetaException e) { + LOGGER.error("table meta will be refreshed later, due to TableMetaException, table:{}, column:{}", + e.getTableName(), e.getColumnName()); + statementProxy.getConnectionProxy().getDataSourceProxy().tableMetaRefreshEvent(); + throw e; + } } private boolean isMultiPk() { diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java index 8077e51078e..555f9f5239e 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java @@ -257,6 +257,7 @@ protected TableMeta getTableMeta(String tableName) { * @param afterImage the after image * @return sql undo log */ + @Override protected SQLUndoLog buildUndoItem(TableRecords beforeImage, TableRecords afterImage) { SQLType sqlType = sqlRecognizer.getSQLType(); String tableName = beforeImage.getTableName(); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java index bd7b7fb890c..1a71aeefdf4 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java @@ -15,19 +15,57 @@ */ package io.seata.rm.datasource.sql.struct; +import java.sql.Connection; import java.util.Map; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import io.seata.common.ConfigurationKeys; import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; +import io.seata.config.ConfigurationFactory; +import io.seata.rm.datasource.DataSourceProxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE; +import static io.seata.common.DefaultValues.DEFAULT_TABLE_META_CHECKER_INTERVAL; /** + * Table meta cache factory + * * @author guoyao */ public class TableMetaCacheFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(TableMetaCacheFactory.class); + private static final Map TABLE_META_CACHE_MAP = new ConcurrentHashMap<>(); + private static final Map TABLE_META_REFRESH_HOLDER_MAP = new ConcurrentHashMap<>(); + + private static final long TABLE_META_REFRESH_INTERVAL_TIME = 1000L; + + private static final int MAX_QUEUE_SIZE = 2000; + + /** + * Enable the table meta checker + */ + private static boolean ENABLE_TABLE_META_CHECKER_ENABLE = ConfigurationFactory.getInstance() + .getBoolean(ConfigurationKeys.CLIENT_TABLE_META_CHECK_ENABLE, DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE); + + /** + * Table meta checker interval + */ + private static final long TABLE_META_CHECKER_INTERVAL = ConfigurationFactory.getInstance() + .getLong(ConfigurationKeys.CLIENT_TABLE_META_CHECKER_INTERVAL, DEFAULT_TABLE_META_CHECKER_INTERVAL); + + /** * get table meta cache * @@ -38,4 +76,70 @@ public static TableMetaCache getTableMetaCache(String dbType) { return CollectionUtils.computeIfAbsent(TABLE_META_CACHE_MAP, dbType, key -> EnhancedServiceLoader.load(TableMetaCache.class, dbType)); } + + /** + * register table meta + * + * @param dataSourceProxy + */ + public static void registerTableMeta(DataSourceProxy dataSourceProxy) { + TableMetaRefreshHolder holder = new TableMetaRefreshHolder(dataSourceProxy); + TABLE_META_REFRESH_HOLDER_MAP.put(dataSourceProxy.getResourceId(), holder); + } + + /** + * public tableMeta refresh event + */ + public static void tableMetaRefreshEvent(String resourceId) { + TableMetaRefreshHolder refreshHolder = TABLE_META_REFRESH_HOLDER_MAP.get(resourceId); + boolean offer = refreshHolder.tableMetaRefreshQueue.offer(System.currentTimeMillis()); + if (!offer) { + LOGGER.error("table refresh event offer error:{}", resourceId); + } + } + + static class TableMetaRefreshHolder { + private long lastRefreshFinishTime; + private DataSourceProxy dataSource; + private BlockingQueue tableMetaRefreshQueue; + + + private final Executor tableMetaRefreshExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>(), new NamedThreadFactory("tableMetaRefresh", 1, true)); + + TableMetaRefreshHolder(DataSourceProxy dataSource) { + this.dataSource = dataSource; + this.lastRefreshFinishTime = System.currentTimeMillis() - TABLE_META_REFRESH_INTERVAL_TIME; + this.tableMetaRefreshQueue = new LinkedBlockingQueue<>(MAX_QUEUE_SIZE); + + tableMetaRefreshExecutor.execute(() -> { + while (true) { + // 1. check table meta + if (ENABLE_TABLE_META_CHECKER_ENABLE + && System.currentTimeMillis() - lastRefreshFinishTime > TABLE_META_CHECKER_INTERVAL) { + tableMetaRefreshEvent(dataSource.getResourceId()); + } + + // 2. refresh table meta + try { + Long eventTime = tableMetaRefreshQueue.take(); + // if it has bean refreshed not long ago, skip + if (eventTime - lastRefreshFinishTime > TABLE_META_REFRESH_INTERVAL_TIME) { + try (Connection connection = dataSource.getConnection()) { + TableMetaCache tableMetaCache = + TableMetaCacheFactory.getTableMetaCache(dataSource.getDbType()); + tableMetaCache.refresh(connection, dataSource.getResourceId()); + } + lastRefreshFinishTime = System.currentTimeMillis(); + } + } catch (Exception exx) { + LOGGER.error("table refresh error:{}", exx.getMessage(), exx); + } + } + }); + } + + + + } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java index 7fda30ea98e..7c9f5420725 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java @@ -34,6 +34,7 @@ import javax.sql.rowset.serial.SerialJavaObject; import javax.sql.rowset.serial.SerialRef; import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.rm.datasource.exception.TableMetaException; import io.seata.rm.datasource.sql.serial.SerialArray; import static io.seata.rm.datasource.exec.oracle.OracleJdbcType.TIMESTAMP_WITH_LOCAL_TIME_ZONE; import static io.seata.rm.datasource.exec.oracle.OracleJdbcType.TIMESTAMP_WITH_TIME_ZONE; @@ -196,7 +197,7 @@ public static TableRecords buildRecords(TableMeta tmeta, ResultSet resultSet) th List fields = new ArrayList<>(columnCount); for (int i = 1; i <= columnCount; i++) { String colName = resultSetMetaData.getColumnName(i); - ColumnMeta col = tmeta.getColumnMeta(colName); + ColumnMeta col = getColumnMeta(tmeta,colName); int dataType = col.getDataType(); Field field = new Field(); field.setName(col.getColumnName()); @@ -259,6 +260,20 @@ public static TableRecords buildRecords(TableMeta tmeta, ResultSet resultSet) th return records; } + /** + * check if the column is null and return + * + * @param tmeta the table meta + * @param colName the column nmae + */ + private static ColumnMeta getColumnMeta(TableMeta tmeta , String colName) throws SQLException { + ColumnMeta col = tmeta.getColumnMeta(colName); + if (col == null) { + throw new TableMetaException(tmeta.getTableName(), colName); + } + return col; + } + /** * since there is no parameterless constructor for Blob, Clob and NClob just like mysql, * it needs to be converted to Serial_ type diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java index f3fb0678b36..a4e0fb8ecb9 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java @@ -22,6 +22,7 @@ import com.alibaba.druid.pool.DruidDataSource; import io.seata.rm.datasource.mock.MockDataSource; import io.seata.rm.datasource.mock.MockDriver; +import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -44,7 +45,7 @@ public void test_constructor() { @Test public void getResourceIdTest() throws SQLException, NoSuchFieldException, IllegalAccessException { // Disable 'DataSourceProxy.tableMetaExecutor' to prevent unit tests from being affected - Field enableField = DataSourceProxy.class.getDeclaredField("ENABLE_TABLE_META_CHECKER_ENABLE"); + Field enableField = TableMetaCacheFactory.class.getDeclaredField("ENABLE_TABLE_META_CHECKER_ENABLE"); enableField.setAccessible(true); enableField.set(null, false); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java index e1772fa21eb..556f60fdcbf 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java @@ -20,6 +20,7 @@ import java.sql.Types; import java.util.List; +import io.seata.rm.datasource.exception.TableMetaException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -48,6 +49,15 @@ public class TableRecordsTest { new Object[] {"", "", "table_records_test", "description", Types.CLOB, "CLOB", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, }; + private static Object[][] columnMetasNewField = + new Object[][] { + new Object[] {"", "", "table_records_test", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, + new Object[] {"", "", "table_records_test", "name", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + new Object[] {"", "", "table_records_test", "information", Types.BLOB, "BLOB", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + new Object[] {"", "", "table_records_test", "description", Types.CLOB, "CLOB", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + new Object[] {"", "", "table_records_test", "newf", Types.CLOB, "CLOB", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + }; + private static Object[][] indexMetas = new Object[][] { new Object[] {"PRIMARY", "id", false, "", 3, 1, "A", 34}, @@ -55,12 +65,20 @@ public class TableRecordsTest { private static List returnValueColumnLabels = Lists.newArrayList("id", "name", "information", "description"); + private static List returnValueColumnLabelsNewField = Lists.newArrayList("id", "name", "information", "description","newf"); + private static Object[][] returnValue = new Object[][] { new Object[] {1, "Tom", "hello", "world"}, new Object[] {2, "Jack", "hello", "world"}, }; + private static Object[][] returnValueNewField = + new Object[][] { + new Object[] {1, "Tom", "hello", "world","newf"}, + new Object[] {2, "Jack", "hello", "world","newf"}, + }; + @BeforeEach public void initBeforeEach() { } @@ -115,6 +133,25 @@ public void testBuildRecords() throws SQLException { Assertions.assertNotNull(tableRecords); } + @Test + public void testBuildRecordsNewFeild() throws SQLException { + MockDriver mockDriver = new MockDriver(returnValueColumnLabels, returnValue, columnMetas, indexMetas); + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setDriver(mockDriver); + MockStatementBase mockStatement = new MockStatement(dataSource.getConnection().getConnection()); + DataSourceProxy proxy = new DataSourceProxy(dataSource); + + TableMeta tableMeta = TableMetaCacheFactory.getTableMetaCache(JdbcConstants.MYSQL).getTableMeta(proxy.getPlainConnection(), + "table_records_test", proxy.getResourceId()); + + + // 模拟新字段增加 + MockDriver mockDriverNewField = new MockDriver(returnValueColumnLabelsNewField, returnValueNewField, columnMetasNewField, indexMetas); + ResultSet resultSet = mockDriverNewField.executeQuery(mockStatement, "select * from table_records_test"); + Assertions.assertThrows(TableMetaException.class, () -> TableRecords.buildRecords(tableMeta, resultSet)); + } + @Test public void testEmpty() { TableRecords.EmptyTableRecords emptyTableRecords = new TableRecords.EmptyTableRecords(); From bb7e373b8fab7263a6f0105e93791e175270ab68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?WangLiang/=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Thu, 2 Mar 2023 14:01:16 +0800 Subject: [PATCH 38/76] optimize: publish images based on java `8`, `8-slim`, `17`, `17-slim` (#5168) --- .github/workflows/build.yml | 50 +++++++++++++------------ .github/workflows/publishes.yml | 65 +++++++++++++++++++++++---------- .github/workflows/test.yml | 6 +-- build/pom.xml | 6 +-- console/pom.xml | 9 +++++ pom.xml | 26 +++++++++++-- server/pom.xml | 2 +- 7 files changed, 109 insertions(+), 55 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9c8db4f4d44..6357e31d0f0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,53 +7,55 @@ on: branches: [ 2.x, develop, master ] jobs: - build_arm64-binary: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/2.x') }} - strategy: - fail-fast: false - steps: - - uses: actions/checkout@v2 - - name: Set up QEMU - id: qemu - uses: docker/setup-qemu-action@v1 - - name: Build arm-binary - run: | - docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ - arm64v8/ubuntu:20.04 \ - bash -exc 'apt-get update -y && \ - apt-get install maven -y && \ - mvn -Prelease-seata -Dmaven.test.skip=true clean install -U' - + # job 1: Test based on java 8 and 17. Do not checkstyle. build: name: "build" runs-on: ubuntu-latest strategy: fail-fast: false matrix: - java: [ 8, 11 ] + java: [ 8, 17 ] steps: # step 1 - name: "Checkout" uses: actions/checkout@v2.4.0 - # step 2 - name: "Set up Java JDK" uses: actions/setup-java@v2.5.0 with: distribution: 'zulu' java-version: ${{ matrix.java }} - # step 3 - name: "Build with Maven" run: | if [ "${{ matrix.java }}" == "8" ]; then ./mvnw -T 4C clean test -Dcheckstyle.skip=false -Dlicense.skip=false -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; - elif [ "${{ matrix.java }}" == "11" ]; then + elif [ "${{ matrix.java }}" == "17" ]; then ./mvnw -T 4C clean test -Dcheckstyle.skip=true -Dlicense.skip=true -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; fi - # step 4 - name: "Codecov" - if: matrix.java == '8' + if: matrix.java == '17' uses: codecov/codecov-action@v2.1.0 + + # job 2: Test on 'arm64v8/ubuntu' OS. + build_arm64-binary: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'snapshot' || github.ref_name == '2.x') }} + strategy: + fail-fast: false + steps: + # step 1 + - uses: actions/checkout@v2 + # step 2 + - name: Set up QEMU + id: qemu + uses: docker/setup-qemu-action@v1 + # step 3 + - name: Build arm-binary + run: | + docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ + arm64v8/ubuntu:20.04 \ + bash -exc 'apt-get update -y && \ + apt-get install maven -y && \ + mvn -Prelease-seata -Dmaven.test.skip=true clean install -U' diff --git a/.github/workflows/publishes.yml b/.github/workflows/publishes.yml index 3ab37947947..fab3a5d828b 100644 --- a/.github/workflows/publishes.yml +++ b/.github/workflows/publishes.yml @@ -10,48 +10,73 @@ on: - cron: '0 16 * * *' #GMT+0 jobs: - publish: - name: "Publish" + # job 1 + publish-to-OSSRH: + name: "Publish to OSSRH" runs-on: ubuntu-latest strategy: fail-fast: false - matrix: - type: [ "OSSRH", "image" ] steps: # step 1 - name: "Checkout" uses: actions/checkout@v2.4.0 - # step 2 - name: "Setup Java JDK" - uses: actions/setup-java@v2.5.0 + uses: actions/setup-java@v3.9.0 with: distribution: 'zulu' java-version: 8 server-id: oss_seata - server-username: OSSRH_USERNAME - server-password: OSSRH_PASSWORD - - # step 3 for type=OSSRH - - name: "Import GPG-SECRET-KEY, Package and Publish-To-OSSRH" - if: matrix.type == 'OSSRH' + server-username: OSSRH_USERNAME # Environment variable name for the username for authentication to the Apache Maven repository. Default is $GITHUB_ACTOR + server-password: OSSRH_PASSWORD # Environment variable name for password or token for authentication to the Apache Maven repository. Default is $GITHUB_TOKEN + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE # Environment variable name for the GPG private key passphrase. Default is $GPG_PASSPHRASE + # step 3 + - name: "Publish to OSSRH" env: OSSRH_USERNAME: ${{ secrets.OSSRH_USER }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} run: | - cat <(echo -e "${{ secrets.GPG_PRIVATE_KEY }}") | gpg --batch --import; - ./mvnw -T 4C clean deploy -Prelease,release-by-github-actions -Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }} -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn + ./mvnw -T 4C clean deploy -Prelease,release-by-github-actions -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn - # step 4 for type=image - - name: "Package and Publish-Image-To-DockerHub" - if: matrix.type == 'image' + # job 2 + publish-images-to-dockerhub: + name: "Publish images to DockerHub" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + java: [ 8, 17 ] + steps: + # step 1 + - name: "Checkout" + uses: actions/checkout@v2.4.0 + # step 2 + - name: "Setup Java JDK" + uses: actions/setup-java@v3.9.0 + with: + distribution: 'zulu' + java-version: ${{ matrix.java }} + # step 3 based on java8 + - name: "Publish images to DockerHub based on java8" + if: matrix.java == 8 env: - IMAGE_NAME: openjdk:8u342 REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | if [ "${{ github.ref_name }}" == "develop" ] || [ "${{ github.ref_name }}" == "snapshot" || [ "${{ github.ref_name }}" == "2.x" ]; then - ./mvnw -T 4C clean package -Pimage -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; + ./mvnw -T 4C clean package -Dimage.name=openjdk:8u342 -Pimage -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; else - ./mvnw -T 4C clean package -Pimage,release-image -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; + ./mvnw -T 4C clean package -Dimage.name=openjdk:8u342 -Pimage,release-image-based-on-java8 -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; + ./mvnw -T 4C clean package -Dimage.name=openjdk:8u342-slim -Pimage,release-image-based-on-java8-slim -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; fi + # step 3 based on java17 + - name: "Publish images to DockerHub based on java17" + if: ${{ matrix.java == 17 && github.ref_name != 'develop' && github.ref_name != 'snapshot' && github.ref_name != '2.x' }} + env: + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + run: | + ./mvnw -T 4C clean package -Dimage.name=openjdk:17.0.2 -Pimage,release-image-based-on-java17 -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; + ./mvnw -T 4C clean package -Dimage.name=openjdk:17.0.2-slim -Pimage,release-image-based-on-java17-slim -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 418102858b1..173eb6a1e81 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: matrix: java: [ 8, 11, 17 ] springboot: [ - 2.7.6 -Dspring-framework.version=5.3.24, + 2.7.8 -Dspring-framework.version=5.3.25, 2.6.14 -Dspring-framework.version=5.3.24, 2.5.14 -Dspring-framework.version=5.3.20, 2.4.13 -Dspring-framework.version=5.3.13, @@ -58,7 +58,7 @@ jobs: matrix: java: [ 17 ] springboot: [ - 3.0.0 -Dspring-framework.version=6.0.2 -Dspring-boot-for-server.version=2.4.13 -Dspring-framework-for-server.version=5.3.18 -Dkotlin-maven-plugin.version=1.7.22 + 3.0.2 -Dspring-framework.version=6.0.4 -Dspring-boot-for-server.version=2.5.14 -Dspring-framework-for-server.version=5.3.20 -Dkotlin-maven-plugin.version=1.7.22 ] steps: # step 1 @@ -82,7 +82,7 @@ jobs: fail-fast: false matrix: springboot: [ - 2.7.6 -Dspring-framework.version=5.3.24, + 2.7.8 -Dspring-framework.version=5.3.25, 2.6.14 -Dspring-framework.version=5.3.24, 2.5.14 -Dspring-framework.version=5.3.20, 2.4.13 -Dspring-framework.version=5.3.13, diff --git a/build/pom.xml b/build/pom.xml index 6029f23b448..3dbd16d8d49 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -73,7 +73,7 @@ UTF-8 - 2.5.13 + 2.5.14 5.3.20 @@ -126,6 +126,7 @@ true + ${IMAGE_NAME} latest true @@ -300,9 +301,6 @@ release - - ${project.version},latest - diff --git a/console/pom.xml b/console/pom.xml index 46fd8335c6b..62147c66d34 100644 --- a/console/pom.xml +++ b/console/pom.xml @@ -35,6 +35,15 @@ + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + org.springframework diff --git a/pom.xml b/pom.xml index 90e31432011..49fcea98100 100644 --- a/pom.xml +++ b/pom.xml @@ -155,19 +155,39 @@ image false - latest false 5.1.42 8.0.27 - + - release-image + release-image-based-on-java8 ${project.version},latest + + + release-image-based-on-java8-slim + + ${project.version}-slim + + + + + release-image-based-on-java17 + + ${project.version}.jre17 + + + + + release-image-based-on-java17-slim + + ${project.version}.jre17-slim + + arrch64 diff --git a/server/pom.xml b/server/pom.xml index c2e3589e33c..aa227193dc9 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -289,7 +289,7 @@ ${jib-maven-plugin.version} - ${IMAGE_NAME} + ${image.name} linux From 51f4b19c18be473219bbc96ff000e8c39e546d96 Mon Sep 17 00:00:00 2001 From: jimin Date: Sat, 4 Mar 2023 22:24:04 +0800 Subject: [PATCH 39/76] bugfix: fix bad service configuration file and compilation failure (#5413) Signed-off-by: slievrly --- build/pom.xml | 2 +- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build/pom.xml b/build/pom.xml index 3dbd16d8d49..e6dab8b81b3 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -73,7 +73,7 @@ UTF-8 - 2.5.14 + 2.5.13 5.3.20 diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index b0e026bd3ac..892f0596b85 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -24,6 +24,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5316](https://github.com/seata/seata/pull/5316)] fix G1 jvm parameter in jdk8 - [[#5321](https://github.com/seata/seata/pull/5321)] fix When the rollback logic on the TC side returns RollbackFailed, the custom FailureHandler is not executed - [[#5332](https://github.com/seata/seata/pull/5332)] fix bugs found in unit tests +- [[#5413](https://github.com/seata/seata/pull/5413)] fix bad service configuration file and compilation failure ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index d7ce2e04580..50ee02fa5fc 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -24,6 +24,7 @@ - [[#5316](https://github.com/seata/seata/pull/5316)] 修复jdk8 中 G1 参数 - [[#5321](https://github.com/seata/seata/pull/5321)] 修复当TC端回滚返回RollbackFailed时,自定义FailureHandler的方法未执行 - [[#5332](https://github.com/seata/seata/pull/5332)] 修复单元测试中发现的bug +- [[#5413](https://github.com/seata/seata/pull/5413)] 修复 arm64平台下的JDK和Spring兼容问题 ### optimize: From d001af10fcc971619c573af3914447589b8ef2ce Mon Sep 17 00:00:00 2001 From: jimin Date: Sat, 4 Mar 2023 23:01:37 +0800 Subject: [PATCH 40/76] optimize: optimize transaction fail handler (#5414) Signed-off-by: slievrly --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../exception/TransactionExceptionCode.java | 7 ++- .../io/seata/core/model/GlobalStatus.java | 47 +++++++++---------- .../GlobalTransactionalInterceptor.java | 35 +++++++++++--- .../tm/api/DefaultFailureHandlerImpl.java | 7 +-- .../java/io/seata/tm/api/FailureHandler.java | 8 +--- .../seata/tm/api/TransactionalExecutor.java | 13 ++--- .../seata/tm/api/TransactionalTemplate.java | 38 +++++++++------ 9 files changed, 88 insertions(+), 69 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 892f0596b85..d656c1ab4fd 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -40,6 +40,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5325](https://github.com/seata/seata/pull/5325)] add store mode,config type and registry type log info - [[#5315](https://github.com/seata/seata/pull/5315)] optimize the log of SPI - [[#5323](https://github.com/seata/seata/pull/5323)] add time info for global transaction timeout log +- [[#5414](https://github.com/seata/seata/pull/5414)] optimize transaction fail handler ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 50ee02fa5fc..7738a13e05b 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -40,6 +40,7 @@ - [[#5325](https://github.com/seata/seata/pull/5325)] 添加配置中心、注册中心类型以及存储模式日志信息 - [[#5315](https://github.com/seata/seata/pull/5315)] 优化SPI加载日志 - [[#5323](https://github.com/seata/seata/pull/5323)] 为全局事务超时日志添加时间信息 +- [[#5414](https://github.com/seata/seata/pull/5414)] 优化事务失败处理 handler ### security: diff --git a/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java b/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java index eb62bbd203f..835d31532cd 100644 --- a/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java +++ b/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java @@ -120,7 +120,12 @@ public enum TransactionExceptionCode { /** * Lock key conflict fail fast transaction exception code. */ - LockKeyConflictFailFast + LockKeyConflictFailFast, + + /** + * transaction already timeout + */ + TransactionTimeout ; diff --git a/core/src/main/java/io/seata/core/model/GlobalStatus.java b/core/src/main/java/io/seata/core/model/GlobalStatus.java index fdfc0926ee1..5e6e6fa5f8f 100644 --- a/core/src/main/java/io/seata/core/model/GlobalStatus.java +++ b/core/src/main/java/io/seata/core/model/GlobalStatus.java @@ -15,7 +15,6 @@ */ package io.seata.core.model; - /** * Status of global transaction. * @@ -27,119 +26,118 @@ public enum GlobalStatus { * Un known global status. */ // Unknown - UnKnown(0), + UnKnown(0, "an ambiguous transaction state, usually use before begin"), /** * The Begin. */ // PHASE 1: can accept new branch registering. - Begin(1), + Begin(1, "global transaction start"), /** * PHASE 2: Running Status: may be changed any time. */ // Committing. - Committing(2), + Committing(2, "2Phase committing"), /** * The Commit retrying. */ // Retrying commit after a recoverable failure. - CommitRetrying(3), + CommitRetrying(3, "2Phase committing failure retry"), /** * Rollbacking global status. */ // Rollbacking - Rollbacking(4), + Rollbacking(4, "2Phase rollbacking"), /** * The Rollback retrying. */ // Retrying rollback after a recoverable failure. - RollbackRetrying(5), + RollbackRetrying(5, "2Phase rollbacking failure retry"), /** * The Timeout rollbacking. */ // Rollbacking since timeout - TimeoutRollbacking(6), + TimeoutRollbacking(6, "after global transaction timeout rollbacking"), /** * The Timeout rollback retrying. */ // Retrying rollback (since timeout) after a recoverable failure. - TimeoutRollbackRetrying(7), + TimeoutRollbackRetrying(7, "after global transaction timeout rollback retrying"), /** * All branches can be async committed. The committing is NOT done yet, but it can be seen as committed for TM/RM * client. */ - AsyncCommitting(8), + AsyncCommitting(8, "2Phase committing, used for AT mode"), /** * PHASE 2: Final Status: will NOT change any more. */ // Finally: global transaction is successfully committed. - Committed(9), + Committed(9, "global transaction completed with status committed"), /** * The Commit failed. */ // Finally: failed to commit - CommitFailed(10), + CommitFailed(10, "2Phase commit failed"), /** * The Rollbacked. */ // Finally: global transaction is successfully rollbacked. - Rollbacked(11), + Rollbacked(11, "global transaction completed with status rollbacked"), /** * The Rollback failed. */ // Finally: failed to rollback - RollbackFailed(12), + RollbackFailed(12, "global transaction completed but rollback failed"), /** * The Timeout rollbacked. */ // Finally: global transaction is successfully rollbacked since timeout. - TimeoutRollbacked(13), + TimeoutRollbacked(13, "global transaction completed with rollback due to timeout"), /** * The Timeout rollback failed. */ // Finally: failed to rollback since timeout - TimeoutRollbackFailed(14), + TimeoutRollbackFailed(14, "global transaction was rollbacking due to timeout, but failed"), /** * The Finished. */ // Not managed in session MAP any more - Finished(15), + Finished(15, "ambiguous transaction status for non-exist transaction and global report for Saga"), /** * The commit retry Timeout . */ // Finally: failed to commit since retry timeout - CommitRetryTimeout(16), + CommitRetryTimeout(16, "global transaction still failed after commit failure and retries for some time"), /** * The rollback retry Timeout . */ // Finally: failed to rollback since retry timeout - RollbackRetryTimeout(17) - - ; + RollbackRetryTimeout(17, "global transaction still failed after commit failure and retries for some time"); private final int code; + private final String desc; - GlobalStatus(int code) { + GlobalStatus(int code, String desc) { this.code = code; + this.desc = desc; } - /** * Gets code. * @@ -149,7 +147,6 @@ public int getCode() { return code; } - /** * Get global status. * @@ -157,7 +154,7 @@ public int getCode() { * @return the global status */ public static GlobalStatus get(byte code) { - return get((int) code); + return get((int)code); } /** diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java index 7bc8609ecad..9aa45a969c9 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java @@ -34,6 +34,8 @@ import io.seata.core.constants.ConfigurationKeys; import io.seata.core.event.EventBus; import io.seata.core.event.GuavaEventBus; +import io.seata.core.exception.TmTransactionException; +import io.seata.core.exception.TransactionExceptionCode; import io.seata.core.model.GlobalLockConfig; import io.seata.rm.GlobalLockExecutor; import io.seata.rm.GlobalLockTemplate; @@ -247,9 +249,14 @@ public TransactionInfo getTransactionInfo() { } catch (TransactionalExecutor.ExecutionException e) { TransactionalExecutor.Code code = e.getCode(); Throwable cause = e.getCause(); + boolean timeout = isTimeoutException(cause); switch (code) { case RollbackDone: - throw e.getOriginalException(); + if (timeout) { + throw cause; + } else { + throw e.getOriginalException(); + } case BeginFailure: succeed = false; failureHandler.onBeginFailure(e.getTransaction(), cause); @@ -261,12 +268,13 @@ public TransactionInfo getTransactionInfo() { case RollbackFailure: failureHandler.onRollbackFailure(e.getTransaction(), e.getOriginalException()); throw e.getOriginalException(); - case RollbackRetrying: - failureHandler.onRollbackRetrying(e.getTransaction(), e.getOriginalException()); - throw e.getOriginalException(); - case TimeoutRollback: - failureHandler.onTimeoutRollback(e.getTransaction(), e.getOriginalException()); - throw cause; + case Rollbacking: + failureHandler.onRollbacking(e.getTransaction(), e.getOriginalException()); + if (timeout) { + throw cause; + } else { + throw e.getOriginalException(); + } default: throw new ShouldNeverHappenException(String.format("Unknown TransactionalExecutor.Code: %s", code)); } @@ -349,6 +357,19 @@ private static void startDegradeCheck() { }, degradeCheckPeriod, degradeCheckPeriod, TimeUnit.MILLISECONDS); } + private boolean isTimeoutException(Throwable th) { + if (null == th) { + return false; + } + if (th instanceof TmTransactionException) { + TmTransactionException exx = (TmTransactionException)th; + if (TransactionExceptionCode.TransactionTimeout == exx.getCode()) { + return true; + } + } + return false; + } + @Subscribe public static void onDegradeCheck(DegradeCheckEvent event) { if (event.isRequestSuccess()) { diff --git a/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java b/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java index af1d5156d52..2a6e76eaef5 100644 --- a/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java +++ b/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java @@ -70,17 +70,12 @@ public void onRollbackFailure(GlobalTransaction tx, Throwable originalException) } @Override - public void onRollbackRetrying(GlobalTransaction tx, Throwable originalException) { + public void onRollbacking(GlobalTransaction tx, Throwable originalException) { StackTraceLogger.warn(LOGGER, originalException, "Retrying to rollback transaction[{}]", new String[] {tx.getXid()}); timer.newTimeout(new CheckTimerTask(tx, GlobalStatus.RollbackRetrying), SCHEDULE_INTERVAL_SECONDS, TimeUnit.SECONDS); } - @Override - public void onTimeoutRollback(GlobalTransaction tx, Throwable originalException) { - StackTraceLogger.warn(LOGGER, originalException, "Transaction timeout rollback[{}]", new String[] {tx.getXid()}); - } - protected class CheckTimerTask implements TimerTask { private final GlobalTransaction tx; diff --git a/tm/src/main/java/io/seata/tm/api/FailureHandler.java b/tm/src/main/java/io/seata/tm/api/FailureHandler.java index 4921ae994b8..32547fc746d 100644 --- a/tm/src/main/java/io/seata/tm/api/FailureHandler.java +++ b/tm/src/main/java/io/seata/tm/api/FailureHandler.java @@ -52,12 +52,6 @@ public interface FailureHandler { * @param tx the tx * @param originalException the originalException */ - void onRollbackRetrying(GlobalTransaction tx, Throwable originalException); + void onRollbacking(GlobalTransaction tx, Throwable originalException); - /** - * On timeout rollback - * @param tx the tx - * @param originalException the originalException - */ - void onTimeoutRollback(GlobalTransaction tx, Throwable originalException); } diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalExecutor.java b/tm/src/main/java/io/seata/tm/api/TransactionalExecutor.java index dfa526c778b..50116ca3cdd 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalExecutor.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalExecutor.java @@ -38,12 +38,15 @@ public interface TransactionalExecutor { */ TransactionInfo getTransactionInfo(); - /** * The enum Code. */ enum Code { + /** + * Unknown code. + */ + Unknown, /** * Begin failure code. */ @@ -78,13 +81,7 @@ enum Code { * Rollback retrying code. */ // - RollbackRetrying, - - /** - * Timeout Rollback code. - */ - // - TimeoutRollback + Rollbacking } /** diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java index 0cf360a8d0d..1c6f2aed5b3 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java @@ -15,21 +15,19 @@ */ package io.seata.tm.api; -import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeoutException; import io.seata.common.exception.ShouldNeverHappenException; import io.seata.core.context.GlobalLockConfigHolder; +import io.seata.core.exception.TmTransactionException; import io.seata.core.exception.TransactionException; +import io.seata.core.exception.TransactionExceptionCode; import io.seata.core.model.GlobalLockConfig; -import io.seata.core.model.GlobalStatus; import io.seata.tm.api.transaction.Propagation; import io.seata.tm.api.transaction.SuspendedResourcesHolder; import io.seata.tm.api.transaction.TransactionHook; import io.seata.tm.api.transaction.TransactionHookManager; import io.seata.tm.api.transaction.TransactionInfo; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -212,13 +210,20 @@ private void commitTransaction(GlobalTransaction tx, TransactionInfo txInfo) try { triggerBeforeCommit(); tx.commit(); - - if (Arrays.asList(GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbacked).contains(tx.getLocalStatus())) { - throw new TransactionalExecutor.ExecutionException(tx, - new TimeoutException(String.format("Global transaction[%s] is timeout and will be rollback[TC].", tx.getXid())), - TransactionalExecutor.Code.TimeoutRollback); + TransactionalExecutor.Code code = TransactionalExecutor.Code.Unknown; + switch (tx.getLocalStatus()) { + case TimeoutRollbacking: + code = TransactionalExecutor.Code.Rollbacking; + break; + case TimeoutRollbacked: + code = TransactionalExecutor.Code.RollbackDone; + break; + default: + } + if (code != TransactionalExecutor.Code.Unknown) { + Exception exx = new TmTransactionException(TransactionExceptionCode.TransactionTimeout, String.format("Global transaction[%s] is timeout and will be rollback[TC].", tx.getXid())); + throw new TransactionalExecutor.ExecutionException(tx, exx, code); } - triggerAfterCommit(); } catch (TransactionException txe) { // 4.1 Failed to commit @@ -249,16 +254,19 @@ private void rollbackTransaction(GlobalTransaction tx, Throwable originalExcepti break; case Rollbacking: case RollbackRetrying: - code = TransactionalExecutor.Code.RollbackRetrying; - break; case TimeoutRollbacking: case TimeoutRollbackRetrying: - case TimeoutRollbacked: - code = TransactionalExecutor.Code.TimeoutRollback; + code = TransactionalExecutor.Code.Rollbacking; break; + case TimeoutRollbacked: case Rollbacked: - default: + //rollback transactions but do not exist are usually considered completed + case Finished: code = TransactionalExecutor.Code.RollbackDone; + break; + default: + code = TransactionalExecutor.Code.Unknown; + LOGGER.warn("{} rollback in the state {}", tx.getXid(), tx.getLocalStatus()); } throw new TransactionalExecutor.ExecutionException(tx, code, originalException); From ee0f7448df01cb8ff0d8edc7ddc2a4a7962cccbb Mon Sep 17 00:00:00 2001 From: jimin Date: Sun, 5 Mar 2023 00:13:39 +0800 Subject: [PATCH 41/76] bugfix: fix transaction timeout on client side not execute hook and failureHandler (#5415) Signed-off-by: slievrly --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index d656c1ab4fd..0866bbdacab 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -25,6 +25,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5321](https://github.com/seata/seata/pull/5321)] fix When the rollback logic on the TC side returns RollbackFailed, the custom FailureHandler is not executed - [[#5332](https://github.com/seata/seata/pull/5332)] fix bugs found in unit tests - [[#5413](https://github.com/seata/seata/pull/5413)] fix bad service configuration file and compilation failure +- [[#5415](https://github.com/seata/seata/pull/5415)] fix transaction timeout on client side not execute hook and failureHandler ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 7738a13e05b..5c5a87ca520 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -25,6 +25,7 @@ - [[#5321](https://github.com/seata/seata/pull/5321)] 修复当TC端回滚返回RollbackFailed时,自定义FailureHandler的方法未执行 - [[#5332](https://github.com/seata/seata/pull/5332)] 修复单元测试中发现的bug - [[#5413](https://github.com/seata/seata/pull/5413)] 修复 arm64平台下的JDK和Spring兼容问题 +- [[#5415](https://github.com/seata/seata/pull/5415)] 修复客户侧事务提交前超时未执行hook和failureHandler的问题 ### optimize: diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java index 1c6f2aed5b3..9479bcf100f 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java @@ -202,8 +202,9 @@ private void commitTransaction(GlobalTransaction tx, TransactionInfo txInfo) throws TransactionalExecutor.ExecutionException, TransactionException { if (isTimeout(tx.getCreateTime(), txInfo)) { // business execution timeout - LOGGER.info("TM detected timeout, xid = {}", tx.getXid()); - tx.rollback(); + Exception exx = new TmTransactionException(TransactionExceptionCode.TransactionTimeout, + String.format("client detected transaction timeout before commit, so change to rollback, xid = %s", tx.getXid())); + rollbackTransaction(tx, exx); return; } From 98c17a51c74eb88c087f5ecf22746054367a4519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?WangLiang/=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Wed, 8 Mar 2023 10:35:37 +0800 Subject: [PATCH 42/76] optimize: upgrade easyj-maven-plugin to 1.1.5 for support maven 3.9.0 (#5402) --- .github/workflows/build.yml | 45 ++++++++++++++++++--------------- .github/workflows/publishes.yml | 10 ++++++-- .github/workflows/test.yml | 44 +++++++++++++++++++++----------- build/pom.xml | 2 +- pom.xml | 5 ++++ 5 files changed, 68 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6357e31d0f0..6839bbba2d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,9 @@ jobs: distribution: 'zulu' java-version: ${{ matrix.java }} # step 3 + - name: "Print maven version" + run: ./mvnw -version + # step 4 - name: "Build with Maven" run: | if [ "${{ matrix.java }}" == "8" ]; then @@ -33,29 +36,31 @@ jobs: elif [ "${{ matrix.java }}" == "17" ]; then ./mvnw -T 4C clean test -Dcheckstyle.skip=true -Dlicense.skip=true -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; fi - # step 4 + # step 5 - name: "Codecov" if: matrix.java == '17' uses: codecov/codecov-action@v2.1.0 # job 2: Test on 'arm64v8/ubuntu' OS. build_arm64-binary: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'snapshot' || github.ref_name == '2.x') }} - strategy: - fail-fast: false - steps: - # step 1 - - uses: actions/checkout@v2 - # step 2 - - name: Set up QEMU - id: qemu - uses: docker/setup-qemu-action@v1 - # step 3 - - name: Build arm-binary - run: | - docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ - arm64v8/ubuntu:20.04 \ - bash -exc 'apt-get update -y && \ - apt-get install maven -y && \ - mvn -Prelease-seata -Dmaven.test.skip=true clean install -U' + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'snapshot' || github.ref_name == '2.x') }} + strategy: + fail-fast: false + steps: + # step 1 + - name: "Checkout" + uses: actions/checkout@v2 + # step 2 + - name: "Set up QEMU" + id: qemu + uses: docker/setup-qemu-action@v1 + # step 3 + - name: "Build arm-binary" + run: | + docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ + arm64v8/ubuntu:20.04 \ + bash -exc 'apt-get update -y && \ + apt-get install maven -y && \ + mvn -version && \ + mvn -Prelease-seata -DskipTests clean install -U' diff --git a/.github/workflows/publishes.yml b/.github/workflows/publishes.yml index fab3a5d828b..9e179e7f9b4 100644 --- a/.github/workflows/publishes.yml +++ b/.github/workflows/publishes.yml @@ -32,6 +32,9 @@ jobs: gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} gpg-passphrase: GPG_PASSPHRASE # Environment variable name for the GPG private key passphrase. Default is $GPG_PASSPHRASE # step 3 + - name: "Print maven version" + run: ./mvnw -version + # step 4 - name: "Publish to OSSRH" env: OSSRH_USERNAME: ${{ secrets.OSSRH_USER }} @@ -58,7 +61,10 @@ jobs: with: distribution: 'zulu' java-version: ${{ matrix.java }} - # step 3 based on java8 + # step 3 + - name: "Print maven version" + run: ./mvnw -version + # step 4 based on java8 - name: "Publish images to DockerHub based on java8" if: matrix.java == 8 env: @@ -71,7 +77,7 @@ jobs: ./mvnw -T 4C clean package -Dimage.name=openjdk:8u342 -Pimage,release-image-based-on-java8 -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; ./mvnw -T 4C clean package -Dimage.name=openjdk:8u342-slim -Pimage,release-image-based-on-java8-slim -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; fi - # step 3 based on java17 + # step 4 based on java17 - name: "Publish images to DockerHub based on java17" if: ${{ matrix.java == 17 && github.ref_name != 'develop' && github.ref_name != 'snapshot' && github.ref_name != '2.x' }} env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 173eb6a1e81..2bb618dc5ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: matrix: java: [ 8, 11, 17 ] springboot: [ - 2.7.8 -Dspring-framework.version=5.3.25, + 2.7.9 -Dspring-framework.version=5.3.25, 2.6.14 -Dspring-framework.version=5.3.24, 2.5.14 -Dspring-framework.version=5.3.20, 2.4.13 -Dspring-framework.version=5.3.13, @@ -40,6 +40,9 @@ jobs: distribution: 'zulu' java-version: ${{ matrix.java }} # step 3 + - name: "Print maven version" + run: ./mvnw -version + # step 4 - name: "Test with Maven" # https://docs.github.com/cn/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#github-context run: | @@ -58,7 +61,7 @@ jobs: matrix: java: [ 17 ] springboot: [ - 3.0.2 -Dspring-framework.version=6.0.4 -Dspring-boot-for-server.version=2.5.14 -Dspring-framework-for-server.version=5.3.20 -Dkotlin-maven-plugin.version=1.7.22 + 3.0.4 -Dspring-framework.version=6.0.6 -Dspring-boot-for-server.version=2.5.14 -Dspring-framework-for-server.version=5.3.20 -Dkotlin-maven-plugin.version=1.7.22 ] steps: # step 1 @@ -71,18 +74,21 @@ jobs: distribution: 'zulu' java-version: ${{ matrix.java }} # step 3 + - name: "Print maven version" + run: ./mvnw -version + # step 4 - name: "Test with Maven" run: | ./mvnw -T 4C clean test -Dspring-boot.version=${{ matrix.springboot }} -Dcheckstyle.skip=false -Dlicense.skip=false -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; # job 3 arm64-test: - runs-on: ubuntu-latest - strategy: + runs-on: ubuntu-latest + strategy: fail-fast: false matrix: springboot: [ - 2.7.8 -Dspring-framework.version=5.3.25, + 2.7.9 -Dspring-framework.version=5.3.25, 2.6.14 -Dspring-framework.version=5.3.24, 2.5.14 -Dspring-framework.version=5.3.20, 2.4.13 -Dspring-framework.version=5.3.13, @@ -97,17 +103,25 @@ jobs: #1.1.12.RELEASE, #1.0.2.RELEASE ] - steps: - - uses: actions/checkout@v2 - - name: Set up QEMU + steps: + # step 1 + - name: "Checkout" + uses: actions/checkout@v2 + # step 2 + - name: "Set up QEMU" id: qemu uses: docker/setup-qemu-action@v1 - - name: install + # step 3 + - name: "install" run: | - docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ - arm64v8/ubuntu:20.04 \ - bash -exc 'apt-get update -y && \ - apt-get install maven -y' - - name: test-arm64 + docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ + arm64v8/ubuntu:20.04 \ + bash -exc 'apt-get update -y && \ + apt-get install maven -y' + # step 4 + - name: "Print maven version" + run: ./mvnw -version + # step 5 + - name: "test-arm64" run: | - ./mvnw -T 4C clean test -Dspring-boot.version=${{ matrix.springboot }} -Dcheckstyle.skip=true -Dlicense.skip=true -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn + ./mvnw -T 4C clean test -Dspring-boot.version=${{ matrix.springboot }} -Dcheckstyle.skip=true -Dlicense.skip=true -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn diff --git a/build/pom.xml b/build/pom.xml index e6dab8b81b3..97202e90359 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -82,7 +82,7 @@ - 1.1.2 + 1.1.5 3.1.0 3.8.1 diff --git a/pom.xml b/pom.xml index 49fcea98100..c60930ccad5 100644 --- a/pom.xml +++ b/pom.xml @@ -273,6 +273,11 @@ org.apache.maven.plugins maven-source-plugin ${maven-source-plugin.version} + + + **/*.java.template + + package From cdbc4c022657d607b09993e4e72488a5203ba225 Mon Sep 17 00:00:00 2001 From: PeppaO <39424591+PeppaO@users.noreply.github.com> Date: Fri, 17 Mar 2023 10:46:19 +0800 Subject: [PATCH 43/76] bugfix: oracle xa mode cannnot be used By same database (#5447) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../rm/datasource/util/SeataXAResource.java | 28 +++++++++++++++++++ .../rm/datasource/xa/ConnectionProxyXA.java | 12 ++++++-- 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 0866bbdacab..3b68ecc88ac 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -26,6 +26,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5332](https://github.com/seata/seata/pull/5332)] fix bugs found in unit tests - [[#5413](https://github.com/seata/seata/pull/5413)] fix bad service configuration file and compilation failure - [[#5415](https://github.com/seata/seata/pull/5415)] fix transaction timeout on client side not execute hook and failureHandler +- [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 5c5a87ca520..8eb2e0c5359 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -26,6 +26,7 @@ - [[#5332](https://github.com/seata/seata/pull/5332)] 修复单元测试中发现的bug - [[#5413](https://github.com/seata/seata/pull/5413)] 修复 arm64平台下的JDK和Spring兼容问题 - [[#5415](https://github.com/seata/seata/pull/5415)] 修复客户侧事务提交前超时未执行hook和failureHandler的问题 +- [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database ### optimize: diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java b/rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java new file mode 100644 index 00000000000..924fec80795 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2019 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.rm.datasource.util; + +import javax.transaction.xa.XAResource; + +/** + * @author PeppaO + * @since 2023/3/16 + */ +public interface SeataXAResource extends XAResource { + // OracleXAResource Loosely Coupled Branches + public static final int ORATRANSLOOSE = 65536; + +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java index 882a71067f2..c3162d64908 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java @@ -21,6 +21,8 @@ import javax.sql.XAConnection; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; + +import com.alibaba.druid.util.JdbcConstants; import io.seata.common.DefaultValues; import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationFactory; @@ -30,6 +32,7 @@ import io.seata.core.model.BranchType; import io.seata.rm.BaseDataSourceResource; import io.seata.rm.DefaultResourceManager; +import io.seata.rm.datasource.util.SeataXAResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,7 +65,7 @@ public class ConnectionProxyXA extends AbstractConnectionProxyXA implements Hold private volatile Long prepareTime = null; private volatile Integer timeout = null; - + private boolean shouldBeHeld = false; /** @@ -265,7 +268,12 @@ public void rollback() throws SQLException { private synchronized void start() throws XAException, SQLException { // 3. XA Start - xaResource.start(this.xaBranchXid, XAResource.TMNOFLAGS); + if (JdbcConstants.ORACLE.equals(resource.getDbType())) { + xaResource.start(this.xaBranchXid, SeataXAResource.ORATRANSLOOSE); + } else { + xaResource.start(this.xaBranchXid, XAResource.TMNOFLAGS); + } + try { termination(); } catch (SQLException e) { From 09bfc42a5543244d4bd7aa9d49211c161cec7f99 Mon Sep 17 00:00:00 2001 From: TuWenlin <96557610+tuwenlin@users.noreply.github.com> Date: Wed, 22 Mar 2023 23:37:03 +0800 Subject: [PATCH 44/76] bugfix: global session is always begin in saga mode (#5145) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../java/io/seata/server/session/SessionHelper.java | 12 ++++++++++-- .../io/seata/server/transaction/saga/SagaCore.java | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 3b68ecc88ac..e7be5571f37 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -24,6 +24,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5316](https://github.com/seata/seata/pull/5316)] fix G1 jvm parameter in jdk8 - [[#5321](https://github.com/seata/seata/pull/5321)] fix When the rollback logic on the TC side returns RollbackFailed, the custom FailureHandler is not executed - [[#5332](https://github.com/seata/seata/pull/5332)] fix bugs found in unit tests +- [[#5145](https://github.com/seata/seata/pull/5145)] fix global session is always begin in saga mode - [[#5413](https://github.com/seata/seata/pull/5413)] fix bad service configuration file and compilation failure - [[#5415](https://github.com/seata/seata/pull/5415)] fix transaction timeout on client side not execute hook and failureHandler - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 8eb2e0c5359..8ffb52ca45b 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -24,6 +24,7 @@ - [[#5316](https://github.com/seata/seata/pull/5316)] 修复jdk8 中 G1 参数 - [[#5321](https://github.com/seata/seata/pull/5321)] 修复当TC端回滚返回RollbackFailed时,自定义FailureHandler的方法未执行 - [[#5332](https://github.com/seata/seata/pull/5332)] 修复单元测试中发现的bug +- [[#5145](https://github.com/seata/seata/pull/5145)] 修复saga模式全局事务状态始终为Begin的问题 - [[#5413](https://github.com/seata/seata/pull/5413)] 修复 arm64平台下的JDK和Spring兼容问题 - [[#5415](https://github.com/seata/seata/pull/5415)] 修复客户侧事务提交前超时未执行hook和failureHandler的问题 - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database diff --git a/server/src/main/java/io/seata/server/session/SessionHelper.java b/server/src/main/java/io/seata/server/session/SessionHelper.java index e766893c732..efa92418e33 100644 --- a/server/src/main/java/io/seata/server/session/SessionHelper.java +++ b/server/src/main/java/io/seata/server/session/SessionHelper.java @@ -134,6 +134,10 @@ public static void endCommitted(GlobalSession globalSession, boolean retryGlobal MetricsPublisher.postSessionDoneEvent(globalSession, IdConstants.STATUS_VALUE_AFTER_COMMITTED_KEY, true, beginTime, retryBranch); } else { + if (globalSession.isSaga()) { + globalSession.setStatus(GlobalStatus.Committed); + globalSession.end(); + } MetricsPublisher.postSessionDoneEvent(globalSession, false, false); } } @@ -152,8 +156,8 @@ public static void endCommitFailed(GlobalSession globalSession, boolean retryGlo /** * End commit failed. * - * @param globalSession the global session - * @param retryGlobal the retry global + * @param globalSession the global session + * @param retryGlobal the retry global * @param isRetryTimeout is retry timeout * @throws TransactionException the transaction exception */ @@ -201,6 +205,10 @@ public static void endRollbacked(GlobalSession globalSession, boolean retryGloba MetricsPublisher.postSessionDoneEvent(globalSession, IdConstants.STATUS_VALUE_AFTER_ROLLBACKED_KEY, true, beginTime, retryBranch); } else { + if (globalSession.isSaga()) { + globalSession.setStatus(GlobalStatus.Rollbacked); + globalSession.end(); + } MetricsPublisher.postSessionDoneEvent(globalSession, GlobalStatus.Rollbacked, false, false); } } diff --git a/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java b/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java index d9285d17f75..b7b0a759b7d 100644 --- a/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java +++ b/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java @@ -194,7 +194,7 @@ public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) t public void doGlobalReport(GlobalSession globalSession, String xid, GlobalStatus globalStatus) throws TransactionException { if (GlobalStatus.Committed.equals(globalStatus)) { SessionHelper.removeAllBranch(globalSession, false); - SessionHelper.endCommitted(globalSession,false); + SessionHelper.endCommitted(globalSession, false); LOGGER.info("Global[{}] committed", globalSession.getXid()); } else if (GlobalStatus.Rollbacked.equals(globalStatus) || GlobalStatus.Finished.equals(globalStatus)) { From 61621980fee5f3886752032fb0ca6a2f296e9998 Mon Sep 17 00:00:00 2001 From: pengten <30648785+pengten@users.noreply.github.com> Date: Wed, 29 Mar 2023 12:02:59 +0800 Subject: [PATCH 45/76] bugfix: fix using @GlobalTransactional in provider ShouldNverHappenException thrown (#5472) --- changes/en-us/develop.md | 2 +- changes/zh-cn/develop.md | 1 + .../GlobalTransactionalInterceptor.java | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index e7be5571f37..97b136f8c99 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -28,7 +28,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5413](https://github.com/seata/seata/pull/5413)] fix bad service configuration file and compilation failure - [[#5415](https://github.com/seata/seata/pull/5415)] fix transaction timeout on client side not execute hook and failureHandler - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database - +- [[#5472](https://github.com/seata/seata/pull/5472)] fix if using `@GlobalTransactional` in RM, `ShouldNeverHappenException` will be thrown ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 8ffb52ca45b..96b0746fd20 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -28,6 +28,7 @@ - [[#5413](https://github.com/seata/seata/pull/5413)] 修复 arm64平台下的JDK和Spring兼容问题 - [[#5415](https://github.com/seata/seata/pull/5415)] 修复客户侧事务提交前超时未执行hook和failureHandler的问题 - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database +- [[#5472](https://github.com/seata/seata/pull/5472)] 在RM中使用`@GlobalTransactional`时,如果RM执行失败会抛出`ShouldNeverHappenException` ### optimize: diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java index 9aa45a969c9..088e7462866 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java @@ -43,6 +43,7 @@ import io.seata.tm.TransactionManagerHolder; import io.seata.tm.api.DefaultFailureHandlerImpl; import io.seata.tm.api.FailureHandler; +import io.seata.tm.api.GlobalTransaction; import io.seata.tm.api.TransactionalExecutor; import io.seata.tm.api.TransactionalTemplate; import io.seata.tm.api.transaction.NoRollbackRule; @@ -64,6 +65,7 @@ import static io.seata.common.DefaultValues.DEFAULT_TM_DEGRADE_CHECK_ALLOW_TIMES; import static io.seata.common.DefaultValues.DEFAULT_TM_DEGRADE_CHECK_PERIOD; import static io.seata.common.DefaultValues.TM_INTERCEPTOR_ORDER; +import static io.seata.tm.api.GlobalTransactionRole.Participant; /** * The type Global transactional interceptor. @@ -247,6 +249,12 @@ public TransactionInfo getTransactionInfo() { } }); } catch (TransactionalExecutor.ExecutionException e) { + GlobalTransaction globalTransaction = e.getTransaction(); + + // If Participant, just throw the exception to original. + if (globalTransaction.getGlobalTransactionRole() == Participant) { + throw e.getOriginalException(); + } TransactionalExecutor.Code code = e.getCode(); Throwable cause = e.getCause(); boolean timeout = isTimeoutException(cause); @@ -259,17 +267,17 @@ public TransactionInfo getTransactionInfo() { } case BeginFailure: succeed = false; - failureHandler.onBeginFailure(e.getTransaction(), cause); + failureHandler.onBeginFailure(globalTransaction, cause); throw cause; case CommitFailure: succeed = false; - failureHandler.onCommitFailure(e.getTransaction(), cause); + failureHandler.onCommitFailure(globalTransaction, cause); throw cause; case RollbackFailure: - failureHandler.onRollbackFailure(e.getTransaction(), e.getOriginalException()); + failureHandler.onRollbackFailure(globalTransaction, e.getOriginalException()); throw e.getOriginalException(); case Rollbacking: - failureHandler.onRollbacking(e.getTransaction(), e.getOriginalException()); + failureHandler.onRollbacking(globalTransaction, e.getOriginalException()); if (timeout) { throw cause; } else { From ff4529a63df01b19c8742cf5ef12a8f759fe7fd8 Mon Sep 17 00:00:00 2001 From: FUNKYE <364176773@qq.com> Date: Wed, 26 Apr 2023 10:13:46 +0800 Subject: [PATCH 46/76] bugfix: fix log file path was loaded incorrectly (#5535) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 2 +- dependencies/pom.xml | 6 ++++ distribution/bin/seata-server.bat | 2 +- distribution/bin/seata-server.sh | 2 +- server/pom.xml | 4 +++ server/src/main/resources/logback-spring.xml | 33 +++++++++++++++----- 7 files changed, 39 insertions(+), 11 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 97b136f8c99..7dbb699105c 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -29,6 +29,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5415](https://github.com/seata/seata/pull/5415)] fix transaction timeout on client side not execute hook and failureHandler - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database - [[#5472](https://github.com/seata/seata/pull/5472)] fix if using `@GlobalTransactional` in RM, `ShouldNeverHappenException` will be thrown +- [[#5535](https://github.com/seata/seata/pull/5535)] fix the log file path was loaded incorrectly ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 96b0746fd20..e1a37d6efc2 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -29,7 +29,7 @@ - [[#5415](https://github.com/seata/seata/pull/5415)] 修复客户侧事务提交前超时未执行hook和failureHandler的问题 - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database - [[#5472](https://github.com/seata/seata/pull/5472)] 在RM中使用`@GlobalTransactional`时,如果RM执行失败会抛出`ShouldNeverHappenException` - +- [[#5535](https://github.com/seata/seata/pull/5535)] 修复读取logback文件路径错误的问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 3137c5818c6..aa9adeba88f 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -113,6 +113,7 @@ 2.23.4 3.12.2 9.4.38.v20210224 + 3.1.7 @@ -681,6 +682,11 @@ jetty-servlet ${jetty-version} + + org.codehaus.janino + janino + ${janino-version} + diff --git a/distribution/bin/seata-server.bat b/distribution/bin/seata-server.bat index d94527ab236..06b818b5a44 100644 --- a/distribution/bin/seata-server.bat +++ b/distribution/bin/seata-server.bat @@ -93,7 +93,7 @@ if "%SKYWALKING_ENABLE%"=="true" ( echo "apm-skywalking not enabled" ) -%JAVACMD% %JAVA_OPTS% %SKYWALKING_OPTS% -server -Dloader.path="%BASEDIR%"/lib -Xmx2048m -Xms2048m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="%BASEDIR%"/logs/java_heapdump.hprof -XX:+DisableExplicitGC -Xloggc:"%BASEDIR%"/logs/seata_gc.log -verbose:gc -Dio.netty.leakDetectionLevel=advanced -classpath %CLASSPATH% -Dapp.name="seata-server" -Dapp.repo="%REPO%" -Dapp.home="%BASEDIR%" -Dbasedir="%BASEDIR%" -Dspring.config.location="%BASEDIR%"/conf/application.yml -Dlogging.config="%BASEDIR%"/conf/logback-spring.xml -jar "%BASEDIR%"/target/seata-server.jar %CMD_LINE_ARGS% +%JAVACMD% %JAVA_OPTS% %SKYWALKING_OPTS% -server -Dloader.path="%BASEDIR%"/lib -Xmx2048m -Xms2048m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="%BASEDIR%"/logs/java_heapdump.hprof -XX:+DisableExplicitGC -Xloggc:"%BASEDIR%"/logs/seata_gc.log -verbose:gc -Dio.netty.leakDetectionLevel=advanced -classpath %CLASSPATH% -Dapp.name="seata-server" -Dapp.repo="%REPO%" -Dapp.home="%BASEDIR%" -Dbasedir="%BASEDIR%" -Dspring.config.additional-location="%BASEDIR%"/conf/ -Dspring.config.location="%BASEDIR%"/conf/application.yml -Dlogging.config="%BASEDIR%"/conf/logback-spring.xml -jar "%BASEDIR%"/target/seata-server.jar %CMD_LINE_ARGS% if %ERRORLEVEL% NEQ 0 goto error goto end diff --git a/distribution/bin/seata-server.sh b/distribution/bin/seata-server.sh index 512851e5372..7509c715ebc 100644 --- a/distribution/bin/seata-server.sh +++ b/distribution/bin/seata-server.sh @@ -143,7 +143,7 @@ fi JAVA_OPT="${JAVA_OPT} -Dio.netty.leakDetectionLevel=advanced" JAVA_OPT="${JAVA_OPT} -Dapp.name=seata-server -Dapp.pid=${$} -Dapp.home=${BASEDIR} -Dbasedir=${BASEDIR}" -JAVA_OPT="${JAVA_OPT} -Dspring.config.location=${BASEDIR}/conf/application.yml -Dlogging.config=${BASEDIR}/conf/logback-spring.xml" +JAVA_OPT="${JAVA_OPT} -Dspring.config.additional-location=${BASEDIR}/conf/ -Dspring.config.location=${BASEDIR}/conf/application.yml -Dlogging.config=${BASEDIR}/conf/logback-spring.xml" JAVA_OPT="${JAVA_OPT} -jar ${BASEDIR}/target/seata-server.jar" diff --git a/server/pom.xml b/server/pom.xml index aa227193dc9..b0eac164b3d 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -223,6 +223,10 @@ com.github.danielwegener logback-kafka-appender + + org.codehaus.janino + janino + diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml index 7d7c2cf21ad..fe55a6f6c05 100644 --- a/server/src/main/resources/logback-spring.xml +++ b/server/src/main/resources/logback-spring.xml @@ -28,20 +28,37 @@ + + + + + - - + + - - + + - - + + + + + + - - + + + + + + + + + + From 7eb98103e16385f11098eb88b6135fdcd472938d Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 26 Apr 2023 11:55:12 +0800 Subject: [PATCH 47/76] optimize: optimize transaction log on client side (#5537) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../rm/datasource/DataSourceManager.java | 3 +++ .../io/seata/rm/AbstractResourceManager.java | 23 ++++++++++++------- .../engine/mock/MockGlobalTransaction.java | 7 +++++- .../tm/api/DefaultGlobalTransaction.java | 20 +++++++++++----- .../io/seata/tm/api/GlobalTransaction.java | 10 ++++++++ .../seata/tm/api/TransactionalTemplate.java | 11 +++++++-- 8 files changed, 59 insertions(+), 17 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 7dbb699105c..46996b411f3 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -45,6 +45,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5315](https://github.com/seata/seata/pull/5315)] optimize the log of SPI - [[#5323](https://github.com/seata/seata/pull/5323)] add time info for global transaction timeout log - [[#5414](https://github.com/seata/seata/pull/5414)] optimize transaction fail handler +- [[#5537](https://github.com/seata/seata/pull/5537)] optimize transaction log on client side ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index e1a37d6efc2..e2018d015ee 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -45,6 +45,7 @@ - [[#5315](https://github.com/seata/seata/pull/5315)] 优化SPI加载日志 - [[#5323](https://github.com/seata/seata/pull/5323)] 为全局事务超时日志添加时间信息 - [[#5414](https://github.com/seata/seata/pull/5414)] 优化事务失败处理 handler +- [[#5537](https://github.com/seata/seata/pull/5537)] 优化客户侧事务日志 ### security: diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java index 6e24db3f765..c988248b4b7 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java @@ -120,6 +120,9 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc } try { UndoLogManagerFactory.getUndoLogManager(dataSourceProxy.getDbType()).undo(dataSourceProxy, xid, branchId); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("branch rollback success, xid:{}, branchId:{}", xid, branchId); + } } catch (TransactionException te) { StackTraceLogger.error(LOGGER, te, "branchRollback failed. branchType:[{}], xid:[{}], branchId:[{}], resourceId:[{}], applicationData:[{}]. reason:[{}]", diff --git a/rm/src/main/java/io/seata/rm/AbstractResourceManager.java b/rm/src/main/java/io/seata/rm/AbstractResourceManager.java index 79b360cb5ec..4641137c3c1 100644 --- a/rm/src/main/java/io/seata/rm/AbstractResourceManager.java +++ b/rm/src/main/java/io/seata/rm/AbstractResourceManager.java @@ -15,6 +15,8 @@ */ package io.seata.rm; +import java.util.concurrent.TimeoutException; + import io.seata.common.exception.NotSupportYetException; import io.seata.core.exception.RmTransactionException; import io.seata.core.exception.TransactionException; @@ -32,8 +34,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.TimeoutException; - /** * abstract ResourceManager * @@ -66,13 +66,18 @@ public Long branchRegister(BranchType branchType, String resourceId, String clie BranchRegisterResponse response = (BranchRegisterResponse) RmNettyRemotingClient.getInstance().sendSyncRequest(request); if (response.getResultCode() == ResultCode.Failed) { - throw new RmTransactionException(response.getTransactionExceptionCode(), String.format("Response[ %s ]", response.getMsg())); + throw new RmTransactionException(response.getTransactionExceptionCode(), + String.format("branch register failed, xid: %s, errMsg: %s ", xid, response.getMsg())); + } + if (LOGGER.isInfoEnabled()) { + LOGGER.info("branch register success, xid:{}, branchId:{}, lockKeys:{}", xid, response.getBranchId(), lockKeys); } return response.getBranchId(); } catch (TimeoutException toe) { - throw new RmTransactionException(TransactionExceptionCode.IO, "RPC Timeout", toe); + throw new RmTransactionException(TransactionExceptionCode.IO, "branch register timeout, xid:" + xid, toe); } catch (RuntimeException rex) { - throw new RmTransactionException(TransactionExceptionCode.BranchRegisterFailed, "Runtime", rex); + throw new RmTransactionException(TransactionExceptionCode.BranchRegisterFailed, + "branch register exception, xid:" + xid, rex); } } @@ -97,12 +102,14 @@ public void branchReport(BranchType branchType, String xid, long branchId, Branc BranchReportResponse response = (BranchReportResponse) RmNettyRemotingClient.getInstance().sendSyncRequest(request); if (response.getResultCode() == ResultCode.Failed) { - throw new RmTransactionException(response.getTransactionExceptionCode(), String.format("Response[ %s ]", response.getMsg())); + throw new RmTransactionException(response.getTransactionExceptionCode(), + String.format("branch report failed, xid: %s, errMsg: %s ", xid, response.getMsg())); } } catch (TimeoutException toe) { - throw new RmTransactionException(TransactionExceptionCode.IO, "RPC Timeout", toe); + throw new RmTransactionException(TransactionExceptionCode.IO, "branch report timeout, xid:" + xid, toe); } catch (RuntimeException rex) { - throw new RmTransactionException(TransactionExceptionCode.BranchReportFailed, "Runtime", rex); + throw new RmTransactionException(TransactionExceptionCode.BranchReportFailed, + "branch report exception, xid:" + xid, rex); } } diff --git a/test/src/test/java/io/seata/saga/engine/mock/MockGlobalTransaction.java b/test/src/test/java/io/seata/saga/engine/mock/MockGlobalTransaction.java index 9a69c1e2635..9f79d2a4ad1 100644 --- a/test/src/test/java/io/seata/saga/engine/mock/MockGlobalTransaction.java +++ b/test/src/test/java/io/seata/saga/engine/mock/MockGlobalTransaction.java @@ -75,7 +75,12 @@ public void rollback() throws TransactionException { } @Override - public SuspendedResourcesHolder suspend() + public SuspendedResourcesHolder suspend() throws TransactionException { + return null; + } + + @Override + public SuspendedResourcesHolder suspend(boolean clean) throws TransactionException { return null; } diff --git a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java index ba923078e49..79fb26eb289 100644 --- a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java +++ b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java @@ -23,7 +23,6 @@ import io.seata.core.model.TransactionManager; import io.seata.tm.TransactionManagerHolder; import io.seata.tm.api.transaction.SuspendedResourcesHolder; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -146,7 +145,7 @@ public void commit() throws TransactionException { } } finally { if (xid.equals(RootContext.getXID())) { - suspend(); + suspend(true); } } if (LOGGER.isInfoEnabled()) { @@ -182,7 +181,7 @@ public void rollback() throws TransactionException { } } finally { if (xid.equals(RootContext.getXID())) { - suspend(); + suspend(true); } } if (LOGGER.isInfoEnabled()) { @@ -192,14 +191,23 @@ public void rollback() throws TransactionException { @Override public SuspendedResourcesHolder suspend() throws TransactionException { + return suspend(false); + } + + @Override + public SuspendedResourcesHolder suspend(boolean clean) throws TransactionException { // In order to associate the following logs with XID, first get and then unbind. String xid = RootContext.getXID(); if (xid != null) { if (LOGGER.isInfoEnabled()) { - LOGGER.info("Suspending current transaction, xid = {}", xid); + if (clean) { + LOGGER.info("transaction end, xid = {}", xid); + } else { + LOGGER.info("suspending current transaction, xid = {}", xid); + } } RootContext.unbind(); - return new SuspendedResourcesHolder(xid); + return clean ? null : new SuspendedResourcesHolder(xid); } else { return null; } @@ -245,7 +253,7 @@ public void globalReport(GlobalStatus globalStatus) throws TransactionException } if (xid.equals(RootContext.getXID())) { - suspend(); + suspend(true); } } diff --git a/tm/src/main/java/io/seata/tm/api/GlobalTransaction.java b/tm/src/main/java/io/seata/tm/api/GlobalTransaction.java index 37771c1a406..eafd27ab798 100644 --- a/tm/src/main/java/io/seata/tm/api/GlobalTransaction.java +++ b/tm/src/main/java/io/seata/tm/api/GlobalTransaction.java @@ -78,6 +78,16 @@ public interface GlobalTransaction { */ SuspendedResourcesHolder suspend() throws TransactionException; + /** + * Suspend the global transaction. + * + * @param clean the clean if true, clean the transaction context. otherwise,supend only + * @return the SuspendedResourcesHolder which holds the suspend resources + * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown + * @see SuspendedResourcesHolder + */ + SuspendedResourcesHolder suspend(boolean clean) throws TransactionException; + /** * Resume the global transaction. * diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java index 9479bcf100f..303b1dd428c 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java @@ -65,14 +65,14 @@ public Object execute(TransactionalExecutor business) throws Throwable { case NOT_SUPPORTED: // If transaction is existing, suspend it. if (existingTransaction(tx)) { - suspendedResourcesHolder = tx.suspend(); + suspendedResourcesHolder = tx.suspend(false); } // Execute without transaction and return. return business.execute(); case REQUIRES_NEW: // If transaction is existing, suspend it, and then begin new transaction. if (existingTransaction(tx)) { - suspendedResourcesHolder = tx.suspend(); + suspendedResourcesHolder = tx.suspend(false); tx = GlobalTransactionContext.createNew(); } // Continue and execute with new transaction @@ -210,6 +210,9 @@ private void commitTransaction(GlobalTransaction tx, TransactionInfo txInfo) try { triggerBeforeCommit(); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("transaction {} will be commit", tx.getXid()); + } tx.commit(); TransactionalExecutor.Code code = TransactionalExecutor.Code.Unknown; switch (tx.getLocalStatus()) { @@ -237,6 +240,10 @@ private void rollbackTransaction(GlobalTransaction tx, Throwable originalExcepti try { triggerBeforeRollback(); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("transaction {} will be rollback, cause by:{}", tx.getXid(), + originalException.getMessage()); + } tx.rollback(); triggerAfterRollback(); } catch (TransactionException txe) { From a55605445315cf211736c09777f70e45166362fd Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 26 Apr 2023 12:03:05 +0800 Subject: [PATCH 48/76] bugfix: fix finished transaction swallows exception when committing (#5538) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../exception/TransactionExceptionCode.java | 13 +++++- .../io/seata/core/model/GlobalStatus.java | 40 +++++++++++++++++++ .../seata/server/session/GlobalSession.java | 10 +---- .../seata/tm/api/TransactionalTemplate.java | 20 ++++++++-- 6 files changed, 70 insertions(+), 15 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 46996b411f3..f6df66d7c98 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -30,6 +30,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database - [[#5472](https://github.com/seata/seata/pull/5472)] fix if using `@GlobalTransactional` in RM, `ShouldNeverHappenException` will be thrown - [[#5535](https://github.com/seata/seata/pull/5535)] fix the log file path was loaded incorrectly +- [[#5538](https://github.com/seata/seata/pull/5538)] fix finished transaction swallows exception when committing ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index e2018d015ee..c573b95acfc 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -30,6 +30,7 @@ - [[#5447](https://github.com/seata/seata/pull/5447)] fix oracle xa mode cannnot be used By same database - [[#5472](https://github.com/seata/seata/pull/5472)] 在RM中使用`@GlobalTransactional`时,如果RM执行失败会抛出`ShouldNeverHappenException` - [[#5535](https://github.com/seata/seata/pull/5535)] 修复读取logback文件路径错误的问题 +- [[#5538](https://github.com/seata/seata/pull/5538)] 修复提交事务时事务已完成不抛出异常问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java b/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java index 835d31532cd..9e8d79051b4 100644 --- a/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java +++ b/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java @@ -125,8 +125,17 @@ public enum TransactionExceptionCode { /** * transaction already timeout */ - TransactionTimeout - ; + TransactionTimeout, + + /** + * Commit heuristic transaction exception code. + */ + CommitHeuristic, + + /** + * Broken transaction exception code. + */ + Broken; /** diff --git a/core/src/main/java/io/seata/core/model/GlobalStatus.java b/core/src/main/java/io/seata/core/model/GlobalStatus.java index 5e6e6fa5f8f..5d12aee2341 100644 --- a/core/src/main/java/io/seata/core/model/GlobalStatus.java +++ b/core/src/main/java/io/seata/core/model/GlobalStatus.java @@ -172,4 +172,44 @@ public static GlobalStatus get(int code) { } return value; } + + /** + * Is one phase timeout boolean. + * + * @param status the status + * @return the boolean + */ + public static boolean isOnePhaseTimeout(GlobalStatus status) { + if (status == TimeoutRollbacking || status == TimeoutRollbackRetrying || status == TimeoutRollbacked || status == TimeoutRollbackFailed) { + return true; + } + return false; + } + + /** + * Is two phase success boolean. + * + * @param status the status + * @return the boolean + */ + public static boolean isTwoPhaseSuccess(GlobalStatus status) { + if (status == GlobalStatus.Committed || status == GlobalStatus.Rollbacked + || status == GlobalStatus.TimeoutRollbacked) { + return true; + } + return false; + } + + /** + * Is two phase heuristic boolean. + * + * @param status the status + * @return the boolean + */ + public static boolean isTwoPhaseHeuristic(GlobalStatus status) { + if (status == GlobalStatus.Finished) { + return true; + } + return false; + } } diff --git a/server/src/main/java/io/seata/server/session/GlobalSession.java b/server/src/main/java/io/seata/server/session/GlobalSession.java index 1f4c4c61821..5ea1a9fa1db 100644 --- a/server/src/main/java/io/seata/server/session/GlobalSession.java +++ b/server/src/main/java/io/seata/server/session/GlobalSession.java @@ -233,7 +233,7 @@ public void close() throws TransactionException { @Override public void end() throws TransactionException { - if (isSuccessEnd()) { + if (GlobalStatus.isTwoPhaseSuccess(status)) { // Clean locks first clean(); for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { @@ -246,14 +246,6 @@ public void end() throws TransactionException { } } - public boolean isSuccessEnd() { - if (status == GlobalStatus.Committed || status == GlobalStatus.Rollbacked - || status == GlobalStatus.TimeoutRollbacked) { - return true; - } - return false; - } - public void clean() throws TransactionException { if (!LockerManagerFactory.getLockManager().releaseGlobalSessionLock(this)) { throw new TransactionException("UnLock globalSession error, xid = " + this.xid); diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java index 303b1dd428c..83932934759 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java @@ -23,6 +23,7 @@ import io.seata.core.exception.TransactionException; import io.seata.core.exception.TransactionExceptionCode; import io.seata.core.model.GlobalLockConfig; +import io.seata.core.model.GlobalStatus; import io.seata.tm.api.transaction.Propagation; import io.seata.tm.api.transaction.SuspendedResourcesHolder; import io.seata.tm.api.transaction.TransactionHook; @@ -214,19 +215,30 @@ private void commitTransaction(GlobalTransaction tx, TransactionInfo txInfo) LOGGER.info("transaction {} will be commit", tx.getXid()); } tx.commit(); + GlobalStatus afterCommitStatus = tx.getLocalStatus(); TransactionalExecutor.Code code = TransactionalExecutor.Code.Unknown; - switch (tx.getLocalStatus()) { + switch (afterCommitStatus) { case TimeoutRollbacking: code = TransactionalExecutor.Code.Rollbacking; break; case TimeoutRollbacked: code = TransactionalExecutor.Code.RollbackDone; break; + case Finished: + code = TransactionalExecutor.Code.CommitFailure; + break; default: } - if (code != TransactionalExecutor.Code.Unknown) { - Exception exx = new TmTransactionException(TransactionExceptionCode.TransactionTimeout, String.format("Global transaction[%s] is timeout and will be rollback[TC].", tx.getXid())); - throw new TransactionalExecutor.ExecutionException(tx, exx, code); + Exception statusException = null; + if (GlobalStatus.isTwoPhaseHeuristic(afterCommitStatus)) { + statusException = new TmTransactionException(TransactionExceptionCode.CommitHeuristic, + String.format("Global transaction[%s] not found, may be rollbacked.", tx.getXid())); + } else if (GlobalStatus.isOnePhaseTimeout(afterCommitStatus)) { + statusException = new TmTransactionException(TransactionExceptionCode.TransactionTimeout, + String.format("Global transaction[%s] is timeout and will be rollback[TC].", tx.getXid())); + } + if (null != statusException) { + throw new TransactionalExecutor.ExecutionException(tx, statusException, code); } triggerAfterCommit(); } catch (TransactionException txe) { From a6f73703f509f8b8caf0422c21789688e3ed052b Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 26 Apr 2023 12:14:40 +0800 Subject: [PATCH 49/76] bugfix: fix the full table scan issue with 'setDate' condition in Oracle 10g (#5539) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../java/io/seata/common/util/DateUtil.java | 82 +++++++++++++++++++ .../io/seata/common/util/DateUtilTest.java | 57 +++++++++++++ .../main/java/io/seata/rm/RMHandlerAT.java | 17 ++-- .../undo/oracle/OracleUndoLogManager.java | 8 +- script/client/at/db/mysql.sql | 5 +- script/client/at/db/oracle.sql | 14 ++-- script/client/at/db/postgresql.sql | 12 ++- 9 files changed, 174 insertions(+), 23 deletions(-) create mode 100644 common/src/main/java/io/seata/common/util/DateUtil.java create mode 100644 common/src/test/java/io/seata/common/util/DateUtilTest.java diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index f6df66d7c98..fd58ce2f67e 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -31,6 +31,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5472](https://github.com/seata/seata/pull/5472)] fix if using `@GlobalTransactional` in RM, `ShouldNeverHappenException` will be thrown - [[#5535](https://github.com/seata/seata/pull/5535)] fix the log file path was loaded incorrectly - [[#5538](https://github.com/seata/seata/pull/5538)] fix finished transaction swallows exception when committing +- [[#5539](https://github.com/seata/seata/pull/5539)] fix the full table scan issue with 'setDate' condition in Oracle 10g ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index c573b95acfc..6f9cc66b13b 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -31,6 +31,7 @@ - [[#5472](https://github.com/seata/seata/pull/5472)] 在RM中使用`@GlobalTransactional`时,如果RM执行失败会抛出`ShouldNeverHappenException` - [[#5535](https://github.com/seata/seata/pull/5535)] 修复读取logback文件路径错误的问题 - [[#5538](https://github.com/seata/seata/pull/5538)] 修复提交事务时事务已完成不抛出异常问题 +- [[#5539](https://github.com/seata/seata/pull/5539)] 修复Oracle 10g where条件包含setDate全表扫描问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/common/src/main/java/io/seata/common/util/DateUtil.java b/common/src/main/java/io/seata/common/util/DateUtil.java new file mode 100644 index 00000000000..32bf8c86d04 --- /dev/null +++ b/common/src/main/java/io/seata/common/util/DateUtil.java @@ -0,0 +1,82 @@ +/* + * Copyright 1999-2019 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.common.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** + * The type Date util. + * + * @author slievrly + */ +public class DateUtil { + + /** + * Gets current date. + * + * @return the current date + */ + public static Date getCurrentDate() { + return new Date(); + } + + /** + * Parse date date. + * + * @param dateStr the date str + * @param format the format + * @return the date + * @throws ParseException the parse exception + */ + public static Date parseDate(String dateStr, String format) throws ParseException { + if (StringUtils.isBlank(dateStr)) { + return null; + } + SimpleDateFormat sdf = new SimpleDateFormat(format); + return sdf.parse(dateStr); + } + + public static Date parseDateWithoutTime(String dateStr) throws ParseException { + return parseDate(dateStr, "yyyy-MM-dd"); + } + + public static Date getDateNowPlusDays(int days) throws ParseException { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, days); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String dateStr = dateFormat.format(calendar.getTime()); + return dateFormat.parse(dateStr); + } + + /** + * Format date string. + * + * @param date the date + * @param format the format + * @return the string + */ + public static String formatDate(Date date, String format) { + if (date == null) { + return null; + } + SimpleDateFormat sdf = new SimpleDateFormat(format); + return sdf.format(date); + } +} diff --git a/common/src/test/java/io/seata/common/util/DateUtilTest.java b/common/src/test/java/io/seata/common/util/DateUtilTest.java new file mode 100644 index 00000000000..1ce47e57d6e --- /dev/null +++ b/common/src/test/java/io/seata/common/util/DateUtilTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2019 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.common.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * @author slievrly + */ +public class DateUtilTest { + @Test + public void testGetCurrentDate() { + Date currentDate = DateUtil.getCurrentDate(); + Assertions.assertNotNull(currentDate); + } + + @Test + public void testParseDate() throws ParseException { + String dateStr = "2021-01-01"; + Date date = DateUtil.parseDate(dateStr, "yyyy-MM-dd"); + Assertions.assertNotNull(date); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Assertions.assertEquals(dateStr, sdf.format(date)); + } + + @Test + public void testFormatDate() { + Date currentDate = DateUtil.getCurrentDate(); + String dateStr = DateUtil.formatDate(currentDate, "yyyy-MM-dd HH:mm:ss"); + Assertions.assertNotNull(dateStr); + } + + @Test + public void testGetDateNowPlusDays() throws ParseException { + Assertions.assertNotNull(DateUtil.getDateNowPlusDays(2)); + } +} diff --git a/rm-datasource/src/main/java/io/seata/rm/RMHandlerAT.java b/rm-datasource/src/main/java/io/seata/rm/RMHandlerAT.java index da2c9d5dbf3..333a121a295 100644 --- a/rm-datasource/src/main/java/io/seata/rm/RMHandlerAT.java +++ b/rm-datasource/src/main/java/io/seata/rm/RMHandlerAT.java @@ -17,11 +17,12 @@ import java.sql.Connection; import java.sql.SQLException; -import java.util.Calendar; +import java.text.ParseException; import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import io.seata.common.util.DateUtil; import io.seata.core.model.BranchType; import io.seata.core.model.ResourceManager; import io.seata.core.protocol.transaction.UndoLogDeleteRequest; @@ -126,13 +127,15 @@ int deleteUndoLog(UndoLogManager manager, Connection conn, Date division) { } } - private Date getLogCreated(int saveDays) { - if (saveDays <= 0) { - saveDays = UndoLogDeleteRequest.DEFAULT_SAVE_DAYS; + private Date getLogCreated(int pastDays) { + if (pastDays <= 0) { + pastDays = UndoLogDeleteRequest.DEFAULT_SAVE_DAYS; + } + try { + return DateUtil.getDateNowPlusDays(-pastDays); + } catch (ParseException exx) { + throw new RuntimeException(exx); } - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.DATE, -saveDays); - return calendar.getTime(); } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoLogManager.java index 9eedb606a78..2f6159e6575 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoLogManager.java @@ -15,13 +15,13 @@ */ package io.seata.rm.datasource.undo.oracle; - import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Date; import io.seata.common.loader.LoadLevel; +import io.seata.common.util.DateUtil; import io.seata.core.compressor.CompressorType; import io.seata.core.constants.ClientTableColumnsName; import io.seata.rm.datasource.undo.AbstractUndoLogManager; @@ -47,13 +47,13 @@ public class OracleUndoLogManager extends AbstractUndoLogManager { + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + ", " + ClientTableColumnsName.UNDO_LOG_LOG_MODIFIED + ")" + "VALUES (UNDO_LOG_SEQ.nextval, ?, ?, ?, ?, ?, sysdate, sysdate)"; - private static final String DELETE_UNDO_LOG_BY_CREATE_SQL = "DELETE FROM " + UNDO_LOG_TABLE_NAME + - " WHERE " + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + " <= ? and ROWNUM <= ?"; + private static final String DELETE_UNDO_LOG_BY_CREATE_SQL = "DELETE FROM " + UNDO_LOG_TABLE_NAME + " WHERE " + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + " <= to_date(?,'yyyy-mm-dd hh24:mi:ss') and ROWNUM <= ?"; @Override public int deleteUndoLogByLogCreated(Date logCreated, int limitRows, Connection conn) throws SQLException { try (PreparedStatement deletePST = conn.prepareStatement(DELETE_UNDO_LOG_BY_CREATE_SQL)) { - deletePST.setDate(1, new java.sql.Date(logCreated.getTime())); + String dateStr = DateUtil.formatDate(logCreated, "yyyy-MM-dd HH:mm:ss"); + deletePST.setString(1, dateStr); deletePST.setInt(2, limitRows); int deleteRows = deletePST.executeUpdate(); if (LOGGER.isDebugEnabled()) { diff --git a/script/client/at/db/mysql.sql b/script/client/at/db/mysql.sql index cbddc35025c..45b03761c6e 100644 --- a/script/client/at/db/mysql.sql +++ b/script/client/at/db/mysql.sql @@ -9,6 +9,5 @@ CREATE TABLE IF NOT EXISTS `undo_log` `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'; +) 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/script/client/at/db/oracle.sql b/script/client/at/db/oracle.sql index 950e3aeffe7..e1db1e95d44 100644 --- a/script/client/at/db/oracle.sql +++ b/script/client/at/db/oracle.sql @@ -1,7 +1,6 @@ -- for AT mode you must to init this sql for you business database. the seata server not need it. CREATE TABLE undo_log ( - id NUMBER(19) NOT NULL, branch_id NUMBER(19) NOT NULL, xid VARCHAR2(128) NOT NULL, context VARCHAR2(128) NOT NULL, @@ -9,11 +8,14 @@ CREATE TABLE undo_log log_status NUMBER(10) NOT NULL, log_created TIMESTAMP(0) NOT NULL, log_modified TIMESTAMP(0) NOT NULL, - PRIMARY KEY (id), CONSTRAINT ux_undo_log UNIQUE (xid, branch_id) ); - +CREATE INDEX ix_log_created ON undo_log(log_created); COMMENT ON TABLE undo_log IS 'AT transaction mode undo table'; - --- Generate ID using sequence and trigger -CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1; \ No newline at end of file +COMMENT ON COLUMN undo_log.branch_id is 'branch transaction id'; +COMMENT ON COLUMN undo_log.xid is 'global transaction id'; +COMMENT ON COLUMN undo_log.context is 'undo_log context,such as serialization'; +COMMENT ON COLUMN undo_log.rollback_info is 'rollback info'; +COMMENT ON COLUMN undo_log.log_status is '0:normal status,1:defense status'; +COMMENT ON COLUMN undo_log.log_created is 'create datetime'; +COMMENT ON COLUMN undo_log.log_modified is 'modify datetime'; \ No newline at end of file diff --git a/script/client/at/db/postgresql.sql b/script/client/at/db/postgresql.sql index 739e77d04b2..6b9feddd406 100644 --- a/script/client/at/db/postgresql.sql +++ b/script/client/at/db/postgresql.sql @@ -1,7 +1,6 @@ -- for AT mode you must to init this sql for you business database. the seata server not need it. CREATE TABLE IF NOT EXISTS public.undo_log ( - id SERIAL NOT NULL, branch_id BIGINT NOT NULL, xid VARCHAR(128) NOT NULL, context VARCHAR(128) NOT NULL, @@ -9,8 +8,15 @@ CREATE TABLE IF NOT EXISTS public.undo_log log_status INT NOT NULL, log_created TIMESTAMP(0) NOT NULL, log_modified TIMESTAMP(0) NOT NULL, - CONSTRAINT pk_undo_log PRIMARY KEY (id), CONSTRAINT ux_undo_log UNIQUE (xid, branch_id) ); +CREATE INDEX ix_log_created ON undo_log(log_created); -CREATE SEQUENCE IF NOT EXISTS undo_log_id_seq INCREMENT BY 1 MINVALUE 1 ; \ No newline at end of file +COMMENT ON TABLE public.undo_log IS 'AT transaction mode undo table'; +COMMENT ON COLUMN public.undo_log.branch_id IS 'branch transaction id'; +COMMENT ON COLUMN public.undo_log.xid IS 'global transaction id'; +COMMENT ON COLUMN public.undo_log.context IS 'undo_log context,such as serialization'; +COMMENT ON COLUMN public.undo_log.rollback_info IS 'rollback info'; +COMMENT ON COLUMN public.undo_log.log_status IS '0:normal status,1:defense status'; +COMMENT ON COLUMN public.undo_log.log_created IS 'create datetime'; +COMMENT ON COLUMN public.undo_log.log_modified IS 'modify datetime'; \ No newline at end of file From 5a1c70ab8aa156e54cfd6f32467568b7ff1c568b Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 26 Apr 2023 12:37:05 +0800 Subject: [PATCH 50/76] bugfix: fix GlobalStatus=9 can't be cleared in DB storage mode (#5540) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../seata/server/coordinator/DefaultCoordinator.java | 10 ++++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index fd58ce2f67e..4f5a66670bc 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -32,6 +32,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5535](https://github.com/seata/seata/pull/5535)] fix the log file path was loaded incorrectly - [[#5538](https://github.com/seata/seata/pull/5538)] fix finished transaction swallows exception when committing - [[#5539](https://github.com/seata/seata/pull/5539)] fix the full table scan issue with 'setDate' condition in Oracle 10g +- [[#5540](https://github.com/seata/seata/pull/5540)] fix GlobalStatus=9 can't be cleared in DB storage mode ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 6f9cc66b13b..e6d1a633608 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -32,6 +32,7 @@ - [[#5535](https://github.com/seata/seata/pull/5535)] 修复读取logback文件路径错误的问题 - [[#5538](https://github.com/seata/seata/pull/5538)] 修复提交事务时事务已完成不抛出异常问题 - [[#5539](https://github.com/seata/seata/pull/5539)] 修复Oracle 10g where条件包含setDate全表扫描问题 +- [[#5540](https://github.com/seata/seata/pull/5540)] 修复 GlobalStatus=9 在DB存储模式无法清除的问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index 8b4a9fa10ba..5f94bf2a55b 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -168,8 +168,7 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran private final GlobalStatus[] rollbackingStatuses = new GlobalStatus[] {GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying, GlobalStatus.RollbackRetrying, GlobalStatus.Rollbacking}; - private final GlobalStatus[] retryCommittingStatuses = - new GlobalStatus[] {GlobalStatus.Committing, GlobalStatus.CommitRetrying}; + private final GlobalStatus[] retryCommittingStatuses = new GlobalStatus[] {GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Committed}; private final ThreadPoolExecutor branchRemoveExecutor; @@ -414,8 +413,7 @@ protected void handleRetryCommitting() { SessionHelper.forEach(committingSessions, committingSession -> { try { // prevent repeated commit - if (committingSession.getStatus() == GlobalStatus.Committing - && !committingSession.isDeadSession()) { + if (GlobalStatus.Committing.equals(committingSession.getStatus()) && !committingSession.isDeadSession()) { // The function of this 'return' is 'continue'. return; } @@ -427,6 +425,10 @@ protected void handleRetryCommitting() { //The function of this 'return' is 'continue'. return; } + if (GlobalStatus.Committed.equals(committingSession.getStatus()) + && committingSession.getBranchSessions().isEmpty()) { + SessionHelper.endCommitted(committingSession,true); + } committingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); core.doGlobalCommit(committingSession, true); } catch (TransactionException ex) { From 878c1a41ce761bac393d614b539cb24736d8c432 Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 26 Apr 2023 13:09:03 +0800 Subject: [PATCH 51/76] optimize: optimize server log output (#5541) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../protocol/AbstractIdentifyRequest.java | 11 +++++ .../protocol/AbstractIdentifyResponse.java | 27 ++++------- .../core/protocol/AbstractResultMessage.java | 4 +- .../core/protocol/RegisterRMRequest.java | 13 ++++-- .../core/protocol/RegisterTMRequest.java | 7 --- .../transaction/AbstractBranchEndRequest.java | 26 ++++------- .../AbstractBranchEndResponse.java | 26 ++++------- .../transaction/AbstractGlobalEndRequest.java | 16 +++---- .../AbstractGlobalEndResponse.java | 19 +++----- .../transaction/BranchRegisterRequest.java | 23 ++++------ .../transaction/BranchRegisterResponse.java | 17 +++---- .../transaction/BranchReportRequest.java | 26 ++++------- .../transaction/BranchReportResponse.java | 9 ++++ .../transaction/GlobalBeginRequest.java | 13 ++---- .../transaction/GlobalBeginResponse.java | 10 ++++ .../transaction/GlobalLockQueryResponse.java | 9 ++++ .../transaction/GlobalReportRequest.java | 10 ++++ .../transaction/UndoLogDeleteRequest.java | 11 +++-- .../rpc/processor/server/BatchLogHandler.java | 21 ++++++--- .../server/ServerOnRequestProcessor.java | 46 +++++++++++++------ .../server/ServerOnResponseProcessor.java | 27 ++++------- .../core/message/BranchCommitRequestTest.java | 3 +- .../message/BranchCommitResponseTest.java | 2 +- .../message/BranchRegisterRequestTest.java | 2 +- .../message/BranchRegisterResponseTest.java | 2 +- .../core/message/BranchReportRequestTest.java | 4 +- .../core/message/GlobalBeginRequestTest.java | 3 +- .../message/GlobalCommitResponseTest.java | 2 +- .../message/GlobalRollbackRequestTest.java | 2 +- .../core/message/RegisterTMRequestTest.java | 2 +- .../core/message/RegisterTMResponseTest.java | 2 +- .../BranchRollbackRequestTest.java | 3 +- .../BranchRollbackResponseTest.java | 2 +- .../RegisterTMRequestSerializerTest.java | 8 ---- .../resources/logback/console-appender.xml | 2 +- .../main/resources/logback/file-appender.xml | 2 +- 38 files changed, 206 insertions(+), 208 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 4f5a66670bc..4153ab3870b 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -49,6 +49,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5323](https://github.com/seata/seata/pull/5323)] add time info for global transaction timeout log - [[#5414](https://github.com/seata/seata/pull/5414)] optimize transaction fail handler - [[#5537](https://github.com/seata/seata/pull/5537)] optimize transaction log on client side +- [[#5541](https://github.com/seata/seata/pull/5541)] optimize server log output ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index e6d1a633608..77f3ec3995e 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -49,6 +49,7 @@ - [[#5323](https://github.com/seata/seata/pull/5323)] 为全局事务超时日志添加时间信息 - [[#5414](https://github.com/seata/seata/pull/5414)] 优化事务失败处理 handler - [[#5537](https://github.com/seata/seata/pull/5537)] 优化客户侧事务日志 +- [[#5541](https://github.com/seata/seata/pull/5541)] 优化Server日志输出 ### security: diff --git a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java index 46cf4dec6ae..b180489095e 100644 --- a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java +++ b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java @@ -138,4 +138,15 @@ public void setExtraData(String extraData) { this.extraData = extraData; } + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('{'); + sb.append("version='").append(version).append('\''); + sb.append(", applicationId='").append(applicationId).append('\''); + sb.append(", transactionServiceGroup='").append(transactionServiceGroup).append('\''); + sb.append(", extraData='").append(extraData).append('\''); + sb.append('}'); + return sb.toString(); + } } diff --git a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java index 564d8eab3d3..33d4281167f 100644 --- a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java +++ b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java @@ -82,25 +82,16 @@ public void setIdentified(boolean identified) { this.identified = identified; } - @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("version="); - result.append(version); - result.append(","); - result.append("extraData="); - result.append(extraData); - result.append(","); - result.append("identified="); - result.append(identified); - result.append(","); - result.append("resultCode="); - result.append(getResultCode()); - result.append(","); - result.append("msg="); - result.append(getMsg()); - - return result.toString(); + final StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('{'); + sb.append("version='").append(version).append('\''); + sb.append(", extraData='").append(extraData).append('\''); + sb.append(", identified=").append(identified); + sb.append(", resultCode=").append(resultCode); + sb.append(", msg='").append(msg).append('\''); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java b/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java index 9b0922bdc63..64ad3594c53 100644 --- a/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java +++ b/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java @@ -22,9 +22,9 @@ */ public abstract class AbstractResultMessage extends AbstractMessage { - private ResultCode resultCode; + protected ResultCode resultCode; - private String msg; + protected String msg; /** * Gets result code. diff --git a/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java b/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java index 21dfb30d396..27877612c2e 100644 --- a/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java +++ b/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java @@ -68,10 +68,13 @@ public short getTypeCode() { @Override public String toString() { - return "RegisterRMRequest{" + - "resourceIds='" + resourceIds + '\'' + - ", applicationId='" + applicationId + '\'' + - ", transactionServiceGroup='" + transactionServiceGroup + '\'' + - '}'; + final StringBuilder sb = new StringBuilder("RegisterRMRequest{"); + sb.append("resourceIds='").append(resourceIds).append('\''); + sb.append(", version='").append(version).append('\''); + sb.append(", applicationId='").append(applicationId).append('\''); + sb.append(", transactionServiceGroup='").append(transactionServiceGroup).append('\''); + sb.append(", extraData='").append(extraData).append('\''); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/RegisterTMRequest.java b/core/src/main/java/io/seata/core/protocol/RegisterTMRequest.java index d1cad21a096..746891f5189 100644 --- a/core/src/main/java/io/seata/core/protocol/RegisterTMRequest.java +++ b/core/src/main/java/io/seata/core/protocol/RegisterTMRequest.java @@ -87,11 +87,4 @@ public short getTypeCode() { return MessageType.TYPE_REG_CLT; } - @Override - public String toString() { - return "RegisterTMRequest{" + - "applicationId='" + applicationId + '\'' + - ", transactionServiceGroup='" + transactionServiceGroup + '\'' + - '}'; - } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java index 1f077edfbb5..6324473a0ee 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java @@ -141,22 +141,14 @@ public void setApplicationData(String applicationData) { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("xid="); - result.append(xid); - result.append(","); - result.append("branchId="); - result.append(branchId); - result.append(","); - result.append("branchType="); - result.append(branchType); - result.append(","); - result.append("resourceId="); - result.append(resourceId); - result.append(","); - result.append("applicationData="); - result.append(applicationData); - - return result.toString(); + final StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('{'); + sb.append("xid='").append(xid).append('\''); + sb.append(", branchId=").append(branchId); + sb.append(", branchType=").append(branchType); + sb.append(", resourceId='").append(resourceId).append('\''); + sb.append(", applicationData='").append(applicationData).append('\''); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java index 5d3b03743f9..d5e54cd36ed 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java @@ -94,22 +94,14 @@ public void setBranchStatus(BranchStatus branchStatus) { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("xid="); - result.append(xid); - result.append(","); - result.append("branchId="); - result.append(branchId); - result.append(","); - result.append("branchStatus="); - result.append(branchStatus); - result.append(","); - result.append("result code ="); - result.append(getResultCode()); - result.append(","); - result.append("getMsg ="); - result.append(getMsg()); - - return result.toString(); + final StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('{'); + sb.append("xid='").append(xid).append('\''); + sb.append(", branchId=").append(branchId); + sb.append(", branchStatus=").append(branchStatus); + sb.append(", resultCode=").append(resultCode); + sb.append(", msg='").append(msg).append('\''); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndRequest.java index 85a8a09ed25..7c8a98bf608 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndRequest.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndRequest.java @@ -22,7 +22,7 @@ */ public abstract class AbstractGlobalEndRequest extends AbstractTransactionRequestToTC { - private String xid; + protected String xid; /** * The Extra data. @@ -67,13 +67,11 @@ public void setExtraData(String extraData) { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("xid="); - result.append(xid); - result.append(","); - result.append("extraData="); - result.append(extraData); - - return result.toString(); + final StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('{'); + sb.append("xid='").append(xid).append('\''); + sb.append(", extraData='").append(extraData).append('\''); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndResponse.java index cd6ac513faf..1936540b748 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndResponse.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractGlobalEndResponse.java @@ -50,17 +50,12 @@ public void setGlobalStatus(GlobalStatus globalStatus) { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("globalStatus="); - result.append(globalStatus); - result.append(","); - result.append("ResultCode="); - result.append(getResultCode()); - result.append(","); - result.append("Msg="); - result.append(getMsg()); - - return result.toString(); + final StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('{'); + sb.append("globalStatus=").append(globalStatus); + sb.append(", resultCode=").append(resultCode); + sb.append(", msg='").append(msg).append('\''); + sb.append('}'); + return sb.toString(); } - } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java index 4f7155a717e..f6896bf6bd1 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java @@ -138,19 +138,14 @@ public AbstractTransactionResponse handle(RpcContext rpcContext) { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("xid="); - result.append(xid); - result.append(","); - result.append("branchType="); - result.append(branchType); - result.append(","); - result.append("resourceId="); - result.append(resourceId); - result.append(","); - result.append("lockKey="); - result.append(lockKey); - - return result.toString(); + final StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('{'); + sb.append("xid='").append(xid).append('\''); + sb.append(", branchType=").append(branchType); + sb.append(", resourceId='").append(resourceId).append('\''); + sb.append(", lockKey='").append(lockKey).append('\''); + sb.append(", applicationData='").append(applicationData).append('\''); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterResponse.java index 823a8ac18cd..6c387484ac5 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterResponse.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterResponse.java @@ -54,16 +54,11 @@ public short getTypeCode() { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("BranchRegisterResponse: branchId="); - result.append(branchId); - result.append(","); - result.append("result code ="); - result.append(getResultCode()); - result.append(","); - result.append("getMsg ="); - result.append(getMsg()); - - return result.toString(); + final StringBuilder sb = new StringBuilder("BranchRegisterResponse{"); + sb.append("branchId=").append(branchId); + sb.append(", resultCode=").append(resultCode); + sb.append(", msg='").append(msg).append('\''); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java index 24784995991..f6781fda20a 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java @@ -160,22 +160,14 @@ public AbstractTransactionResponse handle(RpcContext rpcContext) { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("xid="); - result.append(xid); - result.append(","); - result.append("branchId="); - result.append(branchId); - result.append(","); - result.append("resourceId="); - result.append(resourceId); - result.append(","); - result.append("status="); - result.append(status); - result.append(","); - result.append("applicationData="); - result.append(applicationData); - - return result.toString(); + final StringBuilder sb = new StringBuilder("BranchReportRequest{"); + sb.append("xid='").append(xid).append('\''); + sb.append(", branchId=").append(branchId); + sb.append(", resourceId='").append(resourceId).append('\''); + sb.append(", status=").append(status); + sb.append(", applicationData='").append(applicationData).append('\''); + sb.append(", branchType=").append(branchType); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchReportResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchReportResponse.java index ce619fb2c6f..5b556a46527 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/BranchReportResponse.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchReportResponse.java @@ -28,4 +28,13 @@ public class BranchReportResponse extends AbstractTransactionResponse { public short getTypeCode() { return MessageType.TYPE_BRANCH_STATUS_REPORT_RESULT; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("BranchReportResponse{"); + sb.append("resultCode=").append(resultCode); + sb.append(", msg='").append(msg).append('\''); + sb.append('}'); + return sb.toString(); + } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java index 8c9e8bb1bc9..26f4cb57b33 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java @@ -78,13 +78,10 @@ public AbstractTransactionResponse handle(RpcContext rpcContext) { @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("timeout="); - result.append(timeout); - result.append(","); - result.append("transactionName="); - result.append(transactionName); - - return result.toString(); + final StringBuilder sb = new StringBuilder("GlobalBeginRequest{"); + sb.append("transactionName='").append(transactionName).append('\''); + sb.append(", timeout=").append(timeout); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginResponse.java index 32c98434134..9e64cea24d6 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginResponse.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginResponse.java @@ -69,4 +69,14 @@ public short getTypeCode() { return MessageType.TYPE_GLOBAL_BEGIN_RESULT; } + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("GlobalBeginResponse{"); + sb.append("xid='").append(xid).append('\''); + sb.append(", extraData='").append(extraData).append('\''); + sb.append(", resultCode=").append(resultCode); + sb.append(", msg='").append(msg).append('\''); + sb.append('}'); + return sb.toString(); + } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryResponse.java index d4e69ab3303..0ffaf742e73 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryResponse.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryResponse.java @@ -50,4 +50,13 @@ public short getTypeCode() { return MessageType.TYPE_GLOBAL_LOCK_QUERY_RESULT; } + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("GlobalLockQueryResponse{"); + sb.append("lockable=").append(lockable); + sb.append(", resultCode=").append(resultCode); + sb.append(", msg='").append(msg).append('\''); + sb.append('}'); + return sb.toString(); + } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalReportRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalReportRequest.java index 44c3a449daf..1f660326172 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalReportRequest.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalReportRequest.java @@ -58,4 +58,14 @@ public GlobalStatus getGlobalStatus() { public void setGlobalStatus(GlobalStatus globalStatus) { this.globalStatus = globalStatus; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("GlobalReportRequest{"); + sb.append("xid='").append(xid).append('\''); + sb.append(",globalStatus=").append(globalStatus); + sb.append(", extraData='").append(extraData).append('\''); + sb.append('}'); + return sb.toString(); + } } diff --git a/core/src/main/java/io/seata/core/protocol/transaction/UndoLogDeleteRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/UndoLogDeleteRequest.java index 1244c7601d6..fbb50d6303c 100644 --- a/core/src/main/java/io/seata/core/protocol/transaction/UndoLogDeleteRequest.java +++ b/core/src/main/java/io/seata/core/protocol/transaction/UndoLogDeleteRequest.java @@ -78,10 +78,11 @@ public short getTypeCode() { @Override public String toString() { - return "UndoLogDeleteRequest{" + - "resourceId='" + resourceId + '\'' + - ", saveDays=" + saveDays + - ", branchType=" + branchType + - '}'; + final StringBuilder sb = new StringBuilder("UndoLogDeleteRequest{"); + sb.append("resourceId='").append(resourceId).append('\''); + sb.append(", saveDays=").append(saveDays); + sb.append(", branchType=").append(branchType); + sb.append('}'); + return sb.toString(); } } diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/BatchLogHandler.java b/core/src/main/java/io/seata/core/rpc/processor/server/BatchLogHandler.java index 6ba53c9195f..9d9d7de8781 100644 --- a/core/src/main/java/io/seata/core/rpc/processor/server/BatchLogHandler.java +++ b/core/src/main/java/io/seata/core/rpc/processor/server/BatchLogHandler.java @@ -15,18 +15,19 @@ */ package io.seata.core.rpc.processor.server; -import io.seata.common.thread.NamedThreadFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import io.seata.common.thread.NamedThreadFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * handle ServerOnRequestProcessor and ServerOnResponseProcessor log print. * @@ -37,7 +38,7 @@ public class BatchLogHandler { private static final Logger LOGGER = LoggerFactory.getLogger(BatchLogHandler.class); - private static final BlockingQueue LOG_QUEUE = new LinkedBlockingQueue<>(); + private static final BlockingQueue LOG_QUEUE = new ArrayBlockingQueue<>(1024 * 10); public static final BatchLogHandler INSTANCE = new BatchLogHandler(); @@ -54,8 +55,14 @@ public class BatchLogHandler { mergeSendExecutorService.submit(new BatchLogRunnable()); } - public BlockingQueue getLogQueue() { - return LOG_QUEUE; + public boolean writeLog(String log) { + try { + LOG_QUEUE.put(log); + } catch (InterruptedException e) { + LOGGER.error("put message to logQueue error: {}", e.getMessage(), e); + return false; + } + return true; } /** diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java index 5701de4b711..5c1ee08d674 100644 --- a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java +++ b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java @@ -146,19 +146,8 @@ public void destroy() { private void onRequestMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) { Object message = rpcMessage.getBody(); RpcContext rpcContext = ChannelManager.getContextFromIdentified(ctx.channel()); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("server received:{},clientIp:{},vgroup:{}", message, - NetUtil.toIpAddress(ctx.channel().remoteAddress()), rpcContext.getTransactionServiceGroup()); - } else { - try { - BatchLogHandler.INSTANCE.getLogQueue() - .put(message + ",clientIp:" + NetUtil.toIpAddress(ctx.channel().remoteAddress()) + ",vgroup:" - + rpcContext.getTransactionServiceGroup()); - } catch (InterruptedException e) { - LOGGER.error("put message to logQueue error: {}", e.getMessage(), e); - } - } if (!(message instanceof AbstractMessage)) { + LOGGER.error("unrecognized message:{}", message); return; } // the batch send request message @@ -209,8 +198,18 @@ private void onRequestMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) } else { // the single send request message final AbstractMessage msg = (AbstractMessage) message; + if (LOGGER.isInfoEnabled()) { + String receiveMsgLog = String.format("receive msg[single]: %s, clientIp: %s, vgroup: %s", message, + NetUtil.toIpAddress(ctx.channel().remoteAddress()), rpcContext.getTransactionServiceGroup()); + BatchLogHandler.INSTANCE.writeLog(receiveMsgLog); + } AbstractResultMessage result = transactionMessageHandler.onRequest(msg, rpcContext); remotingServer.sendAsyncResponse(rpcMessage, ctx.channel(), result); + if (LOGGER.isInfoEnabled()) { + String resultMsgLog = String.format("result msg[single]: %s, clientIp: %s, vgroup: %s", result, + NetUtil.toIpAddress(ctx.channel().remoteAddress()), rpcContext.getTransactionServiceGroup()); + BatchLogHandler.INSTANCE.writeLog(resultMsgLog); + } } } @@ -281,7 +280,18 @@ public void run() { * @param rpcContext rpcContext */ private AbstractResultMessage handleRequestsByMergedWarpMessage(AbstractMessage subMessage, RpcContext rpcContext) { - return transactionMessageHandler.onRequest(subMessage, rpcContext); + if (LOGGER.isInfoEnabled()) { + String receiveMsgLog = String.format("receive msg[merged]: %s, clientIp: %s, vgroup: %s", subMessage, + NetUtil.toIpAddress(rpcContext.getChannel().remoteAddress()), rpcContext.getTransactionServiceGroup()); + BatchLogHandler.INSTANCE.writeLog(receiveMsgLog); + } + AbstractResultMessage resultMessage = transactionMessageHandler.onRequest(subMessage, rpcContext); + if (LOGGER.isInfoEnabled()) { + String resultMsgLog = String.format("result msg[merged]: %s, clientIp: %s, vgroup: %s", resultMessage, + NetUtil.toIpAddress(rpcContext.getChannel().remoteAddress()), rpcContext.getTransactionServiceGroup()); + BatchLogHandler.INSTANCE.writeLog(resultMsgLog); + } + return resultMessage; } /** @@ -294,10 +304,20 @@ private AbstractResultMessage handleRequestsByMergedWarpMessage(AbstractMessage */ private void handleRequestsByMergedWarpMessageBy150(AbstractMessage msg, int msgId, RpcMessage rpcMessage, ChannelHandlerContext ctx, RpcContext rpcContext) { + if (LOGGER.isInfoEnabled()) { + String receiveMsgLog = String.format("receive msg[merged]: %s, clientIp: %s, vgroup: %s", msg, + NetUtil.toIpAddress(ctx.channel().remoteAddress()), rpcContext.getTransactionServiceGroup()); + BatchLogHandler.INSTANCE.writeLog(receiveMsgLog); + } AbstractResultMessage resultMessage = transactionMessageHandler.onRequest(msg, rpcContext); BlockingQueue msgQueue = computeIfAbsentMsgQueue(ctx.channel()); offerMsg(msgQueue, rpcMessage, resultMessage, msgId, ctx.channel()); notifyBatchRespondingThread(); + if (LOGGER.isInfoEnabled()) { + String resultMsgLog = String.format("result msg[merged]: %s, clientIp: %s, vgroup: %s", resultMessage, + NetUtil.toIpAddress(ctx.channel().remoteAddress()), rpcContext.getTransactionServiceGroup()); + BatchLogHandler.INSTANCE.writeLog(resultMsgLog); + } } /** diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnResponseProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnResponseProcessor.java index 705b83a73a0..8f6f4e1cb61 100644 --- a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnResponseProcessor.java +++ b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnResponseProcessor.java @@ -15,6 +15,9 @@ */ package io.seata.core.rpc.processor.server; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import io.netty.channel.ChannelHandlerContext; import io.seata.common.util.NetUtil; import io.seata.core.protocol.AbstractResultMessage; @@ -29,9 +32,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - /** * handle RM/TM response message. *

@@ -66,6 +66,11 @@ public ServerOnResponseProcessor(TransactionMessageHandler transactionMessageHan @Override public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { MessageFuture messageFuture = futures.remove(rpcMessage.getId()); + String receiveMsgLog = String.format("receive msg[single]: %s, clientIp: %s, vgroup: %s", rpcMessage.getBody(), NetUtil.toIpAddress(ctx.channel().remoteAddress()), + ChannelManager.getContextFromIdentified(ctx.channel()).getTransactionServiceGroup()); + if (LOGGER.isInfoEnabled()) { + BatchLogHandler.INSTANCE.writeLog(receiveMsgLog); + } if (messageFuture != null) { messageFuture.setResultMessage(rpcMessage.getBody()); } else { @@ -73,9 +78,6 @@ public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exc onResponseMessage(ctx, rpcMessage); } else { try { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("closeChannelHandlerContext channel:" + ctx.channel()); - } ctx.disconnect(); ctx.close(); } catch (Exception exx) { @@ -89,19 +91,6 @@ public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exc } private void onResponseMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("server received:{},clientIp:{},vgroup:{}", rpcMessage.getBody(), - NetUtil.toIpAddress(ctx.channel().remoteAddress()), - ChannelManager.getContextFromIdentified(ctx.channel()).getTransactionServiceGroup()); - } else { - try { - BatchLogHandler.INSTANCE.getLogQueue() - .put(rpcMessage.getBody() + ",clientIp:" + NetUtil.toIpAddress(ctx.channel().remoteAddress()) + ",vgroup:" - + ChannelManager.getContextFromIdentified(ctx.channel()).getTransactionServiceGroup()); - } catch (InterruptedException e) { - LOGGER.error("put message to logQueue error: {}", e.getMessage(), e); - } - } if (rpcMessage.getBody() instanceof AbstractResultMessage) { RpcContext rpcContext = ChannelManager.getContextFromIdentified(ctx.channel()); transactionMessageHandler.onResponse((AbstractResultMessage) rpcMessage.getBody(), rpcContext); diff --git a/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java b/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java index f30d68bc075..620d6beb72a 100644 --- a/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java +++ b/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java @@ -44,8 +44,7 @@ public void toStringTest() { branchCommitRequest.setResourceId("resource1"); branchCommitRequest.setApplicationData("app1"); - Assertions.assertEquals("xid=127.0.0.1:9999:39875642,branchId=1,branchType=AT," - + "resourceId=resource1,applicationData=app1", branchCommitRequest.toString()); + Assertions.assertEquals("BranchCommitRequest{xid='127.0.0.1:9999:39875642', branchId=1, branchType=AT, resourceId='resource1', applicationData='app1'}", branchCommitRequest.toString()); } } \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java b/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java index 261ee33139d..8cb897ddefa 100644 --- a/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java +++ b/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java @@ -41,7 +41,7 @@ public void toStringTest() { branchCommitResponse.setResultCode(ResultCode.Success); branchCommitResponse.setMsg(""); Assertions.assertEquals( - "xid=127.0.0.1:8091:123456,branchId=2345678,branchStatus=PhaseOne_Done,result code =Success,getMsg =", + "BranchCommitResponse{xid='127.0.0.1:8091:123456', branchId=2345678, branchStatus=PhaseOne_Done, resultCode=Success, msg=''}", branchCommitResponse.toString()); } diff --git a/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java b/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java index 9b86d099511..0f3ec1ad589 100644 --- a/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java +++ b/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java @@ -35,7 +35,7 @@ public void toStringTest() { branchRegisterRequest.setBranchType(BranchType.AT); branchRegisterRequest.setResourceId("resource1"); branchRegisterRequest.setLockKey("lock_key_1"); - Assertions.assertEquals("xid=127.0.0.1:8091:1249853,branchType=AT,resourceId=resource1,lockKey=lock_key_1", + Assertions.assertEquals("BranchRegisterRequest{xid='127.0.0.1:8091:1249853', branchType=AT, resourceId='resource1', lockKey='lock_key_1', applicationData='null'}", branchRegisterRequest.toString()); } diff --git a/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java b/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java index ef431c229ef..88502f223a5 100644 --- a/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java +++ b/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java @@ -38,7 +38,7 @@ public void toStringTest() { branchRegisterResponse.setResultCode(ResultCode.Success); branchRegisterResponse.setMsg(""); Assertions.assertEquals( - "BranchRegisterResponse: branchId=123457,result code =Success,getMsg =", + "BranchRegisterResponse{branchId=123457, resultCode=Success, msg=''}", branchRegisterResponse.toString()); } diff --git a/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java b/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java index 86988637c14..c4b0bfbb2a9 100644 --- a/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java +++ b/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java @@ -38,9 +38,7 @@ public void testToString() { branchReportRequest.setStatus(BranchStatus.PhaseOne_Timeout); branchReportRequest.setApplicationData("test app data"); Assertions.assertEquals( - "xid=127.0.0.1:8091:1249853,branchId=3,resourceId=resource003,status=PhaseOne_Timeout," - + "applicationData=test app" - + " data", + "BranchReportRequest{xid='127.0.0.1:8091:1249853', branchId=3, resourceId='resource003', status=PhaseOne_Timeout, applicationData='test app data', branchType=AT}", branchReportRequest.toString()); } diff --git a/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java b/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java index 3cc7d57e890..fcd1f9ed8d1 100644 --- a/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java +++ b/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java @@ -37,9 +37,8 @@ public class GlobalBeginRequestTest { public void testToString() throws Exception { GlobalBeginRequest globalBeginRequest = new GlobalBeginRequest(); globalBeginRequest.setTransactionName("tran 1"); - System.out.println(globalBeginRequest.toString()); - Assertions.assertEquals("timeout=60000,transactionName=tran 1", globalBeginRequest.toString()); + Assertions.assertEquals("GlobalBeginRequest{transactionName='tran 1', timeout=60000}", globalBeginRequest.toString()); } } \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java b/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java index ad1a88afb50..bf4df81783b 100644 --- a/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java +++ b/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java @@ -45,7 +45,7 @@ public void testToString() throws Exception { System.out.println(globalCommitResponse.toString()); - Assertions.assertEquals("globalStatus=Committed,ResultCode=Success,Msg=OK", globalCommitResponse.toString()); + Assertions.assertEquals("GlobalCommitResponse{globalStatus=Committed, resultCode=Success, msg='OK'}", globalCommitResponse.toString()); } } \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java b/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java index 70819352b28..22ad1d6d7d3 100644 --- a/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java +++ b/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java @@ -33,7 +33,7 @@ public void testToString() { GlobalRollbackRequest globalRollbackRequest = new GlobalRollbackRequest(); globalRollbackRequest.setXid("127.0.0.1:8091:1249853"); globalRollbackRequest.setExtraData("test_extra_data"); - Assertions.assertEquals("xid=127.0.0.1:8091:1249853,extraData=test_extra_data", globalRollbackRequest.toString()); + Assertions.assertEquals("GlobalRollbackRequest{xid='127.0.0.1:8091:1249853', extraData='test_extra_data'}", globalRollbackRequest.toString()); } } \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/message/RegisterTMRequestTest.java b/core/src/test/java/io/seata/core/message/RegisterTMRequestTest.java index eae57ff4c79..3c1b49e8903 100644 --- a/core/src/test/java/io/seata/core/message/RegisterTMRequestTest.java +++ b/core/src/test/java/io/seata/core/message/RegisterTMRequestTest.java @@ -37,7 +37,7 @@ public void testToString() throws Exception { registerTMRequest.setApplicationId("seata"); registerTMRequest.setTransactionServiceGroup("daliy_2019"); registerTMRequest.setVersion("2019-snapshot"); - Assertions.assertEquals("RegisterTMRequest{applicationId='seata', transactionServiceGroup='daliy_2019'}", + Assertions.assertEquals("RegisterTMRequest{version='2019-snapshot', applicationId='seata', transactionServiceGroup='daliy_2019', extraData=''}", registerTMRequest.toString()); } } diff --git a/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java b/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java index e546d10bab2..15ce708845f 100644 --- a/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java +++ b/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java @@ -37,7 +37,7 @@ public void testToString() throws Exception { registerTMResponse.setVersion("1"); registerTMResponse.setIdentified(true); registerTMResponse.setResultCode(ResultCode.Success); - Assertions.assertEquals("version=1,extraData=null,identified=true,resultCode=Success,msg=null", + Assertions.assertEquals("RegisterTMResponse{version='1', extraData='null', identified=true, resultCode=Success, msg='null'}", registerTMResponse.toString()); } } diff --git a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java index eda94ba4fca..3c7c786e768 100644 --- a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java +++ b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java @@ -34,8 +34,7 @@ public void toStringTest() { branchRollbackRequest.setResourceId("resource1"); branchRollbackRequest.setApplicationData("app1"); - Assertions.assertEquals("xid=127.0.0.1:9999:39875642,branchId=1,branchType=AT," - + "resourceId=resource1,applicationData=app1", branchRollbackRequest.toString()); + Assertions.assertEquals("BranchRollbackRequest{xid='127.0.0.1:9999:39875642', branchId=1, branchType=AT, resourceId='resource1', applicationData='app1'}", branchRollbackRequest.toString()); } diff --git a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java index 5de4e35ec0c..ee6b480c575 100644 --- a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java +++ b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java @@ -33,7 +33,7 @@ public void toStringTest() { branchRollbackResponse.setResultCode(ResultCode.Success); branchRollbackResponse.setMsg(""); Assertions.assertEquals( - "xid=127.0.0.1:8091:123456,branchId=2345678,branchStatus=PhaseOne_Done,result code =Success,getMsg =", + "BranchRollbackResponse{xid='127.0.0.1:8091:123456', branchId=2345678, branchStatus=PhaseOne_Done, resultCode=Success, msg=''}", branchRollbackResponse.toString()); } diff --git a/serializer/seata-serializer-seata/src/test/java/io/seata/serializer/seata/protocol/RegisterTMRequestSerializerTest.java b/serializer/seata-serializer-seata/src/test/java/io/seata/serializer/seata/protocol/RegisterTMRequestSerializerTest.java index 07281f7b718..99ed2a61374 100644 --- a/serializer/seata-serializer-seata/src/test/java/io/seata/serializer/seata/protocol/RegisterTMRequestSerializerTest.java +++ b/serializer/seata-serializer-seata/src/test/java/io/seata/serializer/seata/protocol/RegisterTMRequestSerializerTest.java @@ -98,14 +98,6 @@ public void testGetTypeCode() { Assertions.assertEquals(TYPE_CODE, registerTMRequest.getTypeCode()); } - /** - * Test toString having all the parameters initialized to null - */ - @Test - public void testToStringNullValues() { - Assertions.assertEquals("RegisterTMRequest{" + "applicationId='" + null + '\'' + ", transactionServiceGroup='" - + null + '\'' + '}', registerTMRequest.toString()); - } /** * Test decode method with empty parameter diff --git a/server/src/main/resources/logback/console-appender.xml b/server/src/main/resources/logback/console-appender.xml index e18e06823ad..542b1b46afa 100644 --- a/server/src/main/resources/logback/console-appender.xml +++ b/server/src/main/resources/logback/console-appender.xml @@ -18,7 +18,7 @@ + defaultValue="%clr(%d{HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%25.25t]){faint} %clr([%-30.30logger]){cyan} %clr([%20.20M]){faint} %clr([%X{X-TX-XID:-}]){faint} %clr(:){faint} %m%n%wEx2"/> diff --git a/server/src/main/resources/logback/file-appender.xml b/server/src/main/resources/logback/file-appender.xml index bfd2d03267b..9225d75efc7 100644 --- a/server/src/main/resources/logback/file-appender.xml +++ b/server/src/main/resources/logback/file-appender.xml @@ -20,7 +20,7 @@ + defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p --- [%t] [%logger] [%M] [%X{X-TX-XID:-}]: %m%n%wEx2"/> From 8b0a3cbb76f43d44a0165349518ddd89410d481c Mon Sep 17 00:00:00 2001 From: jimin Date: Thu, 4 May 2023 11:17:31 +0800 Subject: [PATCH 52/76] optimize: update expire gpg key and publish workflow (#5548) --- .../{publishes.yml => publish-docker.yml} | 35 +---------------- .github/workflows/publish-ossrh.yml | 39 +++++++++++++++++++ build/pom.xml | 2 +- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 2 +- 5 files changed, 43 insertions(+), 36 deletions(-) rename .github/workflows/{publishes.yml => publish-docker.yml} (64%) create mode 100644 .github/workflows/publish-ossrh.yml diff --git a/.github/workflows/publishes.yml b/.github/workflows/publish-docker.yml similarity index 64% rename from .github/workflows/publishes.yml rename to .github/workflows/publish-docker.yml index 9e179e7f9b4..c2a1a60268c 100644 --- a/.github/workflows/publishes.yml +++ b/.github/workflows/publish-docker.yml @@ -1,4 +1,4 @@ -name: "Publishes" +name: "Publish Docker Image" on: push: @@ -11,39 +11,6 @@ on: jobs: # job 1 - publish-to-OSSRH: - name: "Publish to OSSRH" - runs-on: ubuntu-latest - strategy: - fail-fast: false - steps: - # step 1 - - name: "Checkout" - uses: actions/checkout@v2.4.0 - # step 2 - - name: "Setup Java JDK" - uses: actions/setup-java@v3.9.0 - with: - distribution: 'zulu' - java-version: 8 - server-id: oss_seata - server-username: OSSRH_USERNAME # Environment variable name for the username for authentication to the Apache Maven repository. Default is $GITHUB_ACTOR - server-password: OSSRH_PASSWORD # Environment variable name for password or token for authentication to the Apache Maven repository. Default is $GITHUB_TOKEN - gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} - gpg-passphrase: GPG_PASSPHRASE # Environment variable name for the GPG private key passphrase. Default is $GPG_PASSPHRASE - # step 3 - - name: "Print maven version" - run: ./mvnw -version - # step 4 - - name: "Publish to OSSRH" - env: - OSSRH_USERNAME: ${{ secrets.OSSRH_USER }} - OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - run: | - ./mvnw -T 4C clean deploy -Prelease,release-by-github-actions -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn - - # job 2 publish-images-to-dockerhub: name: "Publish images to DockerHub" runs-on: ubuntu-latest diff --git a/.github/workflows/publish-ossrh.yml b/.github/workflows/publish-ossrh.yml new file mode 100644 index 00000000000..6cf10be8e20 --- /dev/null +++ b/.github/workflows/publish-ossrh.yml @@ -0,0 +1,39 @@ +name: "Publish OSSRH" + +on: + push: + branches: [ develop, 2.x, snapshot, "*.*.*" ] + +jobs: + # job 1 + publish-to-OSSRH: + name: "Publish to OSSRH" + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + # step 1 + - name: "Checkout" + uses: actions/checkout@v2.4.0 + # step 2 + - name: "Setup Java JDK" + uses: actions/setup-java@v3.9.0 + with: + distribution: 'zulu' + java-version: 8 + server-id: oss_seata + server-username: OSSRH_USERNAME # Environment variable name for the username for authentication to the Apache Maven repository. Default is $GITHUB_ACTOR + server-password: OSSRH_PASSWORD # Environment variable name for password or token for authentication to the Apache Maven repository. Default is $GITHUB_TOKEN + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE # Environment variable name for the GPG private key passphrase. Default is $GPG_PASSPHRASE + # step 3 + - name: "Print maven version" + run: ./mvnw -version + # step 4 + - name: "Publish to OSSRH" + env: + OSSRH_USERNAME: ${{ secrets.OSSRH_USER }} + OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + run: | + ./mvnw -T 4C clean deploy -Prelease,release-by-github-actions -DskipTests -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ No newline at end of file diff --git a/build/pom.xml b/build/pom.xml index 97202e90359..53aca9c1e3d 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -120,7 +120,7 @@ true false - A1C4DAB9B220DBA0C277E945D6A1420D747D1EE0 + 37F181C60AACE24BD5C1D3925583F79497E8E293 diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 4153ab3870b..b97d7ede2a4 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -50,6 +50,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5414](https://github.com/seata/seata/pull/5414)] optimize transaction fail handler - [[#5537](https://github.com/seata/seata/pull/5537)] optimize transaction log on client side - [[#5541](https://github.com/seata/seata/pull/5541)] optimize server log output +- [[#5548](https://github.com/seata/seata/pull/5548)] update expire gpg key and publish workflow ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 77f3ec3995e..659839fa21c 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -50,7 +50,7 @@ - [[#5414](https://github.com/seata/seata/pull/5414)] 优化事务失败处理 handler - [[#5537](https://github.com/seata/seata/pull/5537)] 优化客户侧事务日志 - [[#5541](https://github.com/seata/seata/pull/5541)] 优化Server日志输出 - +- [[#5548](https://github.com/seata/seata/pull/5548)] 优化 gpg key 和 发布流水线 ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 From 35f9fe771da35e0d8ce143627b97cb46397748a9 Mon Sep 17 00:00:00 2001 From: FUNKYE <364176773@qq.com> Date: Sun, 7 May 2023 17:52:51 +0800 Subject: [PATCH 53/76] bugfix: fix mariadb rollback failed (#5552) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../datasource/undo/AbstractUndoExecutor.java | 33 +++++++------------ .../undo/AbstractUndoLogManager.java | 8 +++-- .../seata/rm/datasource/undo/BaseH2Test.java | 10 ++++-- .../rm/datasource/undo/UndoExecutorTest.java | 32 +++++++++++------- 6 files changed, 46 insertions(+), 39 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index b97d7ede2a4..d649d3b0de7 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -33,6 +33,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5538](https://github.com/seata/seata/pull/5538)] fix finished transaction swallows exception when committing - [[#5539](https://github.com/seata/seata/pull/5539)] fix the full table scan issue with 'setDate' condition in Oracle 10g - [[#5540](https://github.com/seata/seata/pull/5540)] fix GlobalStatus=9 can't be cleared in DB storage mode +- [[#5552](https://github.com/seata/seata/pull/5552)] fix mariadb rollback failed ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 659839fa21c..45063ebae52 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -33,6 +33,7 @@ - [[#5538](https://github.com/seata/seata/pull/5538)] 修复提交事务时事务已完成不抛出异常问题 - [[#5539](https://github.com/seata/seata/pull/5539)] 修复Oracle 10g where条件包含setDate全表扫描问题 - [[#5540](https://github.com/seata/seata/pull/5540)] 修复 GlobalStatus=9 在DB存储模式无法清除的问题 +- [[#5552](https://github.com/seata/seata/pull/5552)] 修复mariadb回滚失败的问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java index ac8026eeb6e..a2e70dfa96f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java @@ -34,6 +34,7 @@ import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.model.Result; +import io.seata.rm.datasource.ConnectionProxy; import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.DataCompareUtils; import io.seata.rm.datasource.SqlGenerateUtils; @@ -43,7 +44,6 @@ import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; -import io.seata.rm.datasource.util.JdbcUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -110,11 +110,12 @@ public SQLUndoLog getSqlUndoLog() { /** * Execute on. * - * @param conn the conn + * @param connectionProxy the connection proxy * @throws SQLException the sql exception */ - public void executeOn(Connection conn) throws SQLException { - if (IS_UNDO_DATA_VALIDATION_ENABLE && !dataValidationAndGoOn(conn)) { + public void executeOn(ConnectionProxy connectionProxy) throws SQLException { + Connection conn = connectionProxy.getTargetConnection(); + if (IS_UNDO_DATA_VALIDATION_ENABLE && !dataValidationAndGoOn(connectionProxy)) { return; } PreparedStatement undoPST = null; @@ -124,7 +125,7 @@ public void executeOn(Connection conn) throws SQLException { TableRecords undoRows = getUndoRows(); for (Row undoRow : undoRows.getRows()) { ArrayList undoValues = new ArrayList<>(); - List pkValueList = getOrderedPkList(undoRows, undoRow, getDbType(conn)); + List pkValueList = getOrderedPkList(undoRows, undoRow, connectionProxy.getDbType()); for (Field field : undoRow.getFields()) { if (field.getKeyType() != KeyType.PRIMARY_KEY) { undoValues.add(field); @@ -228,7 +229,7 @@ protected void undoPrepare(PreparedStatement undoPST, ArrayList undoValue * @return return true if data validation is ok and need continue undo, and return false if no need continue undo. * @throws SQLException the sql exception such as has dirty data */ - protected boolean dataValidationAndGoOn(Connection conn) throws SQLException { + protected boolean dataValidationAndGoOn(ConnectionProxy conn) throws SQLException { TableRecords beforeRecords = sqlUndoLog.getBeforeImage(); TableRecords afterRecords = sqlUndoLog.getAfterImage(); @@ -251,7 +252,7 @@ protected boolean dataValidationAndGoOn(Connection conn) throws SQLException { Result afterEqualsCurrentResult = DataCompareUtils.isRecordsEquals(afterRecords, currentRecords); if (!afterEqualsCurrentResult.getResult()) { - // If current data is not equivalent to the after data, then compare the current data with the before + // If current data is not equivalent to the after data, then compare the current data with the before // data, too. No need continue to undo if current data is equivalent to the before data snapshot Result beforeEqualsCurrentResult = DataCompareUtils.isRecordsEquals(beforeRecords, currentRecords); if (beforeEqualsCurrentResult.getResult()) { @@ -282,11 +283,12 @@ protected boolean dataValidationAndGoOn(Connection conn) throws SQLException { /** * Query current records. * - * @param conn the conn + * @param connectionProxy the connection proxy * @return the table records * @throws SQLException the sql exception */ - protected TableRecords queryCurrentRecords(Connection conn) throws SQLException { + protected TableRecords queryCurrentRecords(ConnectionProxy connectionProxy) throws SQLException { + Connection conn = connectionProxy.getTargetConnection(); TableRecords undoRecords = getUndoRows(); TableMeta tableMeta = undoRecords.getTableMeta(); //the order of element matters @@ -301,7 +303,7 @@ protected TableRecords queryCurrentRecords(Connection conn) throws SQLException String firstKey = pkRowValues.keySet().stream().findFirst().get(); int pkRowSize = pkRowValues.get(firstKey).size(); String checkSQL = String.format(CHECK_SQL_TEMPLATE, sqlUndoLog.getTableName(), - SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, pkRowSize, getDbType(conn))); + SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, pkRowSize, connectionProxy.getDbType())); PreparedStatement statement = null; ResultSet checkSet = null; @@ -380,15 +382,4 @@ protected Map> parsePkValues(List rows, List pk return pkValueMap; } - /** - * Get db type - * - * @param conn the connection - * @return the db type - * @throws SQLException SQLException - */ - protected String getDbType(Connection conn) throws SQLException { - return JdbcUtils.getDbType(conn.getMetaData().getURL()); - } - } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java index 95543d3c094..e6ae3232075 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java @@ -255,6 +255,7 @@ public void flushUndoLogs(ConnectionProxy cp) throws SQLException { */ @Override public void undo(DataSourceProxy dataSourceProxy, String xid, long branchId) throws TransactionException { + ConnectionProxy connectionProxy = null; Connection conn = null; ResultSet rs = null; PreparedStatement selectPST = null; @@ -262,7 +263,8 @@ public void undo(DataSourceProxy dataSourceProxy, String xid, long branchId) thr for (; ; ) { try { - conn = dataSourceProxy.getPlainConnection(); + connectionProxy = dataSourceProxy.getConnection(); + conn = connectionProxy.getTargetConnection(); // The entire undo process should run in a local transaction. if (originalAutoCommit = conn.getAutoCommit()) { @@ -312,7 +314,7 @@ public void undo(DataSourceProxy dataSourceProxy, String xid, long branchId) thr sqlUndoLog.setTableMeta(tableMeta); AbstractUndoExecutor undoExecutor = UndoExecutorFactory.getUndoExecutor( dataSourceProxy.getDbType(), sqlUndoLog); - undoExecutor.executeOn(conn); + undoExecutor.executeOn(connectionProxy); } } finally { // remove serializer name @@ -381,7 +383,7 @@ public void undo(DataSourceProxy dataSourceProxy, String xid, long branchId) thr if (originalAutoCommit) { conn.setAutoCommit(true); } - conn.close(); + connectionProxy.close(); } } catch (SQLException closeEx) { LOGGER.warn("Failed to close JDBC resource while undo ... ", closeEx); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java index 9da87a72e07..ed3bab07f02 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java @@ -16,6 +16,8 @@ package io.seata.rm.datasource.undo; import io.seata.common.util.IOUtil; +import io.seata.rm.datasource.ConnectionProxy; +import io.seata.rm.datasource.DataSourceProxy; import io.seata.rm.datasource.sql.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; @@ -44,7 +46,9 @@ public abstract class BaseH2Test { static BasicDataSource dataSource = null; - static Connection connection = null; + static ConnectionProxy connection = null; + + static DataSourceProxy dataSourceProxy = null; static TableMeta tableMeta = null; @@ -55,8 +59,8 @@ public static void start() throws SQLException { dataSource.setUrl("jdbc:h2:./db_store/test_undo"); dataSource.setUsername("sa"); dataSource.setPassword(""); - - connection = dataSource.getConnection(); + dataSourceProxy = new DataSourceProxy(dataSource); + connection = dataSourceProxy.getConnection(); tableMeta = mockTableMeta(); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java index 2946e9204e8..43ccb10c595 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java @@ -49,6 +49,9 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; +import io.seata.rm.datasource.ConnectionProxy; +import io.seata.rm.datasource.DataSourceProxy; +import io.seata.rm.datasource.mock.MockDataSource; import io.seata.sqlparser.SQLType; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; @@ -56,6 +59,7 @@ import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.util.JdbcConstants; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -64,6 +68,12 @@ */ public class UndoExecutorTest { + MockConnection connection = new MockConnection(); + MockDataSource dataSource = new MockDataSource(); + DataSourceProxy dataSourceProxy = new DataSourceProxy(dataSource); + ConnectionProxy connectionProxy = new ConnectionProxy(dataSourceProxy, connection); + + /** * Test field. */ @@ -146,12 +156,11 @@ public void testUpdate() throws SQLException { SQLUndoLog.setAfterImage(afterImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - MockConnection connection = new MockConnection(); AbstractUndoExecutor spy = Mockito.spy(executor); // skip data validation - Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); - Mockito.doReturn(JdbcConstants.MYSQL).when(spy).getDbType(connection); - spy.executeOn(connection); + Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connectionProxy); + Assertions.assertEquals(JdbcConstants.MYSQL,connectionProxy.getDbType()); + spy.executeOn(connectionProxy); } /** @@ -216,12 +225,11 @@ public void testInsert() throws SQLException { SQLUndoLog.setAfterImage(afterImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - MockConnection connection = new MockConnection(); AbstractUndoExecutor spy = Mockito.spy(executor); // skip data validation - Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); - Mockito.doReturn(JdbcConstants.MYSQL).when(spy).getDbType(connection); - spy.executeOn(connection); + Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connectionProxy); + Assertions.assertEquals(JdbcConstants.MYSQL,connectionProxy.getDbType()); + spy.executeOn(connectionProxy); } /** @@ -286,12 +294,12 @@ public void testDelete() throws SQLException { SQLUndoLog.setBeforeImage(beforeImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - MockConnection connection = new MockConnection(); + AbstractUndoExecutor spy = Mockito.spy(executor); // skip data validation - Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); - Mockito.doReturn(JdbcConstants.MYSQL).when(spy).getDbType(connection); - spy.executeOn(connection); + Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connectionProxy); + Assertions.assertEquals(JdbcConstants.MYSQL,connectionProxy.getDbType()); + spy.executeOn(connectionProxy); } /** From 6b1a84f4ecb705fdf0e0e4fd96dc76698da3ecd7 Mon Sep 17 00:00:00 2001 From: justabug Date: Thu, 1 Jun 2023 09:24:40 +0800 Subject: [PATCH 54/76] bugfix: fix log in participant transaction role (#5602) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../tm/api/DefaultGlobalTransaction.java | 7 +++++- .../seata/tm/api/TransactionalTemplate.java | 22 ++++++------------- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index d649d3b0de7..52cd58da048 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -34,6 +34,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5539](https://github.com/seata/seata/pull/5539)] fix the full table scan issue with 'setDate' condition in Oracle 10g - [[#5540](https://github.com/seata/seata/pull/5540)] fix GlobalStatus=9 can't be cleared in DB storage mode - [[#5552](https://github.com/seata/seata/pull/5552)] fix mariadb rollback failed +- [[#5602](https://github.com/seata/seata/pull/5602)] fix log in participant transaction role ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 45063ebae52..cf7ff480905 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -34,6 +34,7 @@ - [[#5539](https://github.com/seata/seata/pull/5539)] 修复Oracle 10g where条件包含setDate全表扫描问题 - [[#5540](https://github.com/seata/seata/pull/5540)] 修复 GlobalStatus=9 在DB存储模式无法清除的问题 - [[#5552](https://github.com/seata/seata/pull/5552)] 修复mariadb回滚失败的问题 +- [[#5602](https://github.com/seata/seata/pull/5602)] 修复participant情况下的重复日志 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java index 79fb26eb289..478dae261af 100644 --- a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java +++ b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java @@ -129,6 +129,9 @@ public void commit() throws TransactionException { return; } assertXIDNotNull(); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("transaction {} will be commit", xid); + } int retry = COMMIT_RETRY_COUNT <= 0 ? DEFAULT_TM_COMMIT_RETRY_COUNT : COMMIT_RETRY_COUNT; try { while (retry > 0) { @@ -164,7 +167,9 @@ public void rollback() throws TransactionException { return; } assertXIDNotNull(); - + if (LOGGER.isInfoEnabled()) { + LOGGER.info("transaction {} will be rollback", xid); + } int retry = ROLLBACK_RETRY_COUNT <= 0 ? DEFAULT_TM_ROLLBACK_RETRY_COUNT : ROLLBACK_RETRY_COUNT; try { while (retry > 0) { diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java index 83932934759..01998a4400b 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java @@ -74,8 +74,8 @@ public Object execute(TransactionalExecutor business) throws Throwable { // If transaction is existing, suspend it, and then begin new transaction. if (existingTransaction(tx)) { suspendedResourcesHolder = tx.suspend(false); - tx = GlobalTransactionContext.createNew(); } + tx = GlobalTransactionContext.createNew(); // Continue and execute with new transaction break; case SUPPORTS: @@ -86,8 +86,8 @@ public Object execute(TransactionalExecutor business) throws Throwable { // Continue and execute with new transaction break; case REQUIRED: - // If current transaction is existing, execute with current transaction, - // else continue and execute with new transaction. + // If current transaction is existing, execute with current transaction,else create + tx = GlobalTransactionContext.getCurrentOrCreate(); break; case NEVER: // If transaction is existing, throw exception. @@ -110,14 +110,13 @@ public Object execute(TransactionalExecutor business) throws Throwable { throw new TransactionException("Not Supported Propagation:" + propagation); } - // 1.3 If null, create new transaction with role 'GlobalTransactionRole.Launcher'. - if (tx == null) { - tx = GlobalTransactionContext.createNew(); - } - // set current tx config to holder GlobalLockConfig previousConfig = replaceGlobalLockConfig(txInfo); + if (tx.getGlobalTransactionRole() == GlobalTransactionRole.Participant) { + LOGGER.info("join into a existing global transaction,xid={}", tx.getXid()); + } + try { // 2. If the tx role is 'GlobalTransactionRole.Launcher', send the request of beginTransaction to TC, // else do nothing. Of course, the hooks will still be triggered. @@ -211,9 +210,6 @@ private void commitTransaction(GlobalTransaction tx, TransactionInfo txInfo) try { triggerBeforeCommit(); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("transaction {} will be commit", tx.getXid()); - } tx.commit(); GlobalStatus afterCommitStatus = tx.getLocalStatus(); TransactionalExecutor.Code code = TransactionalExecutor.Code.Unknown; @@ -252,10 +248,6 @@ private void rollbackTransaction(GlobalTransaction tx, Throwable originalExcepti try { triggerBeforeRollback(); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("transaction {} will be rollback, cause by:{}", tx.getXid(), - originalException.getMessage()); - } tx.rollback(); triggerAfterRollback(); } catch (TransactionException txe) { From bd18f087ea4a7f93431de0cddb315ff79ce5a879 Mon Sep 17 00:00:00 2001 From: StephenFaust <76416760+StephenFaust@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:01:15 +0800 Subject: [PATCH 55/76] bugfix: grpc interceptor xid unbinding problem (#5583) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../grpc/interceptor/server/ServerListenerProxy.java | 10 ++++------ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 52cd58da048..bd35c58c196 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -34,6 +34,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5539](https://github.com/seata/seata/pull/5539)] fix the full table scan issue with 'setDate' condition in Oracle 10g - [[#5540](https://github.com/seata/seata/pull/5540)] fix GlobalStatus=9 can't be cleared in DB storage mode - [[#5552](https://github.com/seata/seata/pull/5552)] fix mariadb rollback failed +- [[#5583](https://github.com/seata/seata/pull/5583)] fix grpc interceptor xid unbinding problem - [[#5602](https://github.com/seata/seata/pull/5602)] fix log in participant transaction role ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index cf7ff480905..ae7f5e8fee5 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -34,6 +34,7 @@ - [[#5539](https://github.com/seata/seata/pull/5539)] 修复Oracle 10g where条件包含setDate全表扫描问题 - [[#5540](https://github.com/seata/seata/pull/5540)] 修复 GlobalStatus=9 在DB存储模式无法清除的问题 - [[#5552](https://github.com/seata/seata/pull/5552)] 修复mariadb回滚失败的问题 +- [[#5583](https://github.com/seata/seata/pull/5583)] 修复grpc xid 解绑问题 - [[#5602](https://github.com/seata/seata/pull/5602)] 修复participant情况下的重复日志 ### optimize: diff --git a/integration/grpc/src/main/java/io/seata/integration/grpc/interceptor/server/ServerListenerProxy.java b/integration/grpc/src/main/java/io/seata/integration/grpc/interceptor/server/ServerListenerProxy.java index 03d838487f6..66eb7b944b5 100644 --- a/integration/grpc/src/main/java/io/seata/integration/grpc/interceptor/server/ServerListenerProxy.java +++ b/integration/grpc/src/main/java/io/seata/integration/grpc/interceptor/server/ServerListenerProxy.java @@ -18,6 +18,7 @@ import io.grpc.ServerCall; import io.seata.common.util.StringUtils; import io.seata.core.context.RootContext; +import io.seata.core.model.BranchType; import java.util.Objects; @@ -43,6 +44,7 @@ public void onMessage(ReqT message) { @Override public void onHalfClose() { + RootContext.unbind(); if (StringUtils.isNotBlank(xid)) { RootContext.bind(xid); } @@ -51,17 +53,11 @@ public void onHalfClose() { @Override public void onCancel() { - if (StringUtils.isNotBlank(xid) && RootContext.inGlobalTransaction()) { - RootContext.unbind(); - } target.onCancel(); } @Override public void onComplete() { - if (StringUtils.isNotBlank(xid) && RootContext.inGlobalTransaction()) { - RootContext.unbind(); - } target.onComplete(); } @@ -69,4 +65,6 @@ public void onComplete() { public void onReady() { target.onReady(); } + + } From 6851eb42c01ad01033a84be1abc89a4b7e654891 Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 14 Jun 2023 21:42:13 +0800 Subject: [PATCH 56/76] bugfix: fix oracle insert undolog failed (#5645) Signed-off-by: slievrly --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + script/client/at/db/oracle.sql | 7 ++++++- script/client/at/db/postgresql.sql | 6 +++++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index bd35c58c196..8930e4c88d8 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -36,6 +36,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5552](https://github.com/seata/seata/pull/5552)] fix mariadb rollback failed - [[#5583](https://github.com/seata/seata/pull/5583)] fix grpc interceptor xid unbinding problem - [[#5602](https://github.com/seata/seata/pull/5602)] fix log in participant transaction role +- [[#5645](https://github.com/seata/seata/pull/5645)] fix oracle insert undolog failed ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index ae7f5e8fee5..62a471193d2 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -36,6 +36,7 @@ - [[#5552](https://github.com/seata/seata/pull/5552)] 修复mariadb回滚失败的问题 - [[#5583](https://github.com/seata/seata/pull/5583)] 修复grpc xid 解绑问题 - [[#5602](https://github.com/seata/seata/pull/5602)] 修复participant情况下的重复日志 +- [[#5645](https://github.com/seata/seata/pull/5645)] 修复 oracle 插入 undolog 失败问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/script/client/at/db/oracle.sql b/script/client/at/db/oracle.sql index e1db1e95d44..364dc68b74a 100644 --- a/script/client/at/db/oracle.sql +++ b/script/client/at/db/oracle.sql @@ -1,6 +1,7 @@ -- for AT mode you must to init this sql for you business database. the seata server not need it. CREATE TABLE undo_log ( + id NUMBER(19) NOT NULL, branch_id NUMBER(19) NOT NULL, xid VARCHAR2(128) NOT NULL, context VARCHAR2(128) NOT NULL, @@ -8,6 +9,7 @@ CREATE TABLE undo_log log_status NUMBER(10) NOT NULL, log_created TIMESTAMP(0) NOT NULL, log_modified TIMESTAMP(0) NOT NULL, + PRIMARY KEY (id), CONSTRAINT ux_undo_log UNIQUE (xid, branch_id) ); CREATE INDEX ix_log_created ON undo_log(log_created); @@ -18,4 +20,7 @@ COMMENT ON COLUMN undo_log.context is 'undo_log context,such as serialization'; COMMENT ON COLUMN undo_log.rollback_info is 'rollback info'; COMMENT ON COLUMN undo_log.log_status is '0:normal status,1:defense status'; COMMENT ON COLUMN undo_log.log_created is 'create datetime'; -COMMENT ON COLUMN undo_log.log_modified is 'modify datetime'; \ No newline at end of file +COMMENT ON COLUMN undo_log.log_modified is 'modify datetime'; + +-- Generate ID using sequence and trigger +CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1; \ No newline at end of file diff --git a/script/client/at/db/postgresql.sql b/script/client/at/db/postgresql.sql index 6b9feddd406..bf562bcbdc3 100644 --- a/script/client/at/db/postgresql.sql +++ b/script/client/at/db/postgresql.sql @@ -1,6 +1,7 @@ -- for AT mode you must to init this sql for you business database. the seata server not need it. CREATE TABLE IF NOT EXISTS public.undo_log ( + id SERIAL NOT NULL, branch_id BIGINT NOT NULL, xid VARCHAR(128) NOT NULL, context VARCHAR(128) NOT NULL, @@ -8,6 +9,7 @@ CREATE TABLE IF NOT EXISTS public.undo_log log_status INT NOT NULL, log_created TIMESTAMP(0) NOT NULL, log_modified TIMESTAMP(0) NOT NULL, + CONSTRAINT pk_undo_log PRIMARY KEY (id), CONSTRAINT ux_undo_log UNIQUE (xid, branch_id) ); CREATE INDEX ix_log_created ON undo_log(log_created); @@ -19,4 +21,6 @@ COMMENT ON COLUMN public.undo_log.context IS 'undo_log context,such as serializa COMMENT ON COLUMN public.undo_log.rollback_info IS 'rollback info'; COMMENT ON COLUMN public.undo_log.log_status IS '0:normal status,1:defense status'; COMMENT ON COLUMN public.undo_log.log_created IS 'create datetime'; -COMMENT ON COLUMN public.undo_log.log_modified IS 'modify datetime'; \ No newline at end of file +COMMENT ON COLUMN public.undo_log.log_modified IS 'modify datetime'; + +CREATE SEQUENCE IF NOT EXISTS undo_log_id_seq INCREMENT BY 1 MINVALUE 1 ; \ No newline at end of file From 85330dc7930791c540dbda257e3dfdd466bd0f5f Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 14 Jun 2023 22:40:09 +0800 Subject: [PATCH 57/76] optimize: refactor ColumnUtils and EscapeHandler (#5646) Signed-off-by: slievrly --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../exec/BaseTransactionalExecutor.java | 2 +- .../datasource/exec/MultiUpdateExecutor.java | 4 +- .../rm/datasource/exec/UpdateExecutor.java | 4 +- .../handler/mariadb/MariadbEscapeHandler.java | 29 +-- .../handler/mysql/MySQLEscapeHandler.java} | 24 ++- .../handler/oracle/OracleEscapeHandler.java} | 37 +++- .../postgresql/PostgresqlEscapeHandler.java} | 24 ++- .../services/io.seata.sqlparser.EscapeHandler | 4 + .../io.seata.sqlparser.KeywordChecker | 3 - .../seata/rm/datasource/ColumnUtilsTest.java | 22 +-- .../sql/handler/EscapeHandlerTest.java | 129 ++++++++++++ ...est.java => EscapeHandlerFactoryTest.java} | 12 +- ...ywordChecker.java => H2EscapeHandler.java} | 4 +- ...rTest.java => MySQLEscapeHandlerTest.java} | 10 +- ...Test.java => OracleEscapeHandlerTest.java} | 10 +- ....java => PostgresqlEscapeHandlerTest.java} | 10 +- .../services/io.seata.sqlparser.EscapeHandler | 1 + .../io.seata.sqlparser.KeywordChecker | 1 - .../mysql/AntlrMySQLInsertRecognizer.java | 2 +- .../mysql/AntlrMySQLUpdateRecognizer.java | 2 +- .../io/seata/sqlparser/EscapeHandler.java | 148 ++++++++++++++ ...Factory.java => EscapeHandlerFactory.java} | 10 +- .../seata/sqlparser/SQLInsertRecognizer.java | 2 +- .../seata/sqlparser/SQLUpdateRecognizer.java | 2 +- .../io/seata/sqlparser/util/ColumnUtils.java | 185 ++---------------- .../druid/mysql/MySQLInsertRecognizer.java | 2 +- .../druid/mysql/MySQLUpdateRecognizer.java | 2 +- .../druid/oracle/OracleInsertRecognizer.java | 2 +- .../druid/oracle/OracleUpdateRecognizer.java | 2 +- .../PostgresqlInsertRecognizer.java | 2 +- .../PostgresqlUpdateRecognizer.java | 2 +- .../druid/MySQLInsertRecognizerTest.java | 11 -- .../druid/MySQLUpdateRecognizerTest.java | 11 -- 35 files changed, 425 insertions(+), 292 deletions(-) rename sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/KeywordChecker.java => rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mariadb/MariadbEscapeHandler.java (50%) rename rm-datasource/src/main/java/io/seata/rm/datasource/{undo/mysql/keyword/MySQLKeywordChecker.java => sql/handler/mysql/MySQLEscapeHandler.java} (97%) rename rm-datasource/src/main/java/io/seata/rm/datasource/{undo/oracle/keyword/OracleKeywordChecker.java => sql/handler/oracle/OracleEscapeHandler.java} (91%) rename rm-datasource/src/main/java/io/seata/rm/datasource/{undo/postgresql/keyword/PostgresqlKeywordChecker.java => sql/handler/postgresql/PostgresqlEscapeHandler.java} (91%) create mode 100644 rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.EscapeHandler delete mode 100644 rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.KeywordChecker create mode 100644 rm-datasource/src/test/java/io/seata/rm/datasource/sql/handler/EscapeHandlerTest.java rename rm-datasource/src/test/java/io/seata/rm/datasource/undo/{KeywordCheckerFactoryTest.java => EscapeHandlerFactoryTest.java} (72%) rename rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/{H2KeywordChecker.java => H2EscapeHandler.java} (86%) rename rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/{MySQLKeywordCheckerTest.java => MySQLEscapeHandlerTest.java} (96%) rename rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/{OracleKeywordCheckerTest.java => OracleEscapeHandlerTest.java} (75%) rename rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/{PostgresqlKeywordCheckerTest.java => PostgresqlEscapeHandlerTest.java} (75%) create mode 100644 rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.EscapeHandler delete mode 100644 rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.KeywordChecker create mode 100644 sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java rename sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/{KeywordCheckerFactory.java => EscapeHandlerFactory.java} (73%) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 8930e4c88d8..2b7e932cbba 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -55,6 +55,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5537](https://github.com/seata/seata/pull/5537)] optimize transaction log on client side - [[#5541](https://github.com/seata/seata/pull/5541)] optimize server log output - [[#5548](https://github.com/seata/seata/pull/5548)] update expire gpg key and publish workflow +- [[#5646](https://github.com/seata/seata/pull/5646)] refactor ColumnUtils and EscapeHandler ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 62a471193d2..1405462d5d1 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -55,6 +55,7 @@ - [[#5537](https://github.com/seata/seata/pull/5537)] 优化客户侧事务日志 - [[#5541](https://github.com/seata/seata/pull/5541)] 优化Server日志输出 - [[#5548](https://github.com/seata/seata/pull/5548)] 优化 gpg key 和 发布流水线 +- [[#5646](https://github.com/seata/seata/pull/5646)] 重构 ColumnUtils 和 EscapeHandler ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java index fce287d97db..a1cc2e1c175 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java @@ -496,7 +496,7 @@ protected TableRecords buildTableRecords(Map> pkValuesMap) List insertColumns = recognizer.getInsertColumns(); if (ONLY_CARE_UPDATE_COLUMNS && CollectionUtils.isNotEmpty(insertColumns)) { Set columns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - columns.addAll(recognizer.getInsertColumnsIsSimplified()); + columns.addAll(recognizer.getInsertColumnsUnEscape()); columns.addAll(pkColumnNameList); for (String columnName : columns) { selectSQLJoin.add(columnName); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java index 0f0c59c63af..6103a669ef6 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java @@ -88,7 +88,7 @@ protected TableRecords beforeImage() throws SQLException { throw new NotSupportYetException("Multi update SQL with orderBy condition is not support yet !"); } - List updateColumns = sqlUpdateRecognizer.getUpdateColumnsIsSimplified(); + List updateColumns = sqlUpdateRecognizer.getUpdateColumnsUnEscape(); updateColumnsSet.addAll(updateColumns); if (noWhereCondition) { continue; @@ -155,7 +155,7 @@ private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage) for (SQLRecognizer recognizer : sqlRecognizers) { sqlRecognizer = recognizer; SQLUpdateRecognizer sqlUpdateRecognizer = (SQLUpdateRecognizer) sqlRecognizer; - updateColumnsSet.addAll(sqlUpdateRecognizer.getUpdateColumnsIsSimplified()); + updateColumnsSet.addAll(sqlUpdateRecognizer.getUpdateColumnsUnEscape()); } StringBuilder prefix = new StringBuilder("SELECT "); String suffix = " FROM " + getFromTableInSQL() + " WHERE " + SqlGenerateUtils.buildWhereConditionByPKs(tableMeta.getPrimaryKeyOnlyName(), beforeImage.pkRows().size(), getDbType()); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java index 2200c771206..8607b99a1d7 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java @@ -91,7 +91,7 @@ private String buildBeforeImageSQL(TableMeta tableMeta, ArrayList> } suffix.append(" FOR UPDATE"); StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); - List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified()); + List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape()); needUpdateColumns.forEach(selectSQLJoin::add); return selectSQLJoin.toString(); } @@ -119,7 +119,7 @@ private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage) String suffix = " FROM " + getFromTableInSQL() + " WHERE " + whereSql; StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer; - List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified()); + List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape()); needUpdateColumns.forEach(selectSQLJoiner::add); return selectSQLJoiner.toString(); } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/KeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mariadb/MariadbEscapeHandler.java similarity index 50% rename from sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/KeywordChecker.java rename to rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mariadb/MariadbEscapeHandler.java index 2972319e90e..a9f3ada884c 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/KeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mariadb/MariadbEscapeHandler.java @@ -13,28 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.sqlparser; +package io.seata.rm.datasource.sql.handler.mariadb; + +import io.seata.common.loader.LoadLevel; +import io.seata.rm.datasource.sql.handler.mysql.MySQLEscapeHandler; +import io.seata.sqlparser.util.JdbcConstants; /** - * The interface Keyword checker. + * The type Mariadb escape handler. * - * @author Wu + * @author slievrly */ -public interface KeywordChecker { - /** - * check whether given field name and table name use keywords - * - * @param fieldOrTableName the field or table name - * @return boolean - */ - boolean check(String fieldOrTableName); - - - /** - * check whether given field or table name use keywords. the method has database special logic. - * @param fieldOrTableName the field or table name - * @return true: need to escape. false: no need to escape. - */ - boolean checkEscape(String fieldOrTableName); - +@LoadLevel(name = JdbcConstants.MARIADB) +public class MariadbEscapeHandler extends MySQLEscapeHandler { } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mysql/MySQLEscapeHandler.java similarity index 97% rename from rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java rename to rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mysql/MySQLEscapeHandler.java index f060dce5c1e..02ea2ff7291 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mysql/MySQLEscapeHandler.java @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.undo.mysql.keyword; +package io.seata.rm.datasource.sql.handler.mysql; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; import io.seata.common.loader.LoadLevel; -import io.seata.sqlparser.KeywordChecker; +import io.seata.common.util.StringUtils; +import io.seata.sqlparser.EscapeHandler; import io.seata.sqlparser.util.JdbcConstants; /** @@ -29,7 +30,7 @@ * @author xingfudeshi@gmail.com */ @LoadLevel(name = JdbcConstants.MYSQL) -public class MySQLKeywordChecker implements KeywordChecker { +public class MySQLEscapeHandler implements EscapeHandler { private Set keywordSet = Arrays.stream(MySQLKeyword.values()).map(MySQLKeyword::name).collect(Collectors.toSet()); @@ -1101,7 +1102,7 @@ private enum MySQLKeyword { @Override - public boolean check(String fieldOrTableName) { + public boolean checkIfKeyWords(String fieldOrTableName) { if (keywordSet.contains(fieldOrTableName)) { return true; } @@ -1113,8 +1114,19 @@ public boolean check(String fieldOrTableName) { } @Override - public boolean checkEscape(String fieldOrTableName) { - return check(fieldOrTableName); + public boolean checkIfNeedEscape(String fieldOrTableName) { + if (StringUtils.isBlank(fieldOrTableName)) { + return false; + } + fieldOrTableName = fieldOrTableName.trim(); + if (containsEscape(fieldOrTableName)) { + return false; + } + return checkIfKeyWords(fieldOrTableName); } + @Override + public char getEscapeSymbol() { + return '`'; + } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/oracle/OracleEscapeHandler.java similarity index 91% rename from rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordChecker.java rename to rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/oracle/OracleEscapeHandler.java index 22b4dc6febb..0fb5358e206 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/oracle/OracleEscapeHandler.java @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.undo.oracle.keyword; +package io.seata.rm.datasource.sql.handler.oracle; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; import io.seata.common.loader.LoadLevel; -import io.seata.sqlparser.KeywordChecker; +import io.seata.common.util.StringUtils; +import io.seata.sqlparser.EscapeHandler; import io.seata.sqlparser.util.JdbcConstants; /** @@ -29,7 +30,7 @@ * @author ccg */ @LoadLevel(name = JdbcConstants.ORACLE) -public class OracleKeywordChecker implements KeywordChecker { +public class OracleEscapeHandler implements EscapeHandler { private Set keywordSet = Arrays.stream(OracleKeyword.values()).map(OracleKeyword::name).collect(Collectors.toSet()); @@ -488,7 +489,7 @@ private enum OracleKeyword { } @Override - public boolean check(String fieldOrTableName) { + public boolean checkIfKeyWords(String fieldOrTableName) { if (keywordSet.contains(fieldOrTableName)) { return true; } @@ -499,13 +500,33 @@ public boolean check(String fieldOrTableName) { } + @Override - public boolean checkEscape(String fieldOrTableName) { - boolean check = check(fieldOrTableName); + public boolean checkIfNeedEscape(String fieldOrTableName) { + if (StringUtils.isBlank(fieldOrTableName)) { + return false; + } + fieldOrTableName = fieldOrTableName.trim(); + if (containsEscape(fieldOrTableName)) { + return false; + } + boolean isKeyWord = checkIfKeyWords(fieldOrTableName); + if (isKeyWord) { + return true; + } // oracle // we are recommend table name and column name must uppercase. - // if exists full uppercase, the table name or column name does't bundle escape symbol. - if (!check && isUppercase(fieldOrTableName)) { + // if exists full uppercase, the table name or column name doesn't bundle escape symbol. + //create\read table TABLE "table" "TABLE" + // + //table √ √ × √ + // + //TABLE √ √ × √ + // + //"table" × × √ × + // + //"TABLE" √ √ × √ + if (isUppercase(fieldOrTableName)) { return false; } return true; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/postgresql/PostgresqlEscapeHandler.java similarity index 91% rename from rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordChecker.java rename to rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/postgresql/PostgresqlEscapeHandler.java index f35f4ffa114..3cd06a3f875 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/postgresql/PostgresqlEscapeHandler.java @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.undo.postgresql.keyword; +package io.seata.rm.datasource.sql.handler.postgresql; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; import io.seata.common.loader.LoadLevel; -import io.seata.sqlparser.KeywordChecker; +import io.seata.common.util.StringUtils; +import io.seata.sqlparser.EscapeHandler; import io.seata.sqlparser.util.JdbcConstants; /** @@ -29,10 +30,10 @@ * @author japsercloud */ @LoadLevel(name = JdbcConstants.POSTGRESQL) -public class PostgresqlKeywordChecker implements KeywordChecker { +public class PostgresqlEscapeHandler implements EscapeHandler { - private Set keywordSet = Arrays.stream(PostgresqlKeywordChecker.PostgresqlKeyword.values()) - .map(PostgresqlKeywordChecker.PostgresqlKeyword::name).collect(Collectors.toSet()); + private Set keywordSet = Arrays.stream(PostgresqlEscapeHandler.PostgresqlKeyword.values()) + .map(PostgresqlEscapeHandler.PostgresqlKeyword::name).collect(Collectors.toSet()); /** * postgresql keyword @@ -357,7 +358,7 @@ private enum PostgresqlKeyword { } @Override - public boolean check(String fieldOrTableName) { + public boolean checkIfKeyWords(String fieldOrTableName) { if (keywordSet.contains(fieldOrTableName)) { return true; } @@ -369,8 +370,15 @@ public boolean check(String fieldOrTableName) { } @Override - public boolean checkEscape(String fieldOrTableName) { - boolean check = check(fieldOrTableName); + public boolean checkIfNeedEscape(String fieldOrTableName) { + if (StringUtils.isBlank(fieldOrTableName)) { + return false; + } + fieldOrTableName = fieldOrTableName.trim(); + if (containsEscape(fieldOrTableName)) { + return false; + } + boolean check = checkIfKeyWords(fieldOrTableName); if (!check && !containsUppercase(fieldOrTableName)) { // postgresql // we are recommend table name and column name must lowercase. diff --git a/rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.EscapeHandler b/rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.EscapeHandler new file mode 100644 index 00000000000..137aeea649e --- /dev/null +++ b/rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.EscapeHandler @@ -0,0 +1,4 @@ +io.seata.rm.datasource.sql.handler.oracle.OracleEscapeHandler +io.seata.rm.datasource.sql.handler.mysql.MySQLEscapeHandler +io.seata.rm.datasource.sql.handler.postgresql.PostgresqlEscapeHandler +io.seata.rm.datasource.sql.handler.mariadb.MariadbEscapeHandler \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.KeywordChecker b/rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.KeywordChecker deleted file mode 100644 index 6d674d92bc4..00000000000 --- a/rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.KeywordChecker +++ /dev/null @@ -1,3 +0,0 @@ -io.seata.rm.datasource.undo.oracle.keyword.OracleKeywordChecker -io.seata.rm.datasource.undo.mysql.keyword.MySQLKeywordChecker -io.seata.rm.datasource.undo.postgresql.keyword.PostgresqlKeywordChecker \ No newline at end of file diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java index 617a63dc15d..d5949840699 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java @@ -33,51 +33,51 @@ public void test_delEscape_byEscape() throws Exception { List cols = new ArrayList<>(); cols.add("`id`"); cols.add("name"); - cols = ColumnUtils.delEscape(cols, ColumnUtils.Escape.MYSQL); + cols = ColumnUtils.delEscape(cols, JdbcConstants.MYSQL); Assertions.assertEquals("id", cols.get(0)); Assertions.assertEquals("name", cols.get(1)); List cols2 = new ArrayList<>(); cols2.add("\"id\""); - cols2 = ColumnUtils.delEscape(cols2, ColumnUtils.Escape.STANDARD); + cols2 = ColumnUtils.delEscape(cols2, JdbcConstants.ORACLE); Assertions.assertEquals("id", cols2.get(0)); List cols3 = new ArrayList<>(); cols3.add("\"scheme\".\"id\""); - cols3 = ColumnUtils.delEscape(cols3, ColumnUtils.Escape.STANDARD); + cols3 = ColumnUtils.delEscape(cols3, JdbcConstants.ORACLE); Assertions.assertEquals("scheme.id", cols3.get(0)); List cols4 = new ArrayList<>(); cols4.add("`scheme`.`id`"); - cols4 = ColumnUtils.delEscape(cols4, ColumnUtils.Escape.MYSQL); + cols4 = ColumnUtils.delEscape(cols4, JdbcConstants.MYSQL); Assertions.assertEquals("scheme.id", cols4.get(0)); List cols5 = new ArrayList<>(); cols5.add("\"scheme\".id"); - cols5 = ColumnUtils.delEscape(cols5, ColumnUtils.Escape.STANDARD); + cols5 = ColumnUtils.delEscape(cols5, JdbcConstants.ORACLE); Assertions.assertEquals("scheme.id", cols5.get(0)); List cols6 = new ArrayList<>(); cols6.add("\"tab\"\"le\""); - cols6 = ColumnUtils.delEscape(cols6, ColumnUtils.Escape.STANDARD); + cols6 = ColumnUtils.delEscape(cols6, JdbcConstants.ORACLE); Assertions.assertEquals("tab\"\"le", cols6.get(0)); List cols7 = new ArrayList<>(); cols7.add("scheme.\"id\""); - cols7 = ColumnUtils.delEscape(cols7, ColumnUtils.Escape.STANDARD); + cols7 = ColumnUtils.delEscape(cols7, JdbcConstants.ORACLE); Assertions.assertEquals("scheme.id", cols7.get(0)); List cols8 = new ArrayList<>(); cols8.add("`scheme`.id"); - cols8 = ColumnUtils.delEscape(cols8, ColumnUtils.Escape.MYSQL); - Assertions.assertEquals("scheme.id", cols8.get(0)); + cols8 = ColumnUtils.delEscape(cols8, JdbcConstants.ORACLE); + Assertions.assertEquals("`scheme`.id", cols8.get(0)); List cols9 = new ArrayList<>(); cols9.add("scheme.`id`"); - cols9 = ColumnUtils.delEscape(cols9, ColumnUtils.Escape.MYSQL); + cols9 = ColumnUtils.delEscape(cols9, JdbcConstants.MYSQL); Assertions.assertEquals("scheme.id", cols9.get(0)); - Assertions.assertNull(ColumnUtils.delEscape((String) null, ColumnUtils.Escape.MYSQL)); + Assertions.assertNull(ColumnUtils.delEscape((String) null, JdbcConstants.MYSQL)); } @Test diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/handler/EscapeHandlerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/handler/EscapeHandlerTest.java new file mode 100644 index 00000000000..90ee33a355c --- /dev/null +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/handler/EscapeHandlerTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 1999-2019 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.rm.datasource.sql.handler; + +import java.util.List; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; + +import io.seata.sqlparser.druid.mysql.MySQLInsertRecognizer; +import io.seata.sqlparser.druid.mysql.MySQLUpdateRecognizer; +import io.seata.sqlparser.druid.oracle.OracleInsertRecognizer; +import io.seata.sqlparser.druid.oracle.OracleUpdateRecognizer; +import io.seata.sqlparser.druid.postgresql.PostgresqlInsertRecognizer; +import io.seata.sqlparser.druid.postgresql.PostgresqlUpdateRecognizer; +import io.seata.sqlparser.util.JdbcConstants; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * The type Escape handler test. + * + * @author slievrly + */ +public class EscapeHandlerTest { + /** + * Test update columns escape. + */ + @Test + public void testUpdateColumnsEscape() { + //mysql + String sql1 = "update t set `a` = 1, `b` = 2, `c` = 3"; + List astsMysql = SQLUtils.parseStatements(sql1, JdbcConstants.MYSQL); + MySQLUpdateRecognizer regMysql = new MySQLUpdateRecognizer(sql1, astsMysql.get(0)); + List updateColMysql = regMysql.getUpdateColumnsUnEscape(); + for (String updateColumn : updateColMysql) { + Assertions.assertFalse(updateColumn.contains("`")); + } + updateColMysql = regMysql.getUpdateColumns(); + for (String updateColumn : updateColMysql) { + Assertions.assertTrue(updateColumn.contains("`")); + } + + //oracle + String sql2 = "update t set \"a\" = 1, \"b\" = 2, \"c\" = 3"; + List astsOracle = SQLUtils.parseStatements(sql2, JdbcConstants.ORACLE); + OracleUpdateRecognizer regOracle = new OracleUpdateRecognizer(sql2, astsOracle.get(0)); + List updateColOracle = regOracle.getUpdateColumnsUnEscape(); + for (String updateColumn : updateColOracle) { + Assertions.assertFalse(updateColumn.contains("\"")); + } + updateColOracle = regOracle.getUpdateColumns(); + for (String updateColumn : updateColOracle) { + Assertions.assertTrue(updateColumn.contains("\"")); + } + + //postgresql + String sql3 = "update t set \"a\" = 1, \"b\" = 2, \"c\" = 3"; + List astsPgsql = SQLUtils.parseStatements(sql2, JdbcConstants.POSTGRESQL); + PostgresqlUpdateRecognizer regPgsql = new PostgresqlUpdateRecognizer(sql3, astsPgsql.get(0)); + List updateColPgsql = regPgsql.getUpdateColumnsUnEscape(); + for (String updateColumn : updateColPgsql) { + Assertions.assertFalse(updateColumn.contains("\"")); + } + updateColPgsql = regPgsql.getUpdateColumns(); + for (String updateColumn : updateColPgsql) { + Assertions.assertTrue(updateColumn.contains("\"")); + } + + } + + /** + * Test insert columns escape. + */ + @Test + public void testInsertColumnsEscape() { + String sql = "insert into t(`id`, `no`, `name`, `age`) values (1, 'no001', 'aaa', '20')"; + List asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + MySQLInsertRecognizer recognizer = new MySQLInsertRecognizer(sql, asts.get(0)); + List insertColumns = recognizer.getInsertColumnsUnEscape(); + for (String insertColumn : insertColumns) { + Assertions.assertFalse(insertColumn.contains("`")); + } + insertColumns = recognizer.getInsertColumns(); + for (String insertColumn : insertColumns) { + Assertions.assertTrue(insertColumn.contains("`")); + } + + //oracle + String sql2 = "insert into t(\"id\", \"no\", \"name\", \"age\") values (1, 'no001', 'aaa', '20')"; + List astsOracle = SQLUtils.parseStatements(sql2, JdbcConstants.ORACLE); + OracleInsertRecognizer regOracle = new OracleInsertRecognizer(sql2, astsOracle.get(0)); + List insertColOracle = regOracle.getInsertColumnsUnEscape(); + for (String insertCol : insertColOracle) { + Assertions.assertFalse(insertCol.contains("\"")); + } + insertColOracle = regOracle.getInsertColumns(); + for (String insertCol : insertColOracle) { + Assertions.assertTrue(insertCol.contains("\"")); + } + + //postgresql + String sql3 = "insert into t(\"id\", \"no\", \"name\", \"age\") values (1, 'no001', 'aaa', '20')"; + List astsPgsql = SQLUtils.parseStatements(sql2, JdbcConstants.POSTGRESQL); + PostgresqlInsertRecognizer regPgsql = new PostgresqlInsertRecognizer(sql3, astsPgsql.get(0)); + List insertColPgsql = regPgsql.getInsertColumnsUnEscape(); + for (String insertCol : insertColPgsql) { + Assertions.assertFalse(insertCol.contains("\"")); + } + insertColPgsql = regPgsql.getInsertColumns(); + for (String insertCol : insertColPgsql) { + Assertions.assertTrue(insertCol.contains("\"")); + } + } +} diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/KeywordCheckerFactoryTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/EscapeHandlerFactoryTest.java similarity index 72% rename from rm-datasource/src/test/java/io/seata/rm/datasource/undo/KeywordCheckerFactoryTest.java rename to rm-datasource/src/test/java/io/seata/rm/datasource/undo/EscapeHandlerFactoryTest.java index 8747af451fd..96ca13c4063 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/KeywordCheckerFactoryTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/EscapeHandlerFactoryTest.java @@ -16,20 +16,20 @@ package io.seata.rm.datasource.undo; import io.seata.common.loader.EnhancedServiceNotFoundException; -import io.seata.sqlparser.KeywordCheckerFactory; +import io.seata.sqlparser.EscapeHandlerFactory; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * @author will */ -public class KeywordCheckerFactoryTest { +public class EscapeHandlerFactoryTest { @Test - public void testKeywordCheckerFacotry() { - KeywordCheckerFactory keywordCheckerFactory = new KeywordCheckerFactory(); - Assertions.assertNotNull(keywordCheckerFactory); + public void testEscapeHandlerFactoryTest() { + EscapeHandlerFactory escapeHandlerFactory = new EscapeHandlerFactory(); + Assertions.assertNotNull(escapeHandlerFactory); - Assertions.assertThrows(EnhancedServiceNotFoundException.class, () -> KeywordCheckerFactory.getKeywordChecker("unknow")); + Assertions.assertThrows(EnhancedServiceNotFoundException.class, () -> EscapeHandlerFactory.getEscapeHandler("unknow")); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2KeywordChecker.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2EscapeHandler.java similarity index 86% rename from rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2KeywordChecker.java rename to rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2EscapeHandler.java index 46f19169652..aae2da3fcff 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2KeywordChecker.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2EscapeHandler.java @@ -16,12 +16,12 @@ package io.seata.rm.datasource.undo.h2.keyword; import io.seata.common.loader.LoadLevel; -import io.seata.rm.datasource.undo.mysql.keyword.MySQLKeywordChecker; +import io.seata.rm.datasource.sql.handler.mysql.MySQLEscapeHandler; import io.seata.sqlparser.util.JdbcConstants; /** * @author JerryYin */ @LoadLevel(name = JdbcConstants.H2) -public class H2KeywordChecker extends MySQLKeywordChecker { +public class H2EscapeHandler extends MySQLEscapeHandler { } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLEscapeHandlerTest.java similarity index 96% rename from rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java rename to rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLEscapeHandlerTest.java index 093520d7f72..3d48a0582e1 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLEscapeHandlerTest.java @@ -17,8 +17,8 @@ import java.sql.Types; -import io.seata.sqlparser.KeywordChecker; -import io.seata.sqlparser.KeywordCheckerFactory; +import io.seata.sqlparser.EscapeHandler; +import io.seata.sqlparser.EscapeHandlerFactory; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.rm.datasource.undo.mysql.MySQLUndoDeleteExecutor; import io.seata.rm.datasource.undo.mysql.MySQLUndoInsertExecutor; @@ -39,15 +39,15 @@ * * @author Wu */ -public class MySQLKeywordCheckerTest { +public class MySQLEscapeHandlerTest { /** * Test check */ @Test public void testCheck() { - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL); - Assertions.assertTrue(keywordChecker.check("desc")); + EscapeHandler escapeHandler = EscapeHandlerFactory.getEscapeHandler(JdbcConstants.MYSQL); + Assertions.assertTrue(escapeHandler.checkIfKeyWords("desc")); } /** diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleEscapeHandlerTest.java similarity index 75% rename from rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordCheckerTest.java rename to rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleEscapeHandlerTest.java index 2d00d1df907..a11c20cc8f9 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleEscapeHandlerTest.java @@ -18,19 +18,19 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import io.seata.sqlparser.KeywordChecker; -import io.seata.sqlparser.KeywordCheckerFactory; +import io.seata.sqlparser.EscapeHandler; +import io.seata.sqlparser.EscapeHandlerFactory; import io.seata.sqlparser.util.JdbcConstants; /** * @author will */ -public class OracleKeywordCheckerTest { +public class OracleEscapeHandlerTest { @Test public void testOracleKeywordChecker() { - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.ORACLE); - Assertions.assertNotNull(keywordChecker); + EscapeHandler escapeHandler = EscapeHandlerFactory.getEscapeHandler(JdbcConstants.ORACLE); + Assertions.assertNotNull(escapeHandler); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlEscapeHandlerTest.java similarity index 75% rename from rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordCheckerTest.java rename to rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlEscapeHandlerTest.java index 41b2959027c..c4626255e72 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlEscapeHandlerTest.java @@ -18,19 +18,19 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import io.seata.sqlparser.KeywordChecker; -import io.seata.sqlparser.KeywordCheckerFactory; +import io.seata.sqlparser.EscapeHandler; +import io.seata.sqlparser.EscapeHandlerFactory; import io.seata.sqlparser.util.JdbcConstants; /** * @author will */ -public class PostgresqlKeywordCheckerTest { +public class PostgresqlEscapeHandlerTest { @Test public void testOracleKeywordChecker() { - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.POSTGRESQL); - Assertions.assertNotNull(keywordChecker); + EscapeHandler escapeHandler = EscapeHandlerFactory.getEscapeHandler(JdbcConstants.POSTGRESQL); + Assertions.assertNotNull(escapeHandler); } } diff --git a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.EscapeHandler b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.EscapeHandler new file mode 100644 index 00000000000..1daa6248dfd --- /dev/null +++ b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.EscapeHandler @@ -0,0 +1 @@ +io.seata.rm.datasource.undo.h2.keyword.H2EscapeHandler \ No newline at end of file diff --git a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.KeywordChecker b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.KeywordChecker deleted file mode 100644 index de389691db1..00000000000 --- a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.KeywordChecker +++ /dev/null @@ -1 +0,0 @@ -io.seata.rm.datasource.undo.h2.keyword.H2KeywordChecker \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLInsertRecognizer.java b/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLInsertRecognizer.java index 894e67368a7..14933644880 100644 --- a/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLInsertRecognizer.java @@ -109,7 +109,7 @@ public List getDuplicateKeyUpdate() { } @Override - public List getInsertColumnsIsSimplified() { + public List getInsertColumnsUnEscape() { List insertColumns = getInsertColumns(); return ColumnUtils.delEscape(insertColumns, JdbcConstants.MYSQL); } diff --git a/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java index 55d61a5671b..0f974f9245a 100644 --- a/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-antlr/src/main/java/io/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java @@ -75,7 +75,7 @@ public List getUpdateValues() { } @Override - public List getUpdateColumnsIsSimplified() { + public List getUpdateColumnsUnEscape() { List updateColumns = getUpdateColumns(); return ColumnUtils.delEscape(updateColumns, JdbcConstants.MYSQL); } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java new file mode 100644 index 00000000000..5714985f1bd --- /dev/null +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java @@ -0,0 +1,148 @@ +/* + * Copyright 1999-2019 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.sqlparser; + +import io.seata.common.util.StringUtils; + +/** + * The interface Keyword checker. + * + * @author Wu + */ +public interface EscapeHandler { + + String DOT = "."; + /** + * check whether given field name and table name use keywords + * + * @param fieldOrTableName the field or table name + * @return boolean + */ + boolean checkIfKeyWords(String fieldOrTableName); + + + /** + * check whether given field or table name use keywords. the method has database special logic. + * @param fieldOrTableName the field or table name + * @return true: need to escape. false: no need to escape. + */ + boolean checkIfNeedEscape(String fieldOrTableName); + + default char getEscapeSymbol() { + return '"'; + } + + /** + * check fieldOrTableName if contains escape + * @param fieldOrTableName + * @return true if contains,otherwise return false + */ + default boolean containsEscape(String fieldOrTableName) { + fieldOrTableName = fieldOrTableName.trim(); + char escapeSymbol = getEscapeSymbol(); + if (fieldOrTableName.charAt(0) == escapeSymbol && fieldOrTableName.charAt(fieldOrTableName.length() - 1) == escapeSymbol) { + return true; + } + return false; + } + + /** + * add escape if colName is keywords + * @param colName + * @return + */ + default String addColNameEscape(String colName) { + boolean needEscape = checkIfNeedEscape(colName); + if (!needEscape) { + return colName; + } + char escapeChar = getEscapeSymbol(); + if (colName.contains(DOT)) { + // like "scheme".id `scheme`.id + String str = escapeChar + DOT; + int dotIndex = colName.indexOf(str); + if (dotIndex > -1) { + return new StringBuilder().append(colName.substring(0, dotIndex + str.length())).append(escapeChar) + .append(colName.substring(dotIndex + str.length())).append(escapeChar).toString(); + } + // like scheme."id" scheme.`id` + str = DOT + escapeChar; + dotIndex = colName.indexOf(str); + if (dotIndex > -1) { + return new StringBuilder().append(escapeChar).append(colName.substring(0, dotIndex)).append(escapeChar) + .append(colName.substring(dotIndex)).toString(); + } + + str = DOT; + dotIndex = colName.indexOf(str); + if (dotIndex > -1) { + return new StringBuilder().append(escapeChar).append(colName.substring(0, dotIndex)).append(escapeChar) + .append(DOT).append(escapeChar).append(colName.substring(dotIndex + str.length())).append( + escapeChar).toString(); + } + } + + char[] buf = new char[colName.length() + 2]; + buf[0] = escapeChar; + buf[buf.length - 1] = escapeChar; + + colName.getChars(0, colName.length(), buf, 1); + + return new String(buf).intern(); + + } + + /** + * + * https://db.apache.org/derby/docs/10.1/ref/crefsqlj1003454.html + * https://docs.oracle.com/javadb/10.8.3.0/ref/crefsqlj1003454.html + * https://www.informit.com/articles/article.aspx?p=2036581&seqNum=2 + * @param colName + * @return + */ + default String delColNameEscape(String colName) { + if (StringUtils.isBlank(colName)) { + return colName; + } + char escapeChar = getEscapeSymbol(); + if (colName.charAt(0) == escapeChar && colName.charAt(colName.length() - 1) == escapeChar) { + // like "scheme"."id" `scheme`.`id` + String str = escapeChar + DOT + escapeChar; + int index = colName.indexOf(str); + if (index > -1) { + return colName.substring(1, index) + DOT + colName.substring(index + str.length(), + colName.length() - 1); + } + return colName.substring(1, colName.length() - 1); + } else { + // like "scheme".id `scheme`.id + String str = escapeChar + DOT; + int index = colName.indexOf(str); + if (index > -1 && colName.charAt(0) == escapeChar) { + return colName.substring(1, index) + DOT + colName.substring(index + str.length()); + } + // like scheme."id" scheme.`id` + str = DOT + escapeChar; + index = colName.indexOf(str); + if (index > -1 && colName.charAt(colName.length() - 1) == escapeChar) { + return colName.substring(0, index) + DOT + colName.substring(index + str.length(), + colName.length() - 1); + } + } + return colName; + } + +} diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/KeywordCheckerFactory.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandlerFactory.java similarity index 73% rename from sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/KeywordCheckerFactory.java rename to sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandlerFactory.java index 9db5eaa0f98..14e161701f7 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/KeywordCheckerFactory.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandlerFactory.java @@ -26,9 +26,9 @@ * * @author Wu */ -public class KeywordCheckerFactory { +public class EscapeHandlerFactory { - private static final Map KEYWORD_CHECKER_MAP = new ConcurrentHashMap<>(); + private static final Map ESCAPE_HANDLER_MAP = new ConcurrentHashMap<>(); /** * get keyword checker @@ -36,8 +36,8 @@ public class KeywordCheckerFactory { * @param dbType the db type * @return keyword checker */ - public static KeywordChecker getKeywordChecker(String dbType) { - return CollectionUtils.computeIfAbsent(KEYWORD_CHECKER_MAP, dbType, - key -> EnhancedServiceLoader.load(KeywordChecker.class, dbType)); + public static EscapeHandler getEscapeHandler(String dbType) { + return CollectionUtils.computeIfAbsent(ESCAPE_HANDLER_MAP, dbType, + key -> EnhancedServiceLoader.load(EscapeHandler.class, dbType)); } } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java index c9a6d43ff4c..aff1f78f4ec 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java @@ -65,5 +65,5 @@ public interface SQLInsertRecognizer extends SQLRecognizer { * * @return (`a`, `b`, `c`) -> (a, b, c) */ - List getInsertColumnsIsSimplified(); + List getInsertColumnsUnEscape(); } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLUpdateRecognizer.java index fa97f0416ff..54cce0ebedd 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLUpdateRecognizer.java @@ -54,5 +54,5 @@ default String getTableAlias(String tableName) { * * @return (`a`, `b`, `c`) -> (a, b, c) */ - List getUpdateColumnsIsSimplified(); + List getUpdateColumnsUnEscape(); } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java index c979c2fa627..237badce4f3 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java @@ -15,14 +15,14 @@ */ package io.seata.sqlparser.util; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.sqlparser.KeywordChecker; -import io.seata.sqlparser.KeywordCheckerFactory; - import java.util.ArrayList; import java.util.List; +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringUtils; +import io.seata.sqlparser.EscapeHandler; +import io.seata.sqlparser.EscapeHandlerFactory; + /** * column utils * @@ -30,30 +30,6 @@ */ public final class ColumnUtils { - private static final String DOT = "."; - - /** - * The escape - */ - public enum Escape { - /** - * standard escape - */ - STANDARD('"'), - /** - * mysql series escape - */ - MYSQL('`'); - /** - * The Value. - */ - public final char value; - - Escape(char value) { - this.value = value; - } - } - /** * del escape by db type * @@ -62,87 +38,29 @@ public enum Escape { * @return list */ public static List delEscape(List cols, String dbType) { - // sql standard - // https://db.apache.org/derby/docs/10.1/ref/crefsqlj1003454.html - // https://docs.oracle.com/javadb/10.8.3.0/ref/crefsqlj1003454.html - // https://www.informit.com/articles/article.aspx?p=2036581&seqNum=2 - List newCols = delEscape(cols, Escape.STANDARD); - if (isMysqlSeries(dbType)) { - newCols = delEscape(newCols, Escape.MYSQL); - } - return newCols; - } - - /** - * del escape - * - * @param cols the cols - * @param escape the escape - * @return delete the column list element left and right escape. - */ - public static List delEscape(List cols, Escape escape) { if (CollectionUtils.isEmpty(cols)) { return cols; } List newCols = new ArrayList<>(cols.size()); for (int i = 0, len = cols.size(); i < len; i++) { String col = cols.get(i); - col = delEscape(col, escape); + col = delEscape(col, dbType); newCols.add(col); } return newCols; } - /** - * del escape by db type - * - * @param colName the column name - * @param dbType the db type - * @return string string - */ - public static String delEscape(String colName, String dbType) { - String newColName = delEscape(colName, Escape.STANDARD); - if (isMysqlSeries(dbType)) { - newColName = delEscape(newColName, Escape.MYSQL); - } - return newColName; - } /** * del escape by escape * * @param colName the column name - * @param escape the escape + * @param dbType the dbType * @return string string */ - public static String delEscape(String colName, Escape escape) { - if (colName == null || colName.isEmpty()) { - return colName; - } - - if (colName.charAt(0) == escape.value && colName.charAt(colName.length() - 1) == escape.value) { - // like "scheme"."id" `scheme`.`id` - String str = escape.value + DOT + escape.value; - int index = colName.indexOf(str); - if (index > -1) { - return colName.substring(1, index) + DOT + colName.substring(index + str.length(), colName.length() - 1); - } - return colName.substring(1, colName.length() - 1); - } else { - // like "scheme".id `scheme`.id - String str = escape.value + DOT; - int index = colName.indexOf(str); - if (index > -1 && colName.charAt(0) == escape.value) { - return colName.substring(1, index) + DOT + colName.substring(index + str.length()); - } - // like scheme."id" scheme.`id` - str = DOT + escape.value; - index = colName.indexOf(str); - if (index > -1 && colName.charAt(colName.length() - 1) == escape.value) { - return colName.substring(0, index) + DOT + colName.substring(index + str.length(), colName.length() - 1); - } - } - return colName; + public static String delEscape(String colName, String dbType) { + EscapeHandler escapeHandler = EscapeHandlerFactory.getEscapeHandler(dbType); + return escapeHandler.delColNameEscape(colName); } /** @@ -173,93 +91,20 @@ public static List addEscape(List cols, String dbType) { return newCols; } - /** - * if necessary, add escape by db type - * - * @param colName the column name - * @param dbType the db type - * @return the colName left and right add escape - */ - public static String addEscape(String colName, String dbType) { - if (isMysqlSeries(dbType)) { - return addEscape(colName, dbType, ColumnUtils.Escape.MYSQL); - } - return addEscape(colName, dbType, ColumnUtils.Escape.STANDARD); - } /** * if necessary, add escape * * @param colName the column name - * @param escape the escape + * @param dbType the dbType * @return */ - private static String addEscape(String colName, String dbType, Escape escape) { - if (colName == null || colName.isEmpty()) { - return colName; - } - if (colName.charAt(0) == escape.value && colName.charAt(colName.length() - 1) == escape.value) { + public static String addEscape(String colName, String dbType) { + if (StringUtils.isBlank(colName)) { return colName; } - - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(dbType); - if (keywordChecker != null) { - boolean check = keywordChecker.checkEscape(colName); - if (!check) { - return colName; - } - } - - if (colName.contains(DOT)) { - // like "scheme".id `scheme`.id - String str = escape.value + DOT; - int dotIndex = colName.indexOf(str); - if (dotIndex > -1) { - return new StringBuilder() - .append(colName.substring(0, dotIndex + str.length())) - .append(escape.value) - .append(colName.substring(dotIndex + str.length())) - .append(escape.value).toString(); - } - // like scheme."id" scheme.`id` - str = DOT + escape.value; - dotIndex = colName.indexOf(str); - if (dotIndex > -1) { - return new StringBuilder() - .append(escape.value) - .append(colName.substring(0, dotIndex)) - .append(escape.value) - .append(colName.substring(dotIndex)) - .toString(); - } - - str = DOT; - dotIndex = colName.indexOf(str); - if (dotIndex > -1) { - return new StringBuilder() - .append(escape.value) - .append(colName.substring(0, dotIndex)) - .append(escape.value) - .append(DOT) - .append(escape.value) - .append(colName.substring(dotIndex + str.length())) - .append(escape.value).toString(); - } - } - - char[] buf = new char[colName.length() + 2]; - buf[0] = escape.value; - buf[buf.length - 1] = escape.value; - - colName.getChars(0, colName.length(), buf, 1); - - return new String(buf).intern(); - } - - private static boolean isMysqlSeries(String dbType) { - return StringUtils.equalsIgnoreCase(dbType, JdbcConstants.MYSQL) || - StringUtils.equalsIgnoreCase(dbType, JdbcConstants.H2) || - StringUtils.equalsIgnoreCase(dbType, JdbcConstants.MARIADB); + EscapeHandler escapeHandler = EscapeHandlerFactory.getEscapeHandler(dbType); + return escapeHandler.addColNameEscape(colName); } } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java index 13d0ff84698..190c19a9d31 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java @@ -169,7 +169,7 @@ public List getDuplicateKeyUpdate() { } @Override - public List getInsertColumnsIsSimplified() { + public List getInsertColumnsUnEscape() { List insertColumns = getInsertColumns(); return ColumnUtils.delEscape(insertColumns, getDbType()); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java index 011f58873f1..d01a5192014 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java @@ -118,7 +118,7 @@ public List getUpdateValues() { } @Override - public List getUpdateColumnsIsSimplified() { + public List getUpdateColumnsUnEscape() { List updateColumns = getUpdateColumns(); return ColumnUtils.delEscape(updateColumns, getDbType()); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java index 424ee2653c0..45a370ce1d7 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java @@ -152,7 +152,7 @@ public List getDuplicateKeyUpdate() { } @Override - public List getInsertColumnsIsSimplified() { + public List getInsertColumnsUnEscape() { List insertColumns = getInsertColumns(); return ColumnUtils.delEscape(insertColumns, getDbType()); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java index 47d041ad17b..555e1b271c7 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java @@ -102,7 +102,7 @@ public List getUpdateValues() { } @Override - public List getUpdateColumnsIsSimplified() { + public List getUpdateColumnsUnEscape() { List updateColumns = getUpdateColumns(); return ColumnUtils.delEscape(updateColumns, getDbType()); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java index 79e68354c6a..935a6aeb135 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java @@ -162,7 +162,7 @@ public List getDuplicateKeyUpdate() { } @Override - public List getInsertColumnsIsSimplified() { + public List getInsertColumnsUnEscape() { List insertColumns = getInsertColumns(); return ColumnUtils.delEscape(insertColumns, getDbType()); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java index e3c1f89f778..562bef63b83 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java @@ -100,7 +100,7 @@ public List getUpdateValues() { } @Override - public List getUpdateColumnsIsSimplified() { + public List getUpdateColumnsUnEscape() { List updateColumns = getUpdateColumns(); return ColumnUtils.delEscape(updateColumns, getDbType()); } diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java index 5775745d3a3..e153f72c96a 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java @@ -185,15 +185,4 @@ public void testGetInsertColumns_2() { Assertions.assertTrue(insertColumn.contains("`")); } } - - @Test - public void testGetInsertColumnsIsSimplified() { - String sql = "insert into t(`id`, `no`, `name`, `age`) values (1, 'no001', 'aaa', '20')"; - List asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); - MySQLInsertRecognizer recognizer = new MySQLInsertRecognizer(sql, asts.get(0)); - List insertColumns = recognizer.getInsertColumnsIsSimplified(); - for (String insertColumn : insertColumns) { - Assertions.assertFalse(insertColumn.contains("`")); - } - } } diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java index 5ba096a84a0..2b9b6950e7b 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java @@ -374,15 +374,4 @@ public void testGetUpdateColumns_2() { Assertions.assertTrue(updateColumn.contains("`")); } } - - @Test - public void testGetUpdateColumnsIsSimplified() { - String sql = "update t set `a` = 1, `b` = 2, `c` = 3"; - List asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); - MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0)); - List updateColumns = recognizer.getUpdateColumnsIsSimplified(); - for (String updateColumn : updateColumns) { - Assertions.assertFalse(updateColumn.contains("`")); - } - } } From 8311743e44d9d1a649dd54b69084f68532c60aef Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 14 Jun 2023 23:05:17 +0800 Subject: [PATCH 58/76] optimize: support case-sensitive attributes for table and column metadata (#5647) Signed-off-by: slievrly --- changes/en-us/develop.md | 2 +- changes/zh-cn/develop.md | 1 + .../io/seata/common/util/StringUtils.java | 24 ++++++++ .../rm/datasource/sql/struct/ColumnMeta.java | 58 ++++++++++++------- .../rm/datasource/sql/struct/TableMeta.java | 21 +++++++ .../sql/struct/cache/MysqlTableMetaCache.java | 4 ++ .../struct/cache/OracleTableMetaCache.java | 2 + .../cache/PostgresqlTableMetaCache.java | 2 + 8 files changed, 92 insertions(+), 22 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 2b7e932cbba..d7176e17264 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -56,7 +56,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5541](https://github.com/seata/seata/pull/5541)] optimize server log output - [[#5548](https://github.com/seata/seata/pull/5548)] update expire gpg key and publish workflow - [[#5646](https://github.com/seata/seata/pull/5646)] refactor ColumnUtils and EscapeHandler - +- [[#5647](https://github.com/seata/seata/pull/5647)] support case-sensitive attributes for table and column metadata ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 1405462d5d1..b07ccb2baa7 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -56,6 +56,7 @@ - [[#5541](https://github.com/seata/seata/pull/5541)] 优化Server日志输出 - [[#5548](https://github.com/seata/seata/pull/5548)] 优化 gpg key 和 发布流水线 - [[#5646](https://github.com/seata/seata/pull/5646)] 重构 ColumnUtils 和 EscapeHandler +- [[#5647](https://github.com/seata/seata/pull/5647)] 支持表和列元数据大小写敏感设置 ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 diff --git a/common/src/main/java/io/seata/common/util/StringUtils.java b/common/src/main/java/io/seata/common/util/StringUtils.java index 9f48319ce1b..139541dded1 100644 --- a/common/src/main/java/io/seata/common/util/StringUtils.java +++ b/common/src/main/java/io/seata/common/util/StringUtils.java @@ -349,4 +349,28 @@ public static String hump2Line(String str) { return sb.toString(); } + public static boolean hasLowerCase(String str) { + if (null == str) { + return false; + } + for (int i = 0; i < str.length(); i++) { + if (Character.isLowerCase(str.charAt(i))) { + return true; + } + } + return false; + } + + public static boolean hasUpperCase(String str) { + if (null == str) { + return false; + } + for (int i = 0; i < str.length(); i++) { + if (Character.isUpperCase(str.charAt(i))) { + return true; + } + } + return false; + } + } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java index 6cc8eaa189a..6b0694043b5 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java @@ -43,6 +43,8 @@ public class ColumnMeta { private String isAutoincrement; private boolean isOnUpdate; + private boolean isCaseSensitive; + /** * Instantiates a new Column meta. */ @@ -51,27 +53,29 @@ public ColumnMeta() { @Override public String toString() { - return "ColumnMeta{" + - "tableCat='" + tableCat + '\'' + - ", tableSchemaName='" + tableSchemaName + '\'' + - ", tableName='" + tableName + '\'' + - ", columnName='" + columnName + '\'' + - ", dataType=" + dataType + - ", dataTypeName='" + dataTypeName + '\'' + - ", columnSize=" + columnSize + - ", decimalDigits=" + decimalDigits + - ", numPrecRadix=" + numPrecRadix + - ", nullAble=" + nullAble + - ", remarks='" + remarks + '\'' + - ", columnDef='" + columnDef + '\'' + - ", sqlDataType=" + sqlDataType + - ", sqlDatetimeSub=" + sqlDatetimeSub + - ", charOctetLength=" + charOctetLength + - ", ordinalPosition=" + ordinalPosition + - ", isNullAble='" + isNullAble + '\'' + - ", isAutoincrement='" + isAutoincrement + '\'' + - ", isOnUpdate=" + isOnUpdate + - '}'; + final StringBuilder sb = new StringBuilder("ColumnMeta{"); + sb.append("tableCat='").append(tableCat).append('\''); + sb.append(", tableSchemaName='").append(tableSchemaName).append('\''); + sb.append(", tableName='").append(tableName).append('\''); + sb.append(", columnName='").append(columnName).append('\''); + sb.append(", dataType=").append(dataType); + sb.append(", dataTypeName='").append(dataTypeName).append('\''); + sb.append(", columnSize=").append(columnSize); + sb.append(", decimalDigits=").append(decimalDigits); + sb.append(", numPrecRadix=").append(numPrecRadix); + sb.append(", nullAble=").append(nullAble); + sb.append(", remarks='").append(remarks).append('\''); + sb.append(", columnDef='").append(columnDef).append('\''); + sb.append(", sqlDataType=").append(sqlDataType); + sb.append(", sqlDatetimeSub=").append(sqlDatetimeSub); + sb.append(", charOctetLength=").append(charOctetLength); + sb.append(", ordinalPosition=").append(ordinalPosition); + sb.append(", isNullAble='").append(isNullAble).append('\''); + sb.append(", isAutoincrement='").append(isAutoincrement).append('\''); + sb.append(", isOnUpdate=").append(isOnUpdate); + sb.append(", isCaseSensitive=").append(isCaseSensitive); + sb.append('}'); + return sb.toString(); } /** @@ -415,6 +419,14 @@ public void setOnUpdate(boolean onUpdate) { isOnUpdate = onUpdate; } + public boolean isCaseSensitive() { + return isCaseSensitive; + } + + public void setCaseSensitive(boolean caseSensitive) { + isCaseSensitive = caseSensitive; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -481,6 +493,9 @@ public boolean equals(Object o) { if (!Objects.equals(columnMeta.isOnUpdate, this.isOnUpdate)) { return false; } + if (!Objects.equals(columnMeta.isCaseSensitive, this.isCaseSensitive)) { + return false; + } return true; } @@ -505,6 +520,7 @@ public int hashCode() { hash += Objects.hashCode(isNullAble); hash += Objects.hashCode(isAutoincrement); hash += Objects.hashCode(isOnUpdate); + hash += Objects.hashCode(isCaseSensitive); return hash; } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java index c58869103f8..b3a46d85470 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java @@ -36,6 +36,8 @@ public class TableMeta { private String tableName; + private boolean isCaseSensitive; + /** * key: column name */ @@ -92,6 +94,24 @@ public Map getAllIndexes() { return allIndexes; } + /** + * Is case sensitive boolean. + * + * @return the boolean + */ + public boolean isCaseSensitive() { + return isCaseSensitive; + } + + /** + * Sets case sensitive. + * + * @param caseSensitive the case sensitive + */ + public void setCaseSensitive(boolean caseSensitive) { + isCaseSensitive = caseSensitive; + } + /** * Gets auto increase column. * @@ -214,6 +234,7 @@ public int hashCode() { int hash = Objects.hashCode(tableName); hash += Objects.hashCode(allColumns); hash += Objects.hashCode(allIndexes); + hash += Objects.hashCode(isCaseSensitive); return hash; } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java index 3d6b65679fb..8dba04d4375 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java @@ -106,6 +106,9 @@ private TableMeta resultSetMetaToSchema(ResultSetMetaData rsmd, DatabaseMetaData TableMeta tm = new TableMeta(); tm.setTableName(tableName); + //always true and nothing to do with escape characters for mysql. + // May be not consistent with lower_case_table_names + tm.setCaseSensitive(true); /* * here has two different type to get the data @@ -137,6 +140,7 @@ private TableMeta resultSetMetaToSchema(ResultSetMetaData rsmd, DatabaseMetaData col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION")); col.setIsNullAble(rsColumns.getString("IS_NULLABLE")); col.setIsAutoincrement(rsColumns.getString("IS_AUTOINCREMENT")); + col.setCaseSensitive(rsmd.isCaseSensitive(col.getOrdinalPosition())); if (tm.getAllColumns().containsKey(col.getColumnName())) { throw new NotSupportYetException("Not support the table has the same column name with different case yet"); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java index d11329dedad..009aedfeb52 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java @@ -91,6 +91,7 @@ private TableMeta resultSetMetaToSchema(DatabaseMetaData dbmd, String tableName) } else { tableName = tableName.toUpperCase(); } + tm.setCaseSensitive(StringUtils.hasLowerCase(tableName)); try (ResultSet rsColumns = dbmd.getColumns("", schemaName, tableName, "%"); ResultSet rsIndex = dbmd.getIndexInfo(null, schemaName, tableName, false, true); @@ -114,6 +115,7 @@ private TableMeta resultSetMetaToSchema(DatabaseMetaData dbmd, String tableName) col.setCharOctetLength(rsColumns.getInt("CHAR_OCTET_LENGTH")); col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION")); col.setIsNullAble(rsColumns.getString("IS_NULLABLE")); + col.setCaseSensitive(StringUtils.hasLowerCase(col.getColumnName())); if (tm.getAllColumns().containsKey(col.getColumnName())) { throw new NotSupportYetException("Not support the table has the same column name with different case yet"); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java index 074d63b1d7e..c3312c6367c 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java @@ -108,6 +108,7 @@ private TableMeta resultSetMetaToSchema(Connection connection, String tableName) } else { tableName = tableName.toLowerCase(); } + tm.setCaseSensitive(StringUtils.hasUpperCase(tableName)); try (ResultSet rsColumns = dbmd.getColumns(null, schemaName, tableName, "%"); ResultSet rsIndex = dbmd.getIndexInfo(null, schemaName, tableName, false, true); @@ -132,6 +133,7 @@ private TableMeta resultSetMetaToSchema(Connection connection, String tableName) col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION")); col.setIsNullAble(rsColumns.getString("IS_NULLABLE")); col.setIsAutoincrement(rsColumns.getString("IS_AUTOINCREMENT")); + col.setCaseSensitive(StringUtils.hasUpperCase(col.getColumnName())); if (tm.getAllColumns().containsKey(col.getColumnName())) { throw new NotSupportYetException("Not support the table has the same column name with different case yet"); From 3dd365f2e1b59dedf68142ba5dfe92690033f3c9 Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 14 Jun 2023 23:06:54 +0800 Subject: [PATCH 59/76] optimize: optimize server logs print (#5648) Signed-off-by: slievrly --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 1 + .../registry/MultiRegistryFactory.java | 4 ++- .../java/io/seata/server/ServerRunner.java | 27 +++++++++++++++++-- server/src/main/resources/logback-spring.xml | 2 ++ 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index d7176e17264..e3fcb030bac 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -56,7 +56,9 @@ Add changes here for all PR submitted to the develop branch. - [[#5541](https://github.com/seata/seata/pull/5541)] optimize server log output - [[#5548](https://github.com/seata/seata/pull/5548)] update expire gpg key and publish workflow - [[#5646](https://github.com/seata/seata/pull/5646)] refactor ColumnUtils and EscapeHandler +- [[#5648](https://github.com/seata/seata/pull/5648)] optimize server logs print - [[#5647](https://github.com/seata/seata/pull/5647)] support case-sensitive attributes for table and column metadata + ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index b07ccb2baa7..f8cfbb7b929 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -56,6 +56,7 @@ - [[#5541](https://github.com/seata/seata/pull/5541)] 优化Server日志输出 - [[#5548](https://github.com/seata/seata/pull/5548)] 优化 gpg key 和 发布流水线 - [[#5646](https://github.com/seata/seata/pull/5646)] 重构 ColumnUtils 和 EscapeHandler +- [[#5648](https://github.com/seata/seata/pull/5648)] 优化Server日志输出 - [[#5647](https://github.com/seata/seata/pull/5647)] 支持表和列元数据大小写敏感设置 ### security: diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java index cbb4a98dc09..dd8aaebabee 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java @@ -54,8 +54,10 @@ private static List buildRegistryServices() { if (StringUtils.isBlank(registryTypeNamesStr)) { registryTypeNamesStr = RegistryType.File.name(); } - LOGGER.info("use multi registry center type: {}", registryTypeNamesStr); String[] registryTypeNames = registryTypeNamesStr.split(Constants.REGISTRY_TYPE_SPLIT_CHAR); + if (registryTypeNames.length > 1) { + LOGGER.info("use multi registry center type: {}", registryTypeNamesStr); + } for (String registryTypeName : registryTypeNames) { RegistryType registryType; try { diff --git a/server/src/main/java/io/seata/server/ServerRunner.java b/server/src/main/java/io/seata/server/ServerRunner.java index 2d567df697a..941d8cee788 100644 --- a/server/src/main/java/io/seata/server/ServerRunner.java +++ b/server/src/main/java/io/seata/server/ServerRunner.java @@ -19,11 +19,15 @@ import java.util.concurrent.CopyOnWriteArrayList; import io.seata.core.rpc.Disposable; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; import org.springframework.stereotype.Component; @@ -31,12 +35,18 @@ * @author spilledyear@outlook.com */ @Component -public class ServerRunner implements CommandLineRunner, DisposableBean { +public class ServerRunner implements CommandLineRunner, DisposableBean, + ApplicationListener, Ordered { private static final Logger LOGGER = LoggerFactory.getLogger(ServerRunner.class); private boolean started = Boolean.FALSE; + private int port; + + @Value("${logging.file.path}") + private String logPath; + private static final List DISPOSABLE_LIST = new CopyOnWriteArrayList<>(); public static void addDisposable(Disposable disposable) { @@ -51,6 +61,7 @@ public void run(String... args) { started = true; long cost = System.currentTimeMillis() - start; + LOGGER.info("\r\n you can visit seata console UI on http://127.0.0.1:{}. \r\n log path: {}.", this.port, this.logPath); LOGGER.info("seata server started in {} millSeconds", cost); } catch (Throwable e) { started = Boolean.FALSE; @@ -79,4 +90,16 @@ public void destroy() throws Exception { LOGGER.debug("destoryAll finish"); } } + + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof WebServerInitializedEvent) { + this.port = ((WebServerInitializedEvent)event).getWebServer().getPort(); + } + } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } } diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml index fe55a6f6c05..d847ac3b37b 100644 --- a/server/src/main/resources/logback-spring.xml +++ b/server/src/main/resources/logback-spring.xml @@ -75,4 +75,6 @@ + + From d484ff4f9581af2068bab7ea89e3bd82c9647432 Mon Sep 17 00:00:00 2001 From: XQDD <1032453509@qq.com> Date: Wed, 14 Jun 2023 23:09:23 +0800 Subject: [PATCH 60/76] optimize: set server's transaction level to READ_COMMITTED (#5638) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../java/io/seata/server/store/DbcpDataSourceProvider.java | 2 ++ .../java/io/seata/server/store/DruidDataSourceProvider.java | 3 +++ .../java/io/seata/server/store/HikariDataSourceProvider.java | 2 ++ 5 files changed, 9 insertions(+) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index e3fcb030bac..677cb622e51 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -55,6 +55,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5537](https://github.com/seata/seata/pull/5537)] optimize transaction log on client side - [[#5541](https://github.com/seata/seata/pull/5541)] optimize server log output - [[#5548](https://github.com/seata/seata/pull/5548)] update expire gpg key and publish workflow +- [[#5638](https://github.com/seata/seata/pull/5638)] optimize: set server's transaction level to READ_COMMITTED - [[#5646](https://github.com/seata/seata/pull/5646)] refactor ColumnUtils and EscapeHandler - [[#5648](https://github.com/seata/seata/pull/5648)] optimize server logs print - [[#5647](https://github.com/seata/seata/pull/5647)] support case-sensitive attributes for table and column metadata diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index f8cfbb7b929..9e537fa1556 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -55,6 +55,7 @@ - [[#5537](https://github.com/seata/seata/pull/5537)] 优化客户侧事务日志 - [[#5541](https://github.com/seata/seata/pull/5541)] 优化Server日志输出 - [[#5548](https://github.com/seata/seata/pull/5548)] 优化 gpg key 和 发布流水线 +- [[#5638](https://github.com/seata/seata/pull/5638)] 优化server端事务隔离级别为读已提交 - [[#5646](https://github.com/seata/seata/pull/5646)] 重构 ColumnUtils 和 EscapeHandler - [[#5648](https://github.com/seata/seata/pull/5648)] 优化Server日志输出 - [[#5647](https://github.com/seata/seata/pull/5647)] 支持表和列元数据大小写敏感设置 diff --git a/server/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java b/server/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java index 8880943bf04..3d6fc5c96bd 100644 --- a/server/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java +++ b/server/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java @@ -20,6 +20,7 @@ import org.apache.commons.dbcp2.BasicDataSource; import javax.sql.DataSource; +import java.sql.Connection; /** * The dbcp datasource provider @@ -51,6 +52,7 @@ public DataSource generate() { ds.setTestWhileIdle(true); ds.setValidationQuery(getValidationQuery(getDBType())); ds.setConnectionProperties("useUnicode=yes;characterEncoding=utf8;socketTimeout=5000;connectTimeout=500"); + ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); return ds; } } diff --git a/server/src/main/java/io/seata/server/store/DruidDataSourceProvider.java b/server/src/main/java/io/seata/server/store/DruidDataSourceProvider.java index cf5e619009b..ec19aa0b93a 100644 --- a/server/src/main/java/io/seata/server/store/DruidDataSourceProvider.java +++ b/server/src/main/java/io/seata/server/store/DruidDataSourceProvider.java @@ -21,6 +21,8 @@ import io.seata.core.store.db.AbstractDataSourceProvider; import com.alibaba.druid.pool.DruidDataSource; +import java.sql.Connection; + /** * The druid datasource provider * @author zhangsen @@ -52,6 +54,7 @@ public DataSource generate() { ds.setDefaultAutoCommit(true); // fix issue 5030 ds.setUseOracleImplicitCache(false); + ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); return ds; } } diff --git a/server/src/main/java/io/seata/server/store/HikariDataSourceProvider.java b/server/src/main/java/io/seata/server/store/HikariDataSourceProvider.java index 8adb354f574..60eb0d4372a 100644 --- a/server/src/main/java/io/seata/server/store/HikariDataSourceProvider.java +++ b/server/src/main/java/io/seata/server/store/HikariDataSourceProvider.java @@ -17,6 +17,7 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.util.IsolationLevel; import io.seata.common.loader.LoadLevel; import io.seata.core.store.db.AbstractDataSourceProvider; @@ -55,6 +56,7 @@ public DataSource generate() { config.setAutoCommit(true); config.setConnectionTimeout(getMaxWait()); config.setInitializationFailTimeout(-1); + config.setTransactionIsolation(IsolationLevel.TRANSACTION_READ_COMMITTED.name()); return new HikariDataSource(config); } } From 7a34d622bc5936f5901306d4fc6841fa682b432b Mon Sep 17 00:00:00 2001 From: PeppaO <39424591+PeppaO@users.noreply.github.com> Date: Fri, 23 Jun 2023 11:06:47 +0800 Subject: [PATCH 61/76] bugfix: fix the timeout is null when the connectionProxyXA connection is reused (#5663) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../io/seata/rm/datasource/xa/ConnectionProxyXA.java | 11 ++--------- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 677cb622e51..ec5ffaedd65 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -37,6 +37,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5583](https://github.com/seata/seata/pull/5583)] fix grpc interceptor xid unbinding problem - [[#5602](https://github.com/seata/seata/pull/5602)] fix log in participant transaction role - [[#5645](https://github.com/seata/seata/pull/5645)] fix oracle insert undolog failed +- [[#5663](https://github.com/seata/seata/pull/5663)] bugfix: fix the timeout is null when the connectionProxyXA connection is reused ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 9e537fa1556..a9d4d481d93 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -37,6 +37,7 @@ - [[#5583](https://github.com/seata/seata/pull/5583)] 修复grpc xid 解绑问题 - [[#5602](https://github.com/seata/seata/pull/5602)] 修复participant情况下的重复日志 - [[#5645](https://github.com/seata/seata/pull/5645)] 修复 oracle 插入 undolog 失败问题 +- [[#5663](https://github.com/seata/seata/pull/5663)] 修复connectionProxyXA连接复用时timeout为null ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java index c3162d64908..c229f782a36 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ConnectionProxyXA.java @@ -26,7 +26,6 @@ import io.seata.common.DefaultValues; import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationFactory; -import io.seata.core.context.RootContext; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; @@ -64,7 +63,7 @@ public class ConnectionProxyXA extends AbstractConnectionProxyXA implements Hold private volatile Long prepareTime = null; - private volatile Integer timeout = null; + private static final Integer TIMEOUT = Math.max(BRANCH_EXECUTION_TIMEOUT, DefaultValues.DEFAULT_GLOBAL_TRANSACTION_TIMEOUT); private boolean shouldBeHeld = false; @@ -89,11 +88,6 @@ public void init() { if (!currentAutoCommitStatus) { throw new IllegalStateException("Connection[autocommit=false] as default is NOT supported"); } - Integer transactionTimeout = RootContext.getTimeout(); - if (transactionTimeout == null) { - transactionTimeout = DefaultValues.DEFAULT_GLOBAL_TRANSACTION_TIMEOUT; - } - timeout = Math.max(BRANCH_EXECUTION_TIMEOUT, transactionTimeout); } catch (SQLException e) { throw new RuntimeException(e); } @@ -292,7 +286,6 @@ private synchronized void end(int flags) throws XAException, SQLException { private void cleanXABranchContext() { branchRegisterTime = null; prepareTime = null; - timeout = null; xaActive = false; if (!isHeld()) { xaBranchXid = null; @@ -300,7 +293,7 @@ private void cleanXABranchContext() { } private void checkTimeout(Long now) throws XAException { - if (now - branchRegisterTime > timeout) { + if (now - branchRegisterTime > TIMEOUT) { xaRollback(xaBranchXid); throw new XAException("XA branch timeout error"); } From 67af758c1e930f2225bf5698f69c1aa4beb35a19 Mon Sep 17 00:00:00 2001 From: wt_better Date: Tue, 27 Jun 2023 11:12:26 +0800 Subject: [PATCH 62/76] bugfix: fix saga autoType convert error (#5671) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ .../invoker/impl/SpringBeanServiceInvoker.java | 6 +++++- .../io/seata/saga/statelang/parser/JsonParser.java | 9 +++++++++ .../saga/statelang/parser/impl/FastjsonParser.java | 5 +++++ .../statelang/parser/impl/JacksonJsonParser.java | 13 +++++++------ 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index ec5ffaedd65..7c00a3c87ed 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -6,6 +6,7 @@ Add changes here for all PR submitted to the develop branch. - [[#xxx](https://github.com/seata/seata/pull/xxx)] support xxx ### bugfix: +- [[#5671](https://github.com/seata/seata/pull/5671)] fix saga mode serviceTask inputParams json autoType convert exception - [[#5194](https://github.com/seata/seata/pull/5194)] fix wrong keyword order for oracle when creating a table - [[#5021](https://github.com/seata/seata/pull/5201)] Fix JDK Reflection for Spring origin proxy failed in JDK17 - [[#5023](https://github.com/seata/seata/pull/5203)] Fix `seata-core` dependency transitive conflict in `seata-dubbo` @@ -89,6 +90,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [mxsm](https://github.com/mxsm) - [l81893521](https://github.com/l81893521) - [liuqiufeng](https://github.com/liuqiufeng) +- [yixia](https://github.com/wt-better) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index a9d4d481d93..ac17819f785 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -6,6 +6,7 @@ - [[#xxx](https://github.com/seata/seata/pull/xxx)] 支持 xxx ### bugfix: +- [[#5671](https://github.com/seata/seata/pull/5671)] 修复saga模式下serviceTask入参autoType转化失败问题 - [[#5194](https://github.com/seata/seata/pull/5194)] 修复使用Oracle作为服务端DB存储时的建表失败问题 - [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 - [[#5023](https://github.com/seata/seata/pull/5203)] 修复 `seata-core` 模块传递依赖冲突 @@ -89,6 +90,7 @@ - [mxsm](https://github.com/mxsm) - [l81893521](https://github.com/l81893521) - [liuqiufeng](https://github.com/liuqiufeng) +- [yixia](https://github.com/wt-better) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java index 9f4908a8b94..15577499181 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java @@ -301,7 +301,11 @@ protected Object toJavaObject(Object value, Class paramType) { throw new RuntimeException("Cannot get JsonParser by name : " + getSagaJsonParser()); } String jsonValue = jsonParser.toJsonString(value, true, false); - return jsonParser.parse(jsonValue, paramType, false); + + //compatible history autoType serialize json + boolean useAutoType = jsonParser.useAutoType(jsonValue); + + return jsonParser.parse(jsonValue, paramType, !useAutoType); } } diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParser.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParser.java index 30767a8f237..fefd5ff8695 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParser.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParser.java @@ -39,6 +39,15 @@ public interface JsonParser { */ String toJsonString(Object o, boolean prettyPrint); + + /** + * Check json use auto type boolean. + * + * @param json the json + * @return the boolean + */ + boolean useAutoType(String json); + /** * Object to Json string * @param o the input object diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/FastjsonParser.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/FastjsonParser.java index b7ccfb35a59..1341624ada9 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/FastjsonParser.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/FastjsonParser.java @@ -52,6 +52,11 @@ public String getName() { return NAME; } + @Override + public boolean useAutoType(String json) { + return json != null && json.contains("\"@type\""); + } + @Override public String toJsonString(Object o, boolean prettyPrint) { return toJsonString(o, false, prettyPrint); diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/JacksonJsonParser.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/JacksonJsonParser.java index 3407df89ffd..8a0139c6860 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/JacksonJsonParser.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/JacksonJsonParser.java @@ -23,8 +23,6 @@ import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import io.seata.common.loader.LoadLevel; import io.seata.saga.statelang.parser.JsonParser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; @@ -38,15 +36,13 @@ @LoadLevel(name = JacksonJsonParser.NAME) public class JacksonJsonParser implements JsonParser { - private static final Logger LOGGER = LoggerFactory.getLogger(JacksonJsonParser.class); - - private ObjectMapper objectMapperWithAutoType = new ObjectMapper() + private final ObjectMapper objectMapperWithAutoType = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, "@type") .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER) .setSerializationInclusion(Include.NON_NULL); - private ObjectMapper objectMapper = new ObjectMapper() + private final ObjectMapper objectMapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .disableDefaultTyping() .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER) @@ -64,6 +60,11 @@ public String toJsonString(Object o, boolean prettyPrint) { return toJsonString(o, false, prettyPrint); } + @Override + public boolean useAutoType(String json) { + return json != null && json.contains("\"@type\""); + } + @Override public String toJsonString(Object o, boolean ignoreAutoType, boolean prettyPrint) { try { From 51d7d2d9a2cfa4343e157277d5923c460d370fc1 Mon Sep 17 00:00:00 2001 From: FUNKYE <364176773@qq.com> Date: Tue, 27 Jun 2023 11:40:10 +0800 Subject: [PATCH 63/76] bugfix: fix escaped characters for upper and lower case column names (#5659) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../datasource/AbstractConnectionProxy.java | 2 +- .../seata/rm/datasource/DataCompareUtils.java | 2 +- .../datasource/exec/BaseInsertExecutor.java | 2 +- .../exec/BaseTransactionalExecutor.java | 2 +- .../rm/datasource/exec/DeleteExecutor.java | 2 +- .../datasource/exec/MultiDeleteExecutor.java | 2 +- .../datasource/exec/MultiUpdateExecutor.java | 2 +- .../rm/datasource/exec/UpdateExecutor.java | 14 ++++++------ .../exec/mysql/MySQLInsertExecutor.java | 2 +- .../MySQLInsertOnDuplicateUpdateExecutor.java | 6 ++--- .../exec/mysql/MySQLUpdateJoinExecutor.java | 2 +- .../postgresql/PostgresqlInsertExecutor.java | 2 +- .../sql/struct/TableMetaCacheFactory.java | 1 + .../datasource/sql/struct/TableRecords.java | 3 +++ .../struct/cache/AbstractTableMetaCache.java | 4 ++-- .../sql/struct/cache/MysqlTableMetaCache.java | 8 +++---- .../struct/cache/OracleTableMetaCache.java | 8 +++---- .../cache/PostgresqlTableMetaCache.java | 8 +++---- .../datasource/undo/AbstractUndoExecutor.java | 2 +- .../undo/AbstractUndoLogManager.java | 2 +- .../seata/rm/datasource/undo/SQLUndoLog.java | 2 +- ... io.seata.sqlparser.struct.TableMetaCache} | 0 .../rm/datasource/DataCompareUtilsTest.java | 2 +- .../exec/AbstractDMLBaseExecutorTest.java | 2 +- .../exec/BaseTransactionalExecutorTest.java | 2 +- .../exec/BatchInsertExecutorTest.java | 2 +- .../exec/MariadbInsertExecutorTest.java | 2 +- .../exec/MySQLInsertExecutorTest.java | 4 ++-- ...QLInsertOnDuplicateUpdateExecutorTest.java | 8 +++---- .../exec/OracleInsertExecutorTest.java | 4 ++-- .../exec/PostgresqlInsertExecutorTest.java | 4 ++-- .../datasource/exec/UpdateExecutorTest.java | 6 +++-- .../rm/datasource/mock/MockResultSet.java | 2 +- .../mock/MockResultSetMetaData.java | 2 +- .../datasource/sql/struct/ColumnMetaTest.java | 1 + .../datasource/sql/struct/IndexMetaTest.java | 3 +++ .../datasource/sql/struct/IndexTypeTest.java | 1 + .../datasource/sql/struct/TableMetaTest.java | 4 ++++ .../sql/struct/TableRecordsTest.java | 1 + .../struct/cache/MysqlTableMetaCacheTest.java | 10 ++++----- .../cache/OracleTableMetaCacheTest.java | 4 ++-- .../cache/PostgresqlTableMetaCacheTest.java | 4 ++-- .../undo/AbstractUndoExecutorTest.java | 2 +- .../seata/rm/datasource/undo/BaseH2Test.java | 5 ++--- .../undo/BaseUndoLogParserTest.java | 2 +- .../rm/datasource/undo/BranchUndoLogTest.java | 2 +- .../rm/datasource/undo/UndoExecutorTest.java | 2 +- .../mysql/MySQLUndoDeleteExecutorTest.java | 4 +--- .../mysql/MySQLUndoInsertExecutorTest.java | 2 +- .../undo/mysql/MySQLUndoLogManagerTest.java | 2 +- .../mysql/MySQLUndoUpdateExecutorTest.java | 2 +- .../oracle/OracleUndoDeleteExecutorTest.java | 3 +-- .../oracle/OracleUndoInsertExecutorTest.java | 3 +-- .../oracle/OracleUndoUpdateExecutorTest.java | 3 +-- .../io/seata/sqlparser/EscapeHandler.java | 22 +++++++++++++++++-- .../seata/sqlparser}/struct/ColumnMeta.java | 2 +- .../io/seata/sqlparser}/struct/IndexMeta.java | 2 +- .../io/seata/sqlparser}/struct/IndexType.java | 2 +- .../io/seata/sqlparser}/struct/TableMeta.java | 2 +- .../sqlparser}/struct/TableMetaCache.java | 2 +- .../io/seata/sqlparser/util/ColumnUtils.java | 18 ++++++++++++--- .../at/ATModeSupportDataBaseDataTypeTest.java | 2 +- .../seata/at/mysql/MysqlUpdateJoinTest.java | 2 +- .../at/oracle/SupportOracleDataTypeTest.java | 4 +--- 66 files changed, 139 insertions(+), 99 deletions(-) rename rm-datasource/src/main/resources/META-INF/services/{io.seata.rm.datasource.sql.struct.TableMetaCache => io.seata.sqlparser.struct.TableMetaCache} (100%) rename {rm-datasource/src/main/java/io/seata/rm/datasource/sql => sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser}/struct/ColumnMeta.java (99%) mode change 100755 => 100644 rename {rm-datasource/src/main/java/io/seata/rm/datasource/sql => sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser}/struct/IndexMeta.java (99%) mode change 100755 => 100644 rename {rm-datasource/src/main/java/io/seata/rm/datasource/sql => sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser}/struct/IndexType.java (97%) mode change 100755 => 100644 rename {rm-datasource/src/main/java/io/seata/rm/datasource/sql => sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser}/struct/TableMeta.java (99%) mode change 100755 => 100644 rename {rm-datasource/src/main/java/io/seata/rm/datasource/sql => sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser}/struct/TableMetaCache.java (96%) mode change 100755 => 100644 diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 7c00a3c87ed..b9d9a9fae6d 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -38,6 +38,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5583](https://github.com/seata/seata/pull/5583)] fix grpc interceptor xid unbinding problem - [[#5602](https://github.com/seata/seata/pull/5602)] fix log in participant transaction role - [[#5645](https://github.com/seata/seata/pull/5645)] fix oracle insert undolog failed +- [[#5659](https://github.com/seata/seata/pull/5659)] fix the issue of case sensitivity enforcement on the database after adding escape characters to keywords - [[#5663](https://github.com/seata/seata/pull/5663)] bugfix: fix the timeout is null when the connectionProxyXA connection is reused ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index ac17819f785..8099c5d1cea 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -38,6 +38,7 @@ - [[#5583](https://github.com/seata/seata/pull/5583)] 修复grpc xid 解绑问题 - [[#5602](https://github.com/seata/seata/pull/5602)] 修复participant情况下的重复日志 - [[#5645](https://github.com/seata/seata/pull/5645)] 修复 oracle 插入 undolog 失败问题 +- [[#5659](https://github.com/seata/seata/pull/5659)] 修复后镜像查询时增加关键字转义符导致数据库强制开启大小写校验引起的sql异常 - [[#5663](https://github.com/seata/seata/pull/5663)] 修复connectionProxyXA连接复用时timeout为null ### optimize: diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java index ef8c8107211..4d0109e379c 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java @@ -18,7 +18,7 @@ import io.seata.core.context.RootContext; import io.seata.core.model.BranchType; import io.seata.rm.datasource.sql.SQLVisitorFactory; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLType; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java index ef2af6a9ab2..5d66094fecc 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java @@ -20,7 +20,7 @@ import io.seata.core.model.Result; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.rm.datasource.undo.AbstractUndoLogManager; import io.seata.rm.datasource.undo.parser.FastjsonUndoLogParser; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java index 63dbcbf18f7..9432af0995c 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java @@ -34,7 +34,7 @@ import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.StatementProxy; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLRecognizer; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java index a1cc2e1c175..0b8cf57cc4f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java @@ -39,7 +39,7 @@ import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.sql.struct.Field; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.rm.datasource.undo.SQLUndoLog; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java index 6f0d3da274b..30952c326ef 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java @@ -24,7 +24,7 @@ import io.seata.common.util.StringUtils; import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.StatementProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLDeleteRecognizer; import io.seata.sqlparser.SQLRecognizer; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java index 3606b049511..42345605075 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java @@ -21,7 +21,7 @@ import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.StatementProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLDeleteRecognizer; import io.seata.sqlparser.SQLRecognizer; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java index 6103a669ef6..77ac5bceaae 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java @@ -35,7 +35,7 @@ import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.StatementProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLUpdateRecognizer; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java index 8607b99a1d7..17c83f44997 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java @@ -33,7 +33,7 @@ import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.StatementProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLUpdateRecognizer; @@ -134,18 +134,18 @@ protected List getNeedUpdateColumns(String table, String tableAlias, Lis needUpdateColumns.add(getColumnNamesWithTablePrefix(table,tableAlias,pkNameList)); } } - needUpdateColumns.addAll(unescapeUpdateColumns.parallelStream() - .map(unescapeUpdateColumn -> ColumnUtils.addEscape(unescapeUpdateColumn, getDbType())).collect(Collectors.toList())); + needUpdateColumns.addAll(unescapeUpdateColumns.stream() + .map(unescapeUpdateColumn -> ColumnUtils.addEscape(unescapeUpdateColumn, getDbType(), tableMeta)).collect(Collectors.toList())); // The on update xxx columns will be auto update by db, so it's also the actually updated columns List onUpdateColumns = tableMeta.getOnUpdateColumnsOnlyName(); onUpdateColumns.removeAll(unescapeUpdateColumns); - needUpdateColumns.addAll(onUpdateColumns.parallelStream() - .map(onUpdateColumn -> ColumnUtils.addEscape(onUpdateColumn, getDbType())) + needUpdateColumns.addAll(onUpdateColumns.stream() + .map(onUpdateColumn -> ColumnUtils.addEscape(onUpdateColumn, getDbType(), tableMeta)) .collect(Collectors.toList())); } else { - needUpdateColumns.addAll(tableMeta.getAllColumns().keySet().parallelStream() - .map(columnName -> ColumnUtils.addEscape(columnName, getDbType())).collect(Collectors.toList())); + needUpdateColumns.addAll(tableMeta.getAllColumns().keySet().stream() + .map(columnName -> ColumnUtils.addEscape(columnName, getDbType(), tableMeta)).collect(Collectors.toList())); } return needUpdateColumns; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java index 41c7f7dd5ac..a5bbac2febc 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java @@ -36,7 +36,7 @@ import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.BaseInsertExecutor; import io.seata.rm.datasource.exec.StatementCallback; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.struct.Defaultable; import io.seata.sqlparser.struct.Null; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertOnDuplicateUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertOnDuplicateUpdateExecutor.java index 1c66a1eef6d..c3047e77c40 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertOnDuplicateUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertOnDuplicateUpdateExecutor.java @@ -41,12 +41,12 @@ import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.StatementCallback; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; -import io.seata.rm.datasource.sql.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexMeta; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLRecognizer; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java index 555f9f5239e..52f8eeb860c 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java @@ -41,7 +41,7 @@ import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.StatementCallback; import io.seata.rm.datasource.exec.UpdateExecutor; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLUpdateRecognizer; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java index 9f6ff0f8ef9..f8a25a49def 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java @@ -23,7 +23,7 @@ import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.BaseInsertExecutor; import io.seata.rm.datasource.exec.StatementCallback; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.struct.Defaultable; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java index 1a71aeefdf4..848ce378084 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCacheFactory.java @@ -30,6 +30,7 @@ import io.seata.common.util.CollectionUtils; import io.seata.config.ConfigurationFactory; import io.seata.rm.datasource.DataSourceProxy; +import io.seata.sqlparser.struct.TableMetaCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java index 7c9f5420725..219ceb6db1a 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java @@ -36,6 +36,9 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.rm.datasource.exception.TableMetaException; import io.seata.rm.datasource.sql.serial.SerialArray; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.TableMeta; + import static io.seata.rm.datasource.exec.oracle.OracleJdbcType.TIMESTAMP_WITH_LOCAL_TIME_ZONE; import static io.seata.rm.datasource.exec.oracle.OracleJdbcType.TIMESTAMP_WITH_TIME_ZONE; import static io.seata.rm.datasource.util.OffsetTimeUtils.convertOffSetTime; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java index 2c1470447a7..cbae2e9ad10 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java @@ -26,8 +26,8 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.StringUtils; import io.seata.core.context.RootContext; -import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.sql.struct.TableMetaCache; +import io.seata.sqlparser.struct.TableMeta; +import io.seata.sqlparser.struct.TableMetaCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java index 8dba04d4375..fdce71e3e32 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java @@ -26,10 +26,10 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; import io.seata.sqlparser.util.ColumnUtils; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.IndexMeta; -import io.seata.rm.datasource.sql.struct.IndexType; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexType; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.util.JdbcConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java index 009aedfeb52..b00bc9bfb76 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java @@ -24,10 +24,10 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.IndexMeta; -import io.seata.rm.datasource.sql.struct.IndexType; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexType; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.util.JdbcConstants; import java.util.ArrayList; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java index c3312c6367c..a87c2f6adff 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java @@ -24,10 +24,10 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.IndexMeta; -import io.seata.rm.datasource.sql.struct.IndexType; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexType; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.util.JdbcConstants; /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java index a2e70dfa96f..7d64239a6ae 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java @@ -42,7 +42,7 @@ import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java index e6ae3232075..21116d3eeaa 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java @@ -39,7 +39,7 @@ import io.seata.rm.datasource.ConnectionContext; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.DataSourceProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/SQLUndoLog.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/SQLUndoLog.java index 69915c26ac5..61efb55bdbd 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/SQLUndoLog.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/SQLUndoLog.java @@ -16,7 +16,7 @@ package io.seata.rm.datasource.undo; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLType; diff --git a/rm-datasource/src/main/resources/META-INF/services/io.seata.rm.datasource.sql.struct.TableMetaCache b/rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.struct.TableMetaCache similarity index 100% rename from rm-datasource/src/main/resources/META-INF/services/io.seata.rm.datasource.sql.struct.TableMetaCache rename to rm-datasource/src/main/resources/META-INF/services/io.seata.sqlparser.struct.TableMetaCache diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java index 52ced27106c..dfcfbf92e2c 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java @@ -17,7 +17,7 @@ import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java index 60ea7b27316..f2d1a73e08f 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java @@ -21,7 +21,7 @@ import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; import io.seata.rm.datasource.exec.oracle.OracleInsertExecutor; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.util.JdbcConstants; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java index ece25afe305..37e3dbabf83 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java @@ -21,7 +21,7 @@ import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.sql.struct.Field; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLRecognizer; import org.junit.jupiter.api.Assertions; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java index b92a0bd18ad..5a802c5e562 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java @@ -25,7 +25,7 @@ import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.struct.Null; import io.seata.sqlparser.util.JdbcConstants; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MariadbInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MariadbInsertExecutorTest.java index 51f1a6df8ba..949c2b9cc71 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MariadbInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MariadbInsertExecutorTest.java @@ -24,7 +24,7 @@ import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; import io.seata.rm.datasource.mock.MockMariadbDataSource; import io.seata.rm.datasource.mock.MockResultSet; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.util.JdbcConstants; import org.junit.jupiter.api.Assertions; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java index c7eed40b50f..b7ba7ccfdb7 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java @@ -34,9 +34,9 @@ import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; import io.seata.rm.datasource.mock.MockDataSource; import io.seata.rm.datasource.mock.MockResultSet; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.struct.Null; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertOnDuplicateUpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertOnDuplicateUpdateExecutorTest.java index e0de214e551..069c499970b 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertOnDuplicateUpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertOnDuplicateUpdateExecutorTest.java @@ -30,10 +30,10 @@ import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.mysql.MySQLInsertOnDuplicateUpdateExecutor; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.IndexMeta; -import io.seata.rm.datasource.sql.struct.IndexType; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexType; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.util.JdbcConstants; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java index b6dcdde79bf..906b87ceb3d 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java @@ -20,8 +20,8 @@ import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.oracle.OracleInsertExecutor; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.struct.Null; import io.seata.sqlparser.struct.SqlSequenceExpr; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java index 1acad8d40ab..b10d703e2e5 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java @@ -19,8 +19,8 @@ import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.exec.postgresql.PostgresqlInsertExecutor; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.struct.SqlDefaultExpr; import io.seata.sqlparser.util.JdbcConstants; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java index 07d353effe4..c25df6f4e37 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java @@ -57,7 +57,7 @@ public static void init() { Object[][] columnMetas = new Object[][] { new Object[] {"", "", "table_update_executor_test", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, new Object[] {"", "", "table_update_executor_test", "name", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, - new Object[] {"", "", "table_update_executor_test", "all", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + new Object[] {"", "", "table_update_executor_test", "ALL", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, }; Object[][] indexMetas = new Object[][] { new Object[] {"PRIMARY", "id", false, "", 3, 1, "A", 34}, @@ -104,7 +104,9 @@ public void testKeyword() throws SQLException { List asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0)); updateExecutor = new UpdateExecutor(statementProxy, (statement, args) -> null, recognizer); - Assertions.assertNotNull(updateExecutor.beforeImage()); + TableRecords beforeImage = updateExecutor.beforeImage(); + Assertions.assertNotNull(beforeImage); + Assertions.assertNotNull(updateExecutor.afterImage(beforeImage)); } @Test diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java index 8f29b2dcf7c..78f3f8cf69b 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java @@ -26,7 +26,7 @@ import com.alibaba.druid.util.jdbc.ResultSetBase; import com.google.common.collect.Lists; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSetMetaData.java b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSetMetaData.java index 17e394cd847..802b9d25e01 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSetMetaData.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockResultSetMetaData.java @@ -20,7 +20,7 @@ import java.util.List; import io.seata.common.util.ReflectionUtil; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; /** * @author will diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/ColumnMetaTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/ColumnMetaTest.java index a47c183ca79..1200e07a738 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/ColumnMetaTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/ColumnMetaTest.java @@ -15,6 +15,7 @@ */ package io.seata.rm.datasource.sql.struct; +import io.seata.sqlparser.struct.ColumnMeta; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexMetaTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexMetaTest.java index 2b3eb99552c..657c5c4114f 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexMetaTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexMetaTest.java @@ -16,6 +16,9 @@ package io.seata.rm.datasource.sql.struct; import com.google.common.collect.Lists; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexTypeTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexTypeTest.java index 840d3a4068e..9adb04602bd 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexTypeTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/IndexTypeTest.java @@ -15,6 +15,7 @@ */ package io.seata.rm.datasource.sql.struct; +import io.seata.sqlparser.struct.IndexType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java index 55ad004a203..85c43c60223 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java @@ -17,6 +17,10 @@ import com.google.common.collect.Lists; import io.seata.common.exception.NotSupportYetException; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexType; +import io.seata.sqlparser.struct.TableMeta; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java index 556f60fdcbf..61714ca7778 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableRecordsTest.java @@ -21,6 +21,7 @@ import java.util.List; import io.seata.rm.datasource.exception.TableMetaException; +import io.seata.sqlparser.struct.TableMeta; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java index dcec3e420e4..4a24a2b143a 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java @@ -27,11 +27,11 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.rm.datasource.DataSourceProxy; import io.seata.rm.datasource.mock.MockDriver; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.IndexMeta; -import io.seata.rm.datasource.sql.struct.IndexType; -import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.sql.struct.TableMetaCache; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.IndexMeta; +import io.seata.sqlparser.struct.IndexType; +import io.seata.sqlparser.struct.TableMeta; +import io.seata.sqlparser.struct.TableMetaCache; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.sqlparser.util.JdbcConstants; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java index ff7e39cb0d3..8d3aa2abccd 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java @@ -25,8 +25,8 @@ import io.seata.rm.datasource.DataSourceProxy; import io.seata.rm.datasource.mock.MockDriver; -import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.sql.struct.TableMetaCache; +import io.seata.sqlparser.struct.TableMeta; +import io.seata.sqlparser.struct.TableMetaCache; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.sqlparser.util.JdbcConstants; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java index d65e2b43007..2098629e824 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java @@ -25,8 +25,8 @@ import io.seata.rm.datasource.DataSourceProxy; import io.seata.rm.datasource.mock.MockDriver; -import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.sql.struct.TableMetaCache; +import io.seata.sqlparser.struct.TableMeta; +import io.seata.sqlparser.struct.TableMetaCache; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.sqlparser.util.JdbcConstants; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java index d668885a93e..3ff4b4d0844 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java @@ -19,7 +19,7 @@ import io.seata.sqlparser.SQLType; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java index ed3bab07f02..9a84c5e08e5 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java @@ -18,11 +18,11 @@ import io.seata.common.util.IOUtil; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.DataSourceProxy; -import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.apache.commons.dbcp2.BasicDataSource; import org.h2.store.fs.FileUtils; @@ -31,7 +31,6 @@ import org.junit.jupiter.api.BeforeEach; import org.mockito.Mockito; -import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseUndoLogParserTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseUndoLogParserTest.java index 2d8974769c8..cca60178642 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseUndoLogParserTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseUndoLogParserTest.java @@ -25,7 +25,7 @@ import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLType; import org.junit.jupiter.api.Assertions; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java index df2010ba133..9b8138772c4 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java @@ -21,7 +21,7 @@ import io.seata.sqlparser.SQLType; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java index 43ccb10c595..6d95e6b898b 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java @@ -56,7 +56,7 @@ import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.util.JdbcConstants; import org.junit.jupiter.api.Assertions; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java index 7866781fa3a..c0ef428748e 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java @@ -19,7 +19,7 @@ import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.SQLType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -30,8 +30,6 @@ import java.util.Arrays; import java.util.List; -import static org.mockito.Mockito.when; - /** * @author Geng Zhang */ diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java index 37a48dbe995..1fbcf5311e3 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java @@ -19,7 +19,7 @@ import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.SQLType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java index b0741ace6ae..367dc94a82e 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java @@ -35,7 +35,7 @@ import io.seata.rm.datasource.DataSourceProxy; import io.seata.rm.datasource.mock.MockDriver; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.rm.datasource.undo.AbstractUndoLogManager; import io.seata.rm.datasource.undo.BranchUndoLog; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java index 11c6ffc4195..5c90dc64a8c 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java @@ -19,7 +19,7 @@ import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.SQLType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java index 279a33cb853..b67b3618df0 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java @@ -16,13 +16,12 @@ package io.seata.rm.datasource.undo.oracle; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.rm.datasource.undo.BaseExecutorTest; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.SQLType; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java index 74e67da6e30..ac55b953ff9 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java @@ -16,13 +16,12 @@ package io.seata.rm.datasource.undo.oracle; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.rm.datasource.undo.BaseExecutorTest; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.SQLType; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java index 3848669843b..1533f9af962 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java @@ -16,13 +16,12 @@ package io.seata.rm.datasource.undo.oracle; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.rm.datasource.undo.BaseExecutorTest; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.SQLType; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java index 5714985f1bd..f1bc419a13e 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java @@ -16,6 +16,8 @@ package io.seata.sqlparser; import io.seata.common.util.StringUtils; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.TableMeta; /** * The interface Keyword checker. @@ -61,14 +63,30 @@ default boolean containsEscape(String fieldOrTableName) { /** * add escape if colName is keywords - * @param colName - * @return + * @param colName colName + * @return colName */ default String addColNameEscape(String colName) { + return addColNameEscape(colName, null); + } + + /** + * add escape if colName is keywords + * @param colName colName + * @param tableMeta tableMeta + * @return colName + */ + default String addColNameEscape(String colName, TableMeta tableMeta) { boolean needEscape = checkIfNeedEscape(colName); if (!needEscape) { return colName; } + if (tableMeta != null) { + ColumnMeta columnMeta = tableMeta.getColumnMeta(colName); + if (columnMeta != null) { + colName = columnMeta.getColumnName(); + } + } char escapeChar = getEscapeSymbol(); if (colName.contains(DOT)) { // like "scheme".id `scheme`.id diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/ColumnMeta.java old mode 100755 new mode 100644 similarity index 99% rename from rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java rename to sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/ColumnMeta.java index 6b0694043b5..6cff6eeaaee --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/ColumnMeta.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.sql.struct; +package io.seata.sqlparser.struct; import java.util.Objects; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/IndexMeta.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/IndexMeta.java old mode 100755 new mode 100644 similarity index 99% rename from rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/IndexMeta.java rename to sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/IndexMeta.java index 6d1618c2552..a55055c3ad0 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/IndexMeta.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/IndexMeta.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.sql.struct; +package io.seata.sqlparser.struct; import java.util.ArrayList; import java.util.List; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/IndexType.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/IndexType.java old mode 100755 new mode 100644 similarity index 97% rename from rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/IndexType.java rename to sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/IndexType.java index 7c435979bfc..ae0109d60c2 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/IndexType.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/IndexType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.sql.struct; +package io.seata.sqlparser.struct; /** * The enum Index type. diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/TableMeta.java old mode 100755 new mode 100644 similarity index 99% rename from rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java rename to sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/TableMeta.java index b3a46d85470..2e093b78e51 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/TableMeta.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.sql.struct; +package io.seata.sqlparser.struct; import java.util.ArrayList; import java.util.HashMap; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCache.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/TableMetaCache.java old mode 100755 new mode 100644 similarity index 96% rename from rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCache.java rename to sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/TableMetaCache.java index c7605d8c4da..f4999ade230 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCache.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/TableMetaCache.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.datasource.sql.struct; +package io.seata.sqlparser.struct; import java.sql.Connection; diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java index 237badce4f3..d72020bbf4e 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/util/ColumnUtils.java @@ -22,6 +22,7 @@ import io.seata.common.util.StringUtils; import io.seata.sqlparser.EscapeHandler; import io.seata.sqlparser.EscapeHandlerFactory; +import io.seata.sqlparser.struct.TableMeta; /** * column utils @@ -91,20 +92,31 @@ public static List addEscape(List cols, String dbType) { return newCols; } - /** * if necessary, add escape * * @param colName the column name * @param dbType the dbType - * @return + * @return colName */ public static String addEscape(String colName, String dbType) { + return addEscape(colName, dbType, null); + } + + /** + * if necessary, add escape + * + * @param colName the column name + * @param dbType the dbType + * @param tableMeta the tableMeta + * @return colName + */ + public static String addEscape(String colName, String dbType, TableMeta tableMeta) { if (StringUtils.isBlank(colName)) { return colName; } EscapeHandler escapeHandler = EscapeHandlerFactory.getEscapeHandler(dbType); - return escapeHandler.addColNameEscape(colName); + return escapeHandler.addColNameEscape(colName, tableMeta); } } diff --git a/test/src/test/java/io/seata/at/ATModeSupportDataBaseDataTypeTest.java b/test/src/test/java/io/seata/at/ATModeSupportDataBaseDataTypeTest.java index 6718f9efd36..0effa63c06c 100644 --- a/test/src/test/java/io/seata/at/ATModeSupportDataBaseDataTypeTest.java +++ b/test/src/test/java/io/seata/at/ATModeSupportDataBaseDataTypeTest.java @@ -33,7 +33,7 @@ import io.seata.rm.datasource.DataCompareUtils; import io.seata.rm.datasource.DataSourceManager; import io.seata.rm.datasource.DataSourceProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.rm.datasource.sql.struct.TableRecords; import static io.seata.at.DruidDataSourceUtils.ORACLE; diff --git a/test/src/test/java/io/seata/at/mysql/MysqlUpdateJoinTest.java b/test/src/test/java/io/seata/at/mysql/MysqlUpdateJoinTest.java index 6bd9820b846..20a697b1654 100644 --- a/test/src/test/java/io/seata/at/mysql/MysqlUpdateJoinTest.java +++ b/test/src/test/java/io/seata/at/mysql/MysqlUpdateJoinTest.java @@ -29,7 +29,7 @@ import io.seata.rm.datasource.DataCompareUtils; import io.seata.rm.datasource.DataSourceManager; import io.seata.rm.datasource.DataSourceProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.server.UUIDGenerator; diff --git a/test/src/test/java/io/seata/at/oracle/SupportOracleDataTypeTest.java b/test/src/test/java/io/seata/at/oracle/SupportOracleDataTypeTest.java index 783ae45b9c2..4b6fce14850 100644 --- a/test/src/test/java/io/seata/at/oracle/SupportOracleDataTypeTest.java +++ b/test/src/test/java/io/seata/at/oracle/SupportOracleDataTypeTest.java @@ -16,7 +16,6 @@ package io.seata.at.oracle; import com.alibaba.druid.pool.DruidDataSource; -import io.seata.common.exception.NotSupportYetException; import io.seata.core.context.RootContext; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; @@ -25,7 +24,7 @@ import io.seata.rm.datasource.DataCompareUtils; import io.seata.rm.datasource.DataSourceManager; import io.seata.rm.datasource.DataSourceProxy; -import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Assertions; @@ -39,7 +38,6 @@ import java.sql.Statement; import static io.seata.at.DruidDataSourceUtils.ORACLE; -import static io.seata.at.DruidDataSourceUtils.POSTGRESQL; import static io.seata.at.DruidDataSourceUtils.createNewDruidDataSource; import static io.seata.at.oracle.OracleSqlConstant.BINARY_TABLE_NAME; import static io.seata.at.oracle.OracleSqlConstant.BINARY_TYPE; From f1a74548f6dbcf848251fb0de83cdb2c55ffc747 Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 28 Jun 2023 13:25:11 +0800 Subject: [PATCH 64/76] bugfix: fix compatibility between xxx.grouplist and grouplist.xxx (#5675) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../exception/ConfigNotFoundException.java | 48 +++++++++++++++++++ .../rpc/netty/NettyClientChannelManager.java | 22 +++------ .../consul/ConsulRegistryServiceImpl.java | 4 +- .../registry/FileRegistryServiceImpl.java | 30 +++++++----- .../etcd3/EtcdRegistryServiceImpl.java | 4 +- .../eureka/EurekaRegistryServiceImpl.java | 4 +- .../nacos/NacosRegistryServiceImpl.java | 4 +- .../redis/RedisRegistryServiceImpl.java | 4 +- .../sofa/SofaRegistryServiceImpl.java | 4 +- .../zk/ZookeeperRegisterServiceImpl.java | 4 +- .../zk/ZookeeperRegisterServiceImplTest.java | 21 +++++--- .../SpringBootConfigurationProvider.java | 8 ++++ 14 files changed, 118 insertions(+), 41 deletions(-) create mode 100644 config/seata-config-core/src/main/java/io/seata/config/exception/ConfigNotFoundException.java diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index b9d9a9fae6d..c8e179b0e7f 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -40,6 +40,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5645](https://github.com/seata/seata/pull/5645)] fix oracle insert undolog failed - [[#5659](https://github.com/seata/seata/pull/5659)] fix the issue of case sensitivity enforcement on the database after adding escape characters to keywords - [[#5663](https://github.com/seata/seata/pull/5663)] bugfix: fix the timeout is null when the connectionProxyXA connection is reused +- [[#5675](https://github.com/seata/seata/pull/5675)] bugfix: fix compatibility between xxx.grouplist and grouplist.xxx configuration items ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 8099c5d1cea..44b49b19034 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -40,6 +40,7 @@ - [[#5645](https://github.com/seata/seata/pull/5645)] 修复 oracle 插入 undolog 失败问题 - [[#5659](https://github.com/seata/seata/pull/5659)] 修复后镜像查询时增加关键字转义符导致数据库强制开启大小写校验引起的sql异常 - [[#5663](https://github.com/seata/seata/pull/5663)] 修复connectionProxyXA连接复用时timeout为null +- [[#5675](https://github.com/seata/seata/pull/5675)] 修复 xxx.grouplist 和 grouplist.xxx 配置项兼容问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/config/seata-config-core/src/main/java/io/seata/config/exception/ConfigNotFoundException.java b/config/seata-config-core/src/main/java/io/seata/config/exception/ConfigNotFoundException.java new file mode 100644 index 00000000000..3c5e5cf8895 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/exception/ConfigNotFoundException.java @@ -0,0 +1,48 @@ +/* + * Copyright 1999-2019 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.config.exception; + +/** + * @author slievrly + */ +public class ConfigNotFoundException extends RuntimeException { + + public ConfigNotFoundException() { + super(); + } + + public ConfigNotFoundException(String message) { + super(message); + } + + public ConfigNotFoundException(String format, String... args) { + this(String.format(format, args)); + } + + public ConfigNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ConfigNotFoundException(Throwable cause) { + super(cause); + } + + protected ConfigNotFoundException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java index 0ad9f8b0cd5..e225d1e3504 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java @@ -18,30 +18,27 @@ import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; import java.util.stream.Collectors; -import io.seata.core.protocol.RegisterTMRequest; -import org.apache.commons.pool.impl.GenericKeyedObjectPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import io.netty.channel.Channel; import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.FrameworkException; import io.seata.common.util.CollectionUtils; import io.seata.common.util.NetUtil; -import io.seata.common.util.StringUtils; -import io.seata.core.constants.ConfigurationKeys; import io.seata.core.protocol.RegisterRMRequest; +import io.seata.core.protocol.RegisterTMRequest; import io.seata.discovery.registry.FileRegistryServiceImpl; import io.seata.discovery.registry.RegistryFactory; import io.seata.discovery.registry.RegistryService; +import org.apache.commons.pool.impl.GenericKeyedObjectPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Netty client pool manager. @@ -177,15 +174,8 @@ void reconnect(String transactionServiceGroup) { RegistryService registryService = RegistryFactory.getInstance(); String clusterName = registryService.getServiceGroup(transactionServiceGroup); - if (StringUtils.isBlank(clusterName)) { - LOGGER.error("can not get cluster name in registry config '{}{}', please make sure registry config correct", - ConfigurationKeys.SERVICE_GROUP_MAPPING_PREFIX, - transactionServiceGroup); - return; - } - if (!(registryService instanceof FileRegistryServiceImpl)) { - LOGGER.error("no available service found in cluster '{}', please make sure registry config correct and keep your seata server running", clusterName); + LOGGER.error("no available service endpoint found in cluster '{}', please make sure registry config correct and keep your seata-server is running", clusterName); } return; } diff --git a/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java b/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java index c603377dfa7..c6b4637989d 100644 --- a/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java +++ b/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java @@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import io.seata.config.exception.ConfigNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -163,7 +164,8 @@ public void unsubscribe(String cluster, ConsulListener listener) throws Exceptio public List lookup(String key) throws Exception { final String cluster = getServiceGroup(key); if (cluster == null) { - return null; + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } return lookupByCluster(cluster); diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java index 6c4f58cade8..4f4fa0840f8 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java @@ -15,15 +15,15 @@ */ package io.seata.discovery.registry; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; import io.seata.common.util.StringUtils; import io.seata.config.ConfigChangeListener; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; - -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; +import io.seata.config.exception.ConfigNotFoundException; /** * The type File registry service. @@ -31,13 +31,13 @@ * @author slievrly */ public class FileRegistryServiceImpl implements RegistryService { + private static volatile FileRegistryServiceImpl instance; private static final Configuration CONFIG = ConfigurationFactory.getInstance(); private static final String POSTFIX_GROUPLIST = ".grouplist"; private static final String ENDPOINT_SPLIT_CHAR = ";"; private static final String IP_PORT_SPLIT_CHAR = ":"; - private FileRegistryServiceImpl() { } @@ -81,13 +81,10 @@ public void unsubscribe(String cluster, ConfigChangeListener listener) throws Ex public List lookup(String key) throws Exception { String clusterName = getServiceGroup(key); if (clusterName == null) { - return null; - } - String endpointStr = CONFIG.getConfig( - PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + clusterName + POSTFIX_GROUPLIST); - if (StringUtils.isNullOrEmpty(endpointStr)) { - throw new IllegalArgumentException(clusterName + POSTFIX_GROUPLIST + " is required"); + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } + String endpointStr = getGroupListFromConfig(clusterName); String[] endpoints = endpointStr.split(ENDPOINT_SPLIT_CHAR); List inetSocketAddresses = new ArrayList<>(); for (String endpoint : endpoints) { @@ -100,6 +97,17 @@ public List lookup(String key) throws Exception { return inetSocketAddresses; } + private String getGroupListFromConfig(String clusterName) { + String oldGrouplistDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + clusterName + POSTFIX_GROUPLIST; + String endpointStr = CONFIG.getConfig(oldGrouplistDataId); + if (StringUtils.isNullOrEmpty(endpointStr)) { + String newGrouplistDataId = PREFIX_SERVICE_ROOT + POSTFIX_GROUPLIST + CONFIG_SPLIT_CHAR + clusterName; + throw new ConfigNotFoundException("%s or %s configuration item is required", oldGrouplistDataId, + newGrouplistDataId); + } + return endpointStr; + } + @Override public void close() throws Exception { diff --git a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java index 94965c75235..b2bc4b1858e 100644 --- a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java +++ b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java @@ -33,6 +33,7 @@ import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; +import io.seata.config.exception.ConfigNotFoundException; import io.seata.discovery.registry.RegistryHeartBeats; import io.seata.discovery.registry.RegistryService; @@ -183,7 +184,8 @@ public void unsubscribe(String cluster, Watch.Listener listener) throws Exceptio public List lookup(String key) throws Exception { final String cluster = getServiceGroup(key); if (cluster == null) { - return null; + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } return lookupByCluster(cluster); } diff --git a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java index 3217ec6e526..bd894b22409 100644 --- a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java +++ b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java @@ -30,6 +30,7 @@ import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; +import io.seata.config.exception.ConfigNotFoundException; import io.seata.discovery.registry.RegistryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -131,7 +132,8 @@ public void unsubscribe(String cluster, EurekaEventListener listener) throws Exc public List lookup(String key) throws Exception { String clusterName = getServiceGroup(key); if (clusterName == null) { - return null; + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } String clusterUpperName = clusterName.toUpperCase(); if (!LISTENER_SERVICE_MAP.containsKey(clusterUpperName)) { diff --git a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java index 96ea5046973..9a62552ea39 100644 --- a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java +++ b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java @@ -38,6 +38,7 @@ import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; import io.seata.config.ConfigurationKeys; +import io.seata.config.exception.ConfigNotFoundException; import io.seata.discovery.registry.RegistryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -145,7 +146,8 @@ public void unsubscribe(String cluster, EventListener listener) throws Exception public List lookup(String key) throws Exception { String clusterName = getServiceGroup(key); if (clusterName == null) { - return null; + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } if (useSLBWay) { if (LOGGER.isDebugEnabled()) { diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java index 6d2418e7d14..77b988a47b0 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java @@ -35,6 +35,7 @@ import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; +import io.seata.config.exception.ConfigNotFoundException; import io.seata.discovery.registry.RegistryHeartBeats; import io.seata.discovery.registry.RegistryService; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; @@ -220,7 +221,8 @@ public void unsubscribe(String cluster, RedisListener listener) { public List lookup(String key) { String clusterName = getServiceGroup(key); if (clusterName == null) { - return null; + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } return lookupByCluster(clusterName); } diff --git a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java index ed095fc1348..28105f390c7 100644 --- a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java +++ b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java @@ -37,6 +37,7 @@ import io.seata.common.util.NetUtil; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; +import io.seata.config.exception.ConfigNotFoundException; import io.seata.discovery.registry.RegistryService; import org.apache.commons.lang.StringUtils; @@ -160,7 +161,8 @@ public void unsubscribe(String cluster, SubscriberDataObserver listener) throws public List lookup(String key) throws Exception { String clusterName = getServiceGroup(key); if (clusterName == null) { - return null; + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } if (!LISTENER_SERVICE_MAP.containsKey(clusterName)) { CountDownLatch respondRegistries = new CountDownLatch(1); diff --git a/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java b/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java index adfd02045a3..24344d196ec 100644 --- a/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java +++ b/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java @@ -33,6 +33,7 @@ import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; +import io.seata.config.exception.ConfigNotFoundException; import io.seata.discovery.registry.RegistryService; import org.I0Itec.zkclient.IZkChildListener; import org.I0Itec.zkclient.IZkStateListener; @@ -179,7 +180,8 @@ public List lookup(String key) throws Exception { String clusterName = getServiceGroup(key); if (clusterName == null) { - return null; + String missingDataId = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + throw new ConfigNotFoundException("%s configuration item is required", missingDataId); } return doLookup(clusterName); diff --git a/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java b/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java index 52b07258098..4698bbd0e20 100644 --- a/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java +++ b/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java @@ -15,7 +15,14 @@ */ package io.seata.discovery.registry.zk; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + import io.seata.common.util.NetUtil; +import io.seata.config.exception.ConfigNotFoundException; import org.I0Itec.zkclient.IZkChildListener; import org.I0Itec.zkclient.ZkClient; import org.apache.curator.test.TestingServer; @@ -23,12 +30,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.function.Executable; /** * @author Geng Zhang @@ -67,7 +69,12 @@ public void buildZkTest() { public void testAll() throws Exception { service.register(new InetSocketAddress(NetUtil.getLocalAddress(), 33333)); - Assertions.assertNull(service.lookup("xxx")); + Assertions.assertThrows(ConfigNotFoundException.class, new Executable() { + @Override + public void execute() throws Throwable { + service.lookup("xxx"); + } + }); List lookup2 = service.doLookup("default"); Assertions.assertEquals(1, lookup2.size()); diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java index 5a3c4cdd07c..4268bca0133 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java @@ -227,6 +227,14 @@ private Object getConfigFromEnvironment(String dataId, Class dataType) { if (value == null) { value = environment.getProperty(io.seata.common.util.StringUtils.hump2Line(dataId), dataType); } + if (value == null) { + String grouplistPrefix = SERVICE_PREFIX + DOT + SPECIAL_KEY_GROUPLIST + DOT; + if (dataId.startsWith(grouplistPrefix)) { + String vgroup = StringUtils.removeStart(dataId, grouplistPrefix); + String oldGrouplistDataId = SERVICE_PREFIX + DOT + vgroup + DOT + SPECIAL_KEY_GROUPLIST; + return getConfigFromEnvironment(oldGrouplistDataId, dataType); + } + } return value; } From d252cbc86efd4b8888a644396b0d2da2bea75dcf Mon Sep 17 00:00:00 2001 From: jimin Date: Wed, 28 Jun 2023 13:37:00 +0800 Subject: [PATCH 65/76] optimize: optimize escape character for case of columnNames (#5678) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../sql/handler/mysql/MySQLEscapeHandler.java | 11 ++++---- .../handler/oracle/OracleEscapeHandler.java | 19 +++++++++----- .../postgresql/PostgresqlEscapeHandler.java | 25 ++++++++++++------- .../io/seata/sqlparser/EscapeHandler.java | 14 +++-------- 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index c8e179b0e7f..61da6aa56b8 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -63,6 +63,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5646](https://github.com/seata/seata/pull/5646)] refactor ColumnUtils and EscapeHandler - [[#5648](https://github.com/seata/seata/pull/5648)] optimize server logs print - [[#5647](https://github.com/seata/seata/pull/5647)] support case-sensitive attributes for table and column metadata +- [[#5678](https://github.com/seata/seata/pull/5678)] optimize escape character for case of columnNames ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 44b49b19034..439a3fa9b37 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -63,6 +63,7 @@ - [[#5646](https://github.com/seata/seata/pull/5646)] 重构 ColumnUtils 和 EscapeHandler - [[#5648](https://github.com/seata/seata/pull/5648)] 优化Server日志输出 - [[#5647](https://github.com/seata/seata/pull/5647)] 支持表和列元数据大小写敏感设置 +- [[#5678](https://github.com/seata/seata/pull/5678)] 优化大小写转义符 ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mysql/MySQLEscapeHandler.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mysql/MySQLEscapeHandler.java index 02ea2ff7291..29285f84c47 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mysql/MySQLEscapeHandler.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/mysql/MySQLEscapeHandler.java @@ -22,6 +22,7 @@ import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; import io.seata.sqlparser.EscapeHandler; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.util.JdbcConstants; /** @@ -1114,15 +1115,15 @@ public boolean checkIfKeyWords(String fieldOrTableName) { } @Override - public boolean checkIfNeedEscape(String fieldOrTableName) { - if (StringUtils.isBlank(fieldOrTableName)) { + public boolean checkIfNeedEscape(String columnName, TableMeta tableMeta) { + if (StringUtils.isBlank(columnName)) { return false; } - fieldOrTableName = fieldOrTableName.trim(); - if (containsEscape(fieldOrTableName)) { + columnName = columnName.trim(); + if (containsEscape(columnName)) { return false; } - return checkIfKeyWords(fieldOrTableName); + return checkIfKeyWords(columnName); } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/oracle/OracleEscapeHandler.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/oracle/OracleEscapeHandler.java index 0fb5358e206..7887dc50ff1 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/oracle/OracleEscapeHandler.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/oracle/OracleEscapeHandler.java @@ -22,6 +22,8 @@ import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; import io.seata.sqlparser.EscapeHandler; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.util.JdbcConstants; /** @@ -502,15 +504,15 @@ public boolean checkIfKeyWords(String fieldOrTableName) { @Override - public boolean checkIfNeedEscape(String fieldOrTableName) { - if (StringUtils.isBlank(fieldOrTableName)) { + public boolean checkIfNeedEscape(String columnName, TableMeta tableMeta) { + if (StringUtils.isBlank(columnName)) { return false; } - fieldOrTableName = fieldOrTableName.trim(); - if (containsEscape(fieldOrTableName)) { + columnName = columnName.trim(); + if (containsEscape(columnName)) { return false; } - boolean isKeyWord = checkIfKeyWords(fieldOrTableName); + boolean isKeyWord = checkIfKeyWords(columnName); if (isKeyWord) { return true; } @@ -526,7 +528,12 @@ public boolean checkIfNeedEscape(String fieldOrTableName) { //"table" × × √ × // //"TABLE" √ √ × √ - if (isUppercase(fieldOrTableName)) { + if (null != tableMeta) { + ColumnMeta columnMeta = tableMeta.getColumnMeta(columnName); + if (null != columnMeta) { + return columnMeta.isCaseSensitive(); + } + } else if (isUppercase(columnName)) { return false; } return true; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/postgresql/PostgresqlEscapeHandler.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/postgresql/PostgresqlEscapeHandler.java index 3cd06a3f875..f29b9c996c1 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/postgresql/PostgresqlEscapeHandler.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/handler/postgresql/PostgresqlEscapeHandler.java @@ -22,6 +22,8 @@ import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; import io.seata.sqlparser.EscapeHandler; +import io.seata.sqlparser.struct.ColumnMeta; +import io.seata.sqlparser.struct.TableMeta; import io.seata.sqlparser.util.JdbcConstants; /** @@ -370,19 +372,24 @@ public boolean checkIfKeyWords(String fieldOrTableName) { } @Override - public boolean checkIfNeedEscape(String fieldOrTableName) { - if (StringUtils.isBlank(fieldOrTableName)) { + public boolean checkIfNeedEscape(String columnName, TableMeta tableMeta) { + if (StringUtils.isBlank(columnName)) { return false; } - fieldOrTableName = fieldOrTableName.trim(); - if (containsEscape(fieldOrTableName)) { + columnName = columnName.trim(); + if (containsEscape(columnName)) { return false; } - boolean check = checkIfKeyWords(fieldOrTableName); - if (!check && !containsUppercase(fieldOrTableName)) { - // postgresql - // we are recommend table name and column name must lowercase. - // if exists uppercase character or full uppercase, the table name or column name must bundle escape symbol. + boolean isKeyWord = checkIfKeyWords(columnName); + if (isKeyWord) { + return true; + } + if (null != tableMeta) { + ColumnMeta columnMeta = tableMeta.getColumnMeta(columnName); + if (null != columnMeta) { + return columnMeta.isCaseSensitive(); + } + } else if (!containsUppercase(columnName)) { return false; } return true; diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java index f1bc419a13e..94cad902363 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/EscapeHandler.java @@ -16,7 +16,6 @@ package io.seata.sqlparser; import io.seata.common.util.StringUtils; -import io.seata.sqlparser.struct.ColumnMeta; import io.seata.sqlparser.struct.TableMeta; /** @@ -38,10 +37,11 @@ public interface EscapeHandler { /** * check whether given field or table name use keywords. the method has database special logic. - * @param fieldOrTableName the field or table name + * @param columnName the column or table name + * @param tableMeta the tableMeta * @return true: need to escape. false: no need to escape. */ - boolean checkIfNeedEscape(String fieldOrTableName); + boolean checkIfNeedEscape(String columnName, TableMeta tableMeta); default char getEscapeSymbol() { return '"'; @@ -77,16 +77,10 @@ default String addColNameEscape(String colName) { * @return colName */ default String addColNameEscape(String colName, TableMeta tableMeta) { - boolean needEscape = checkIfNeedEscape(colName); + boolean needEscape = checkIfNeedEscape(colName, tableMeta); if (!needEscape) { return colName; } - if (tableMeta != null) { - ColumnMeta columnMeta = tableMeta.getColumnMeta(colName); - if (columnMeta != null) { - colName = columnMeta.getColumnName(); - } - } char escapeChar = getEscapeSymbol(); if (colName.contains(DOT)) { // like "scheme".id `scheme`.id From c0c1541da6ddab2a64caeeb1e46f8f755d0ab295 Mon Sep 17 00:00:00 2001 From: wt_better Date: Thu, 29 Jun 2023 14:31:32 +0800 Subject: [PATCH 66/76] bugfix: fix saga mode replay context lost start (#5682) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 1 + .../seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 61da6aa56b8..fcf36adf53d 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -6,6 +6,7 @@ Add changes here for all PR submitted to the develop branch. - [[#xxx](https://github.com/seata/seata/pull/xxx)] support xxx ### bugfix: +- [[#5682](https://github.com/seata/seata/pull/5682)] fix saga mode replay context lost startParams - [[#5671](https://github.com/seata/seata/pull/5671)] fix saga mode serviceTask inputParams json autoType convert exception - [[#5194](https://github.com/seata/seata/pull/5194)] fix wrong keyword order for oracle when creating a table - [[#5021](https://github.com/seata/seata/pull/5201)] Fix JDK Reflection for Spring origin proxy failed in JDK17 diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 439a3fa9b37..20a10d0e2bf 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -6,6 +6,7 @@ - [[#xxx](https://github.com/seata/seata/pull/xxx)] 支持 xxx ### bugfix: +- [[#5682](https://github.com/seata/seata/pull/5682)] 修复saga模式下replay context丢失startParams问题 - [[#5671](https://github.com/seata/seata/pull/5671)] 修复saga模式下serviceTask入参autoType转化失败问题 - [[#5194](https://github.com/seata/seata/pull/5194)] 修复使用Oracle作为服务端DB存储时的建表失败问题 - [[#5021](https://github.com/seata/seata/pull/5201)] 修复 JDK17 下获取 Spring 原始代理对象失败的问题 diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java index 7e9a0b01286..6bfc7b0d342 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java @@ -355,7 +355,7 @@ private Map getStateMachineContextVariables(StateMachineInstance protected Map replayContextVariables(StateMachineInstance stateMachineInstance) { Map contextVariables = new HashMap<>(); - if (stateMachineInstance.getStartParams() == null) { + if (stateMachineInstance.getStartParams() != null) { contextVariables.putAll(stateMachineInstance.getStartParams()); } From c267320c6612bd8c0f19b04b74a46fb48df26db4 Mon Sep 17 00:00:00 2001 From: jimin Date: Thu, 29 Jun 2023 14:37:38 +0800 Subject: [PATCH 67/76] security: add Hessian Serializer WhiteDenyList (#5683) Signed-off-by: slievrly --- changes/en-us/2.0.0.md | 46 ------------- changes/en-us/develop.md | 3 +- changes/zh-cn/2.0.0.md | 46 ------------- changes/zh-cn/develop.md | 1 + .../hessian/HessianSerializerFactory.java | 67 ++++++++++++++++--- .../hessian/HessianSerializerTest.java | 55 +++++++++++++++ 6 files changed, 116 insertions(+), 102 deletions(-) delete mode 100644 changes/en-us/2.0.0.md delete mode 100644 changes/zh-cn/2.0.0.md diff --git a/changes/en-us/2.0.0.md b/changes/en-us/2.0.0.md deleted file mode 100644 index 4593f9bae53..00000000000 --- a/changes/en-us/2.0.0.md +++ /dev/null @@ -1,46 +0,0 @@ -### 2.0.0 - - [source](https://github.com/seata/seata/archive/v2.0.0.zip) | - [binary](https://github.com/seata/seata/releases/download/v2.0.0/seata-server-2.0.0.zip) - -
- Release notes - -### Seata 2.0.0 - -Seata 2.0.0 Released. - -Seata is an easy-to-use, high-performance, open source distributed transaction solution. - -The version is updated as follows: - -### feature: - - [[#1234](https://github.com/seata/seata/pull/1234)] Please delete the sample later - -### bugfix: - - [[#1234](https://github.com/seata/seata/pull/1234)] Please delete the sample later - -### optimize: - - [[#1234](https://github.com/seata/seata/pull/1234)] Please delete the sample later - -### test: - - [[#1234](https://github.com/seata/seata/pull/1234)] Please delete the sample later - - -### Contributors: - -Thanks to these contributors for their code commits. Please report an unintended omission. - - - [slievrly](https://github.com/slievrly) - -Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. - - -#### Link - - - **Seata:** https://github.com/seata/seata - - **Seata-Samples:** https://github.com/seata/seata-samples - - **Release:** https://github.com/seata/seata/releases - - **WebSite:** https://seata.io - -
diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index fcf36adf53d..f18353c2d2c 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -64,10 +64,11 @@ Add changes here for all PR submitted to the develop branch. - [[#5646](https://github.com/seata/seata/pull/5646)] refactor ColumnUtils and EscapeHandler - [[#5648](https://github.com/seata/seata/pull/5648)] optimize server logs print - [[#5647](https://github.com/seata/seata/pull/5647)] support case-sensitive attributes for table and column metadata -- [[#5678](https://github.com/seata/seata/pull/5678)] optimize escape character for case of columnNames +- [[#5683](https://github.com/seata/seata/pull/5683)] optimize escape character for case of columnNames ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities +- [[#5642](https://github.com/seata/seata/pull/5642)] add Hessian Serializer WhiteDenyList ### test: - [[#5380](https://github.com/seata/seata/pull/5380)] fix UpdateExecutorTest failed diff --git a/changes/zh-cn/2.0.0.md b/changes/zh-cn/2.0.0.md deleted file mode 100644 index 591880a4071..00000000000 --- a/changes/zh-cn/2.0.0.md +++ /dev/null @@ -1,46 +0,0 @@ -### 2.0.0 - - [source](https://github.com/seata/seata/archive/v2.0.0.zip) | - [binary](https://github.com/seata/seata/releases/download/v2.0.0/seata-server-2.0.0.zip) - -
- Release notes - -### Seata 2.0.0 - -Seata 2.0.0 发布。 - -Seata 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务。 - -此版本更新如下: - -### feature: - - [[#1234](https://github.com/seata/seata/pull/1234)] 样例,后续请删除 - -### bugfix: - - [[#1234](https://github.com/seata/seata/pull/1234)] 样例,后续请删除 - -### optimize: - - [[#1234](https://github.com/seata/seata/pull/1234)] 样例,后续请删除 - -### test: - - [[#1234](https://github.com/seata/seata/pull/1234)] 样例,后续请删除 - - -### Contributors: - -非常感谢以下 contributors 的代码贡献。若有无意遗漏,请报告。 - - - [slievrly](https://github.com/slievrly) - -同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 - - -#### Link - - - **Seata:** https://github.com/seata/seata - - **Seata-Samples:** https://github.com/seata/seata-samples - - **Release:** https://github.com/seata/seata/releases - - **WebSite:** https://seata.io - -
diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 20a10d0e2bf..672312b9eab 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -68,6 +68,7 @@ ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 +- [[#5683](https://github.com/seata/seata/pull/5683)] 增加Hessian 序列化黑白名单 ### test: - [[#5380](https://github.com/seata/seata/pull/5380)] 修复 UpdateExecutorTest 单测失败问题 diff --git a/serializer/seata-serializer-hessian/src/main/java/io/seata/serializer/hessian/HessianSerializerFactory.java b/serializer/seata-serializer-hessian/src/main/java/io/seata/serializer/hessian/HessianSerializerFactory.java index 35ebfaf5ce7..4fce9517d03 100644 --- a/serializer/seata-serializer-hessian/src/main/java/io/seata/serializer/hessian/HessianSerializerFactory.java +++ b/serializer/seata-serializer-hessian/src/main/java/io/seata/serializer/hessian/HessianSerializerFactory.java @@ -15,9 +15,18 @@ */ package io.seata.serializer.hessian; -import com.caucho.hessian.io.Deserializer; -import com.caucho.hessian.io.HessianProtocolException; -import com.caucho.hessian.io.Serializer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + import com.caucho.hessian.io.SerializerFactory; /* @@ -28,19 +37,59 @@ public class HessianSerializerFactory extends SerializerFactory { private HessianSerializerFactory() { super(); + super.getClassFactory().setWhitelist(true); + super.getClassFactory().allow("io.seata.*"); + allowBasicTypes(); + allowCollections(); + denyTypes(); } public static SerializerFactory getInstance() { return INSTANCE; } - @Override - protected Serializer loadSerializer(Class cl) throws HessianProtocolException { - return super.loadSerializer(cl); + private void allowBasicTypes() { + super.getClassFactory().allow(boolean.class.getCanonicalName()); + super.getClassFactory().allow(byte.class.getCanonicalName()); + super.getClassFactory().allow(char.class.getCanonicalName()); + super.getClassFactory().allow(double.class.getCanonicalName()); + super.getClassFactory().allow(float.class.getCanonicalName()); + super.getClassFactory().allow(int.class.getCanonicalName()); + super.getClassFactory().allow(long.class.getCanonicalName()); + super.getClassFactory().allow(short.class.getCanonicalName()); + super.getClassFactory().allow(Boolean.class.getCanonicalName()); + super.getClassFactory().allow(Byte.class.getCanonicalName()); + super.getClassFactory().allow(Character.class.getCanonicalName()); + super.getClassFactory().allow(Double.class.getCanonicalName()); + super.getClassFactory().allow(Float.class.getCanonicalName()); + super.getClassFactory().allow(Integer.class.getCanonicalName()); + super.getClassFactory().allow(Long.class.getCanonicalName()); + super.getClassFactory().allow(Short.class.getCanonicalName()); + + super.getClassFactory().allow(Number.class.getCanonicalName()); + super.getClassFactory().allow(Class.class.getCanonicalName()); + super.getClassFactory().allow(String.class.getCanonicalName()); + } + + private void allowCollections() { + super.getClassFactory().allow(List.class.getCanonicalName()); + super.getClassFactory().allow(ArrayList.class.getCanonicalName()); + super.getClassFactory().allow(LinkedList.class.getCanonicalName()); + + super.getClassFactory().allow(Set.class.getCanonicalName()); + super.getClassFactory().allow(HashSet.class.getCanonicalName()); + super.getClassFactory().allow(LinkedHashSet.class.getCanonicalName()); + super.getClassFactory().allow(TreeSet.class.getCanonicalName()); + + super.getClassFactory().allow(Map.class.getCanonicalName()); + super.getClassFactory().allow(HashMap.class.getCanonicalName()); + super.getClassFactory().allow(LinkedHashMap.class.getCanonicalName()); + super.getClassFactory().allow(TreeMap.class.getCanonicalName()); } - @Override - protected Deserializer loadDeserializer(Class cl) throws HessianProtocolException { - return super.loadDeserializer(cl); + private void denyTypes() { + super.getClassFactory().deny("javax.naming.InitialContext"); + super.getClassFactory().deny("javax.net.ssl.*"); + super.getClassFactory().deny("com.unboundid.ldap.*"); } } diff --git a/serializer/seata-serializer-hessian/src/test/java/io/seata/serializer/hessian/HessianSerializerTest.java b/serializer/seata-serializer-hessian/src/test/java/io/seata/serializer/hessian/HessianSerializerTest.java index a2d3b0e48ab..c5a34f50777 100644 --- a/serializer/seata-serializer-hessian/src/test/java/io/seata/serializer/hessian/HessianSerializerTest.java +++ b/serializer/seata-serializer-hessian/src/test/java/io/seata/serializer/hessian/HessianSerializerTest.java @@ -15,12 +15,19 @@ */ package io.seata.serializer.hessian; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import javax.naming.InitialContext; + import io.seata.core.exception.TransactionExceptionCode; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.protocol.ResultCode; import io.seata.core.protocol.transaction.BranchCommitRequest; import io.seata.core.protocol.transaction.BranchCommitResponse; +import io.seata.core.protocol.transaction.BranchRollbackRequest; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -82,4 +89,52 @@ public void testBranchCommitResponse() { } + @Test + public void testWhitelist() throws ClassNotFoundException { + //basic type Integer + Class clazz = HessianSerializerFactory.getInstance().getClassFactory().load(Integer.class.getCanonicalName()); + assertThat(!clazz.equals(HashMap.class)); + + //collection type List + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(List.class.getCanonicalName()); + assertThat(!clazz.equals(HashMap.class)); + + //String type + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(String.class.getCanonicalName()); + assertThat(!clazz.equals(HashMap.class)); + + //Number type + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(Number.class.getCanonicalName()); + assertThat(!clazz.equals(HashMap.class)); + + //HashMap type + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(HashSet.class.getCanonicalName()); + assertThat(!clazz.equals(HashMap.class)); + + //io.seata.core.protocol.transaction.BranchRollbackRequest + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(BranchRollbackRequest.class.getCanonicalName()); + assertThat(!clazz.equals(HashMap.class)); + + //HashMap type + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(HashMap.class.getCanonicalName()); + assertThat(clazz.equals(HashMap.class)); + + //blackList Process + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(Process.class.getCanonicalName()); + assertThat(clazz.equals(HashMap.class)); + + //blackList System + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(System.class.getCanonicalName()); + assertThat(clazz.equals(HashMap.class)); + + //blackList Runtime + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(Runtime.class.getCanonicalName()); + assertThat(clazz.equals(HashMap.class)); + + //blackList InitialContext + clazz = HessianSerializerFactory.getInstance().getClassFactory().load(InitialContext.class.getCanonicalName()); + assertThat(clazz.equals(HashMap.class)); + + } + } From cb0a72749260086f40f2ab55c204983aec531e60 Mon Sep 17 00:00:00 2001 From: jimin Date: Sat, 1 Jul 2023 22:15:35 +0800 Subject: [PATCH 68/76] optimize: optimize github actions for CodeQL, skywalking-eyes (#5685) --- .github/workflows/build.yml | 10 +++--- .github/workflows/codeql-analysis.yml | 42 +++++--------------------- .github/workflows/license-checker.yaml | 16 +++++++--- .github/workflows/publish-docker.yml | 2 +- .github/workflows/test.yml | 8 ++--- changes/en-us/develop.md | 6 ++-- changes/zh-cn/develop.md | 1 + 7 files changed, 34 insertions(+), 51 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6839bbba2d8..6c369d7c53e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: steps: # step 1 - name: "Checkout" - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 # step 2 - name: "Set up Java JDK" uses: actions/setup-java@v2.5.0 @@ -50,7 +50,7 @@ jobs: steps: # step 1 - name: "Checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v3 # step 2 - name: "Set up QEMU" id: qemu @@ -61,6 +61,6 @@ jobs: docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ arm64v8/ubuntu:20.04 \ bash -exc 'apt-get update -y && \ - apt-get install maven -y && \ - mvn -version && \ - mvn -Prelease-seata -DskipTests clean install -U' + apt-get install maven -y && \ + mvn -version && \ + mvn -Prelease-seata -DskipTests clean install -U' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f7f2c925fac..f1b048aab00 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,14 +1,3 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# name: "CodeQL" on: @@ -30,43 +19,26 @@ jobs: fail-fast: false matrix: language: [ 'java' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: # step 1 - - name: "Checkout repository" - uses: actions/checkout@v2 + - name: "Checkout" + uses: actions/checkout@v3 # step 2: Initializes the CodeQL tools for scanning. - name: "Initialize CodeQL" - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main # step 3 # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: "Autobuild" - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # step 4 - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - # step 5 - name: "Perform CodeQL Analysis" - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" \ No newline at end of file diff --git a/.github/workflows/license-checker.yaml b/.github/workflows/license-checker.yaml index d3ac84bb88c..2ee9b5e0f52 100644 --- a/.github/workflows/license-checker.yaml +++ b/.github/workflows/license-checker.yaml @@ -8,17 +8,25 @@ jobs: check-license: runs-on: ubuntu-latest steps: - # step 1 + # step 1 clear cache + - name: Clear cache directory first before trying to restore from cache + run: sudo rm -rf $(go env GOMODCACHE) && sudo rm -rf $(go env GOCACHE) + shell: bash + # step 2 checkout - name: Checkout - uses: actions/checkout@v2.4.0 - # step 2 + uses: actions/checkout@v3 + # step 3 https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/ + - uses: actions/setup-node@v3 + with: + node-version: '14.x' + # step 4 check license - name: Check License Header uses: apache/skywalking-eyes/header@8fc52baabc14c86294d96034bcc194cfa7f76b05 with: log: info config: .licenserc.yaml mode: check - # step 3 + # step 5 heck dependencies - name: Check Dependencies' License uses: apache/skywalking-eyes/dependency@8fc52baabc14c86294d96034bcc194cfa7f76b05 with: diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index c2a1a60268c..65999b197f2 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -21,7 +21,7 @@ jobs: steps: # step 1 - name: "Checkout" - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 # step 2 - name: "Setup Java JDK" uses: actions/setup-java@v3.9.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2bb618dc5ce..7d9a4ea3dc7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,7 @@ jobs: steps: # step 1 - name: "Checkout" - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 # step 2 - name: "Set up Java JDK" uses: actions/setup-java@v2.5.0 @@ -66,7 +66,7 @@ jobs: steps: # step 1 - name: "Checkout" - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 # step 2 - name: "Set up Java JDK" uses: actions/setup-java@v2.5.0 @@ -106,7 +106,7 @@ jobs: steps: # step 1 - name: "Checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v3 # step 2 - name: "Set up QEMU" id: qemu @@ -117,7 +117,7 @@ jobs: docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ arm64v8/ubuntu:20.04 \ bash -exc 'apt-get update -y && \ - apt-get install maven -y' + apt-get install maven -y' # step 4 - name: "Print maven version" run: ./mvnw -version diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index f18353c2d2c..8a3233baeac 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -64,11 +64,13 @@ Add changes here for all PR submitted to the develop branch. - [[#5646](https://github.com/seata/seata/pull/5646)] refactor ColumnUtils and EscapeHandler - [[#5648](https://github.com/seata/seata/pull/5648)] optimize server logs print - [[#5647](https://github.com/seata/seata/pull/5647)] support case-sensitive attributes for table and column metadata -- [[#5683](https://github.com/seata/seata/pull/5683)] optimize escape character for case of columnNames +- [[#5678](https://github.com/seata/seata/pull/5678)] optimize escape character for case of columnNames +- [[#5684](https://github.com/seata/seata/pull/5684)] optimize github actions for CodeQL, skywalking-eyes and checkout + ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities -- [[#5642](https://github.com/seata/seata/pull/5642)] add Hessian Serializer WhiteDenyList +- [[#5683](https://github.com/seata/seata/pull/5683)] add Hessian Serializer WhiteDenyList ### test: - [[#5380](https://github.com/seata/seata/pull/5380)] fix UpdateExecutorTest failed diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 672312b9eab..4d20933dc90 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -65,6 +65,7 @@ - [[#5648](https://github.com/seata/seata/pull/5648)] 优化Server日志输出 - [[#5647](https://github.com/seata/seata/pull/5647)] 支持表和列元数据大小写敏感设置 - [[#5678](https://github.com/seata/seata/pull/5678)] 优化大小写转义符 +- [[#5684](https://github.com/seata/seata/pull/5684)] 优化 CodeQL, skywalking-eyes 和 checkout 等 actions ### security: - [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本 From 8a92c5bb536910206c72ea3d9d257f475195da41 Mon Sep 17 00:00:00 2001 From: jimin Date: Sat, 1 Jul 2023 22:50:47 +0800 Subject: [PATCH 69/76] bugfix: fix console jwt error (#5690) --- changes/en-us/develop.md | 2 ++ changes/zh-cn/develop.md | 2 ++ console/src/main/resources/static/index.html | 6 +++--- server/src/main/resources/application.yml | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 8a3233baeac..ac4e8e9a02b 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -42,6 +42,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5659](https://github.com/seata/seata/pull/5659)] fix the issue of case sensitivity enforcement on the database after adding escape characters to keywords - [[#5663](https://github.com/seata/seata/pull/5663)] bugfix: fix the timeout is null when the connectionProxyXA connection is reused - [[#5675](https://github.com/seata/seata/pull/5675)] bugfix: fix compatibility between xxx.grouplist and grouplist.xxx configuration items +- [[#5690](https://github.com/seata/seata/pull/5690)] fix console print `unauthorized error` ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more @@ -98,6 +99,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [l81893521](https://github.com/l81893521) - [liuqiufeng](https://github.com/liuqiufeng) - [yixia](https://github.com/wt-better) +- [jumtp](https://github.com/jumtp) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 4d20933dc90..4089687860b 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -42,6 +42,7 @@ - [[#5659](https://github.com/seata/seata/pull/5659)] 修复后镜像查询时增加关键字转义符导致数据库强制开启大小写校验引起的sql异常 - [[#5663](https://github.com/seata/seata/pull/5663)] 修复connectionProxyXA连接复用时timeout为null - [[#5675](https://github.com/seata/seata/pull/5675)] 修复 xxx.grouplist 和 grouplist.xxx 配置项兼容问题 +- [[#5690](https://github.com/seata/seata/pull/5690)] 修复控制台打印 `unauthorized error` 问题 ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 @@ -97,6 +98,7 @@ - [l81893521](https://github.com/l81893521) - [liuqiufeng](https://github.com/liuqiufeng) - [yixia](https://github.com/wt-better) +- [jumtp](https://github.com/jumtp) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/console/src/main/resources/static/index.html b/console/src/main/resources/static/index.html index 575163dd569..72ffa50518f 100644 --- a/console/src/main/resources/static/index.html +++ b/console/src/main/resources/static/index.html @@ -23,9 +23,9 @@ Seata - - - + + + diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index 16822c55e18..03dcee74114 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -51,4 +51,4 @@ seata: secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017 tokenValidityInMilliseconds: 1800000 ignore: - urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login \ No newline at end of file + urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login \ No newline at end of file From 23244cff94dcd1d8e0bdae1178abda902c0ffb7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?WangLiang/=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Sun, 2 Jul 2023 18:02:02 +0800 Subject: [PATCH 70/76] feature: support `native-image` for `seata-client` (#5476) --- .github/workflows/test.yml | 2 +- .licenserc.yaml | 1 + all/pom.xml | 33 +- build/pom.xml | 2 +- changes/en-us/develop.md | 2 +- changes/zh-cn/develop.md | 2 +- .../java/io/seata/common/aot/NativeUtils.java | 63 ++ .../common/loader/EnhancedServiceLoader.java | 9 +- .../io/seata/common/util/ReflectionUtil.java | 19 + .../seata-common/resource-config.json | 66 ++ .../io.seata/seata-common/reflect-config.json | 14 + .../seata-compressor-7z/reflect-config.json | 14 + .../reflect-config.json | 14 + .../reflect-config.json | 14 + .../seata-compressor-gzip/reflect-config.json | 14 + .../seata-compressor-lz4/reflect-config.json | 14 + .../seata-compressor-zip/reflect-config.json | 14 + .../seata-compressor-zstd/reflect-config.json | 14 + .../seata-config-apollo/reflect-config.json | 14 + .../seata-config-consul/reflect-config.json | 14 + config/seata-config-core/pom.xml | 4 - .../io/seata/config/ConfigurationCache.java | 13 +- .../seata-config-core/proxy-config.json | 10 + .../seata-config-core/reflect-config.json | 56 ++ .../services/io.seata.config.file.FileConfig | 2 +- .../seata-config-custom/reflect-config.json | 14 + .../seata-config-custom/reflect-config.json | 14 + .../seata-config-etcd3/reflect-config.json | 14 + .../seata-config-nacos/reflect-config.json | 14 + .../reflect-config.json | 14 + .../seata-config-zk/reflect-config.json | 14 + .../seata-console/resource-config.json | 9 + .../io.seata/seata-core/reflect-config.json | 188 +++++ .../reflect-config.json | 14 + .../seata-discovery-core/reflect-config.json | 74 ++ .../reflect-config.json | 14 + .../reflect-config.json | 14 + .../seata-discovery-etcd3/reflect-config.json | 14 + .../reflect-config.json | 14 + .../seata-discovery-nacos/reflect-config.json | 14 + .../seata-discovery-redis/reflect-config.json | 14 + .../seata-discovery-sofa/reflect-config.json | 14 + .../seata-discovery-zk/reflect-config.json | 14 + .../seata-dubbo-alibaba/reflect-config.json | 14 + .../io.seata/seata-hsf/reflect-config.json | 14 + .../io.seata/seata-motan/reflect-config.json | 14 + .../seata-sofa-rpc/reflect-config.json | 26 + .../reflect-config.json | 14 + .../reflect-config.json | 14 + pom.xml | 2 + .../rm/datasource/util/SeataXAResource.java | 3 +- .../native-image.properties | 16 + .../seata-rm-datasource/reflect-config.json | 654 ++++++++++++++++++ .../seata-rm-datasource/reflect-config.json | 74 ++ .../io.seata.sqlparser.SQLRecognizerFactory | 18 +- ...sqlparser.druid.SQLOperateRecognizerHolder | 16 - .../io.seata.sqlparser.util.DbTypeParser | 18 +- .../reflect-config.json | 14 + .../seata-saga-engine/reflect-config.json | 50 ++ .../seata-saga-rm/reflect-config.json | 26 + .../io.seata.core.model.ResourceManager | 2 +- .../seata-saga-statelang/reflect-config.json | 26 + .../reflect-config.json | 14 + .../SpringBootConfigurationProvider.java | 39 +- .../proxy-config.json | 10 + .../reflect-config.json | 14 + .../seata-serializer-fst/reflect-config.json | 14 + .../reflect-config.json | 14 + .../seata-serializer-kryo/reflect-config.json | 14 + .../reflect-config.json | 14 + .../reflect-config.json | 14 + server/pom.xml | 117 +++- .../io/seata/server/ServerApplication.java | 27 +- .../controller/BranchSessionController.java | 3 +- .../controller/GlobalLockController.java | 7 +- .../controller/GlobalSessionController.java | 8 +- .../io.seata/server/reflect-config.json | 362 ++++++++++ .../io.seata/server/resource-config.json | 21 + spring-aot/pom.xml | 58 ++ spring-aot/seata-spring-aot-client/pom.xml | 51 ++ ...aLocalTCCBeanRegistrationAotProcessor.java | 89 +++ .../resources/META-INF/spring/aot.factories | 2 + spring-aot/seata-spring-aot-core/pom.xml | 39 ++ .../java/io/seata/spring/aot/AotUtils.java | 247 +++++++ .../io/seata/spring/aot/ResourceUtil.java | 40 ++ .../spring/aot/SeataServicesRuntimeHints.java | 68 ++ spring-framework-fake-for-java8/pom.xml | 63 ++ .../aot/generate/GenerationContext.java | 38 + .../aot/hint/ExecutableMode.java | 37 + .../aot/hint/MemberCategory.java | 53 ++ .../springframework/aot/hint/ProxyHints.java | 43 ++ .../aot/hint/ReflectionHints.java | 90 +++ .../aot/hint/ResourceHints.java | 70 ++ .../aot/hint/RuntimeHints.java | 48 ++ .../aot/hint/RuntimeHintsRegistrar.java | 33 + .../aot/hint/SerializationHints.java | 50 ++ .../aot/hint/TypeReference.java | 54 ++ .../aot/BeanRegistrationAotContribution.java | 43 ++ .../aot/BeanRegistrationAotProcessor.java | 39 ++ .../factory/aot/BeanRegistrationCode.java | 33 + .../beans/factory/support/RegisteredBean.java | 97 +++ .../annotation/GlobalTransactionScanner.java | 25 + .../SeataAutoDataSourceProxyCreator.java | 12 +- .../io.seata/seata-spring/reflect-config.json | 57 ++ .../seata-sqlparser-antlr/reflect-config.json | 38 + .../io.seata.sqlparser.SQLRecognizerFactory | 2 +- ...sqlparser.antlr.SQLOperateRecognizerHolder | 2 +- .../seata-sqlparser-druid/reflect-config.json | 86 +++ .../resource-config.json | 12 + .../io.seata.sqlparser.SQLRecognizerFactory | 2 +- .../io.seata.sqlparser.util.DbTypeParser | 2 +- style/seata_suppressions.xml | 2 + .../io.seata/seata-tcc/reflect-config.json | 98 +++ .../io.seata.core.model.ResourceManager | 2 +- .../io.seata/seata-test/reflect-config.json | 50 ++ .../io.seata/seata-tm/reflect-config.json | 14 + 116 files changed, 4288 insertions(+), 113 deletions(-) create mode 100644 common/src/main/java/io/seata/common/aot/NativeUtils.java create mode 100644 common/src/main/resources/META-INF/native-image/io.seata/seata-common/resource-config.json create mode 100644 common/src/test/resources/META-INF/native-image/io.seata/seata-common/reflect-config.json create mode 100644 compressor/seata-compressor-7z/src/main/resources/META-INF/native-image/io.seata/seata-compressor-7z/reflect-config.json create mode 100644 compressor/seata-compressor-bzip2/src/main/resources/META-INF/native-image/io.seata/seata-compressor-bzip2/reflect-config.json create mode 100644 compressor/seata-compressor-deflater/src/main/resources/META-INF/native-image/io.seata/seata-compressor-deflater/reflect-config.json create mode 100644 compressor/seata-compressor-gzip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-gzip/reflect-config.json create mode 100644 compressor/seata-compressor-lz4/src/main/resources/META-INF/native-image/io.seata/seata-compressor-lz4/reflect-config.json create mode 100644 compressor/seata-compressor-zip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zip/reflect-config.json create mode 100644 compressor/seata-compressor-zstd/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zstd/reflect-config.json create mode 100644 config/seata-config-apollo/src/main/resources/META-INF/native-image/io.seata/seata-config-apollo/reflect-config.json create mode 100644 config/seata-config-consul/src/main/resources/META-INF/native-image/io.seata/seata-config-consul/reflect-config.json create mode 100644 config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/proxy-config.json create mode 100644 config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/reflect-config.json create mode 100644 config/seata-config-custom/src/main/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json create mode 100644 config/seata-config-custom/src/test/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json create mode 100644 config/seata-config-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-config-etcd3/reflect-config.json create mode 100644 config/seata-config-nacos/src/main/resources/META-INF/native-image/io.seata/seata-config-nacos/reflect-config.json create mode 100644 config/seata-config-spring-cloud/src/main/resources/META-INF/native-image/io.seata/seata-config-spring-cloud/reflect-config.json create mode 100644 config/seata-config-zk/src/main/resources/META-INF/native-image/io.seata/seata-config-zk/reflect-config.json create mode 100644 console/src/main/resources/META-INF/native-image/io.seata/seata-console/resource-config.json create mode 100644 core/src/main/resources/META-INF/native-image/io.seata/seata-core/reflect-config.json create mode 100644 discovery/seata-discovery-consul/src/main/resources/META-INF/native-image/io.seata/seata-discovery-consul/reflect-config.json create mode 100644 discovery/seata-discovery-core/src/main/resources/META-INF/native-image/io.seata/seata-discovery-core/reflect-config.json create mode 100644 discovery/seata-discovery-custom/src/main/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json create mode 100644 discovery/seata-discovery-custom/src/test/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json create mode 100644 discovery/seata-discovery-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-discovery-etcd3/reflect-config.json create mode 100644 discovery/seata-discovery-eureka/src/main/resources/META-INF/native-image/io.seata/seata-discovery-eureka/reflect-config.json create mode 100644 discovery/seata-discovery-nacos/src/main/resources/META-INF/native-image/io.seata/seata-discovery-nacos/reflect-config.json create mode 100644 discovery/seata-discovery-redis/src/main/resources/META-INF/native-image/io.seata/seata-discovery-redis/reflect-config.json create mode 100644 discovery/seata-discovery-sofa/src/main/resources/META-INF/native-image/io.seata/seata-discovery-sofa/reflect-config.json create mode 100644 discovery/seata-discovery-zk/src/main/resources/META-INF/native-image/io.seata/seata-discovery-zk/reflect-config.json create mode 100644 integration/dubbo-alibaba/src/main/resources/META-INF/native-image/io.seata/seata-dubbo-alibaba/reflect-config.json create mode 100644 integration/hsf/src/main/resources/META-INF/native-image/io.seata/seata-hsf/reflect-config.json create mode 100644 integration/motan/src/main/resources/META-INF/native-image/io.seata/seata-motan/reflect-config.json create mode 100644 integration/sofa-rpc/src/main/resources/META-INF/native-image/io.seata/seata-sofa-rpc/reflect-config.json create mode 100644 metrics/seata-metrics-exporter-prometheus/src/main/resources/META-INF/native-image/io.seata/seata-metrics-exporter-prometheus/reflect-config.json create mode 100644 metrics/seata-metrics-registry-compact/src/main/resources/META-INF/native-image/io.seata/seata-metrics-registry-compact/reflect-config.json create mode 100644 rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/native-image.properties create mode 100644 rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json create mode 100644 rm-datasource/src/test/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json create mode 100644 saga/seata-saga-engine-store/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine-store/reflect-config.json create mode 100644 saga/seata-saga-engine/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine/reflect-config.json create mode 100644 saga/seata-saga-rm/src/main/resources/META-INF/native-image/io.seata/seata-saga-rm/reflect-config.json create mode 100644 saga/seata-saga-statelang/src/main/resources/META-INF/native-image/io.seata/seata-saga-statelang/reflect-config.json create mode 100644 seata-plugin/seata-jackson-parser-oracle/src/main/resources/META-INF/native-image/io.seata/seata-jackson-parser-oracle/reflect-config.json create mode 100644 seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/proxy-config.json create mode 100644 seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/reflect-config.json create mode 100644 serializer/seata-serializer-fst/src/main/resources/META-INF/native-image/io.seata/seata-serializer-fst/reflect-config.json create mode 100644 serializer/seata-serializer-hessian/src/main/resources/META-INF/native-image/io.seata/seata-serializer-hessian/reflect-config.json create mode 100644 serializer/seata-serializer-kryo/src/main/resources/META-INF/native-image/io.seata/seata-serializer-kryo/reflect-config.json create mode 100644 serializer/seata-serializer-protobuf/src/main/resources/META-INF/native-image/io.seata/seata-serializer-protobuf/reflect-config.json create mode 100644 serializer/seata-serializer-seata/src/main/resources/META-INF/native-image/io.seata/seata-serializer-seata/reflect-config.json create mode 100644 server/src/main/resources/META-INF/native-image/io.seata/server/reflect-config.json create mode 100644 server/src/main/resources/META-INF/native-image/io.seata/server/resource-config.json create mode 100644 spring-aot/pom.xml create mode 100644 spring-aot/seata-spring-aot-client/pom.xml create mode 100644 spring-aot/seata-spring-aot-client/src/main/java/io/seata/spring/aot/SeataLocalTCCBeanRegistrationAotProcessor.java create mode 100644 spring-aot/seata-spring-aot-client/src/main/resources/META-INF/spring/aot.factories create mode 100644 spring-aot/seata-spring-aot-core/pom.xml create mode 100644 spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/AotUtils.java create mode 100644 spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/ResourceUtil.java create mode 100644 spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/SeataServicesRuntimeHints.java create mode 100644 spring-framework-fake-for-java8/pom.xml create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/generate/GenerationContext.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ExecutableMode.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/MemberCategory.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ProxyHints.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ReflectionHints.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ResourceHints.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHints.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHintsRegistrar.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/SerializationHints.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/TypeReference.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotProcessor.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCode.java create mode 100644 spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java create mode 100644 spring/src/main/resources/META-INF/native-image/io.seata/seata-spring/reflect-config.json create mode 100644 sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-antlr/reflect-config.json create mode 100644 sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/reflect-config.json create mode 100644 sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/resource-config.json create mode 100644 tcc/src/main/resources/META-INF/native-image/io.seata/seata-tcc/reflect-config.json create mode 100644 test/src/test/resources/META-INF/native-image/io.seata/seata-test/reflect-config.json create mode 100644 tm/src/main/resources/META-INF/native-image/io.seata/seata-tm/reflect-config.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7d9a4ea3dc7..c8ac1eaf267 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,7 +79,7 @@ jobs: # step 4 - name: "Test with Maven" run: | - ./mvnw -T 4C clean test -Dspring-boot.version=${{ matrix.springboot }} -Dcheckstyle.skip=false -Dlicense.skip=false -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; + ./mvnw -T 4C clean test -Dspring-boot.version=${{ matrix.springboot }} -Dcheckstyle.skip=true -Dlicense.skip=true -e -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; # job 3 arm64-test: diff --git a/.licenserc.yaml b/.licenserc.yaml index 699f39beee0..d295560cf1f 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -75,6 +75,7 @@ header: - 'ext/apm-seata-skywalking-plugin/config/agent.config' - 'server/src/main/resources/lua/redislocker/redislock.lua' - 'server/src/main/resources/banner.txt' + - '**/org/springframework/**' comment: on-failure diff --git a/all/pom.xml b/all/pom.xml index e0215683f9e..0bf311f1700 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -212,6 +212,16 @@ + + io.seata + seata-spring-aot-core + ${project.version} + + + io.seata + seata-spring-aot-client + ${project.version} + io.seata seata-tcc @@ -421,10 +431,6 @@ edas-sdk provided - - net.bytebuddy - byte-buddy - aopalliance aopalliance @@ -623,6 +629,13 @@ org.apache.maven.plugins maven-shade-plugin + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + package @@ -641,17 +654,17 @@ - + - + META-INF/spring.handlers - + META-INF/spring.schemas + + META-INF/spring/aot.factories + diff --git a/build/pom.xml b/build/pom.xml index 53aca9c1e3d..2e60d208149 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -103,7 +103,7 @@ 2.2.1 3.2.0 3.2.2 - 2.4.3 + 3.2.4 3.0.2 3.0.0 3.2.0 diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index ac4e8e9a02b..de23e996af3 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -3,7 +3,7 @@ Add changes here for all PR submitted to the develop branch. ### feature: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] support xxx +- [[#5476](https://github.com/seata/seata/pull/5476)] First support `native-image` for `seata-client` ### bugfix: - [[#5682](https://github.com/seata/seata/pull/5682)] fix saga mode replay context lost startParams diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index 4089687860b..98377d40790 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -3,7 +3,7 @@ ### feature: -- [[#xxx](https://github.com/seata/seata/pull/xxx)] 支持 xxx +- [[#5476](https://github.com/seata/seata/pull/5476)] seata客户端,首次支持 `native-image` ### bugfix: - [[#5682](https://github.com/seata/seata/pull/5682)] 修复saga模式下replay context丢失startParams问题 diff --git a/common/src/main/java/io/seata/common/aot/NativeUtils.java b/common/src/main/java/io/seata/common/aot/NativeUtils.java new file mode 100644 index 00000000000..e708d9a78a5 --- /dev/null +++ b/common/src/main/java/io/seata/common/aot/NativeUtils.java @@ -0,0 +1,63 @@ +/* + * Copyright 1999-2019 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.common.aot; + +/** + * The native utils + * + * @author wang.liang + */ +public class NativeUtils { + + /** + * The native-image code + * + * @see ImageInfo.java + */ + private static final String NATIVE_IMAGE_CODE = System.getProperty("org.graalvm.nativeimage.imagecode"); + + + public static final String SPRING_AOT_PROCESSING = "spring.aot.processing"; + + + /** + * Whether Spring-AOT processing + * + * @return the boolean + */ + public static boolean isSpringAotProcessing() { + return "true".equalsIgnoreCase(System.getProperty(SPRING_AOT_PROCESSING)); + } + + /** + * Gets the native-image code. + * + * @return the native-image code + */ + public static String getNativeImageCode() { + return NATIVE_IMAGE_CODE; + } + + /** + * Whether run in native-image + * + * @return the boolean + * @see org.springframework.core.NativeDetector#inNativeImage() + */ + public static boolean inNativeImage() { + return NATIVE_IMAGE_CODE != null; + } +} diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index dc56d50f76c..69f7189a099 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -44,6 +44,9 @@ */ public class EnhancedServiceLoader { + public static final String SERVICES_DIRECTORY = "META-INF/services/"; + public static final String SEATA_DIRECTORY = "META-INF/seata/"; + /** * Class->InnerEnhancedServiceLoader map */ @@ -245,8 +248,6 @@ private static ClassLoader findClassLoader() { private static class InnerEnhancedServiceLoader { private static final Logger LOGGER = LoggerFactory.getLogger(InnerEnhancedServiceLoader.class); - private static final String SERVICES_DIRECTORY = "META-INF/services/"; - private static final String SEATA_DIRECTORY = "META-INF/seata/"; private final Class type; private final Holder>> definitionsHolder = new Holder<>(); @@ -555,7 +556,9 @@ private void loadFile(String dir, ClassLoader loader, List getWrappedClass(Class clazz) { return clazz; } + public static boolean isJavaClass(Class clazz) { + return clazz != null && clazz.getClassLoader() == null; + } + + /** + * Whether the class exists + * + * @param className the class name + * @return the boolean + */ + public static boolean existsClass(String className) { + try { + getClassByName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + //endregion diff --git a/common/src/main/resources/META-INF/native-image/io.seata/seata-common/resource-config.json b/common/src/main/resources/META-INF/native-image/io.seata/seata-common/resource-config.json new file mode 100644 index 00000000000..a8a21ce022d --- /dev/null +++ b/common/src/main/resources/META-INF/native-image/io.seata/seata-common/resource-config.json @@ -0,0 +1,66 @@ +{ + "resources": { + "includes": [ + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/services\/io.seata.\\E.*" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/seata\/io.seata.\\E.*" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/services\/com.alibaba.dubbo.rpc.Filter\\E" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/seata\/com.alibaba.dubbo.rpc.Filter\\E" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/services\/com.alipay.sofa.rpc.filter.Filter\\E" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/seata\/com.alipay.sofa.rpc.filter.Filter\\E" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/services\/com.taobao.hsf.invocation.filter.RPCFilter\\E" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/seata\/com.taobao.hsf.invocation.filter.RPCFilter\\E" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/services\/com.weibo.api.motan.filter.Filter\\E" + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.EnhancedServiceLoader" + }, + "pattern": "\\QMETA-INF\/seata\/com.weibo.api.motan.filter.Filter\\E" + } + ] + } +} diff --git a/common/src/test/resources/META-INF/native-image/io.seata/seata-common/reflect-config.json b/common/src/test/resources/META-INF/native-image/io.seata/seata-common/reflect-config.json new file mode 100644 index 00000000000..1dc92069584 --- /dev/null +++ b/common/src/test/resources/META-INF/native-image/io.seata/seata-common/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.common.loader.Hello" + }, + "name": "io.seata.common.loader.ChineseHello", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/compressor/seata-compressor-7z/src/main/resources/META-INF/native-image/io.seata/seata-compressor-7z/reflect-config.json b/compressor/seata-compressor-7z/src/main/resources/META-INF/native-image/io.seata/seata-compressor-7z/reflect-config.json new file mode 100644 index 00000000000..b49e8b6c200 --- /dev/null +++ b/compressor/seata-compressor-7z/src/main/resources/META-INF/native-image/io.seata/seata-compressor-7z/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.compressor.Compressor" + }, + "name": "io.seata.compressor.sevenz.SevenZCompressor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/compressor/seata-compressor-bzip2/src/main/resources/META-INF/native-image/io.seata/seata-compressor-bzip2/reflect-config.json b/compressor/seata-compressor-bzip2/src/main/resources/META-INF/native-image/io.seata/seata-compressor-bzip2/reflect-config.json new file mode 100644 index 00000000000..f5db3d44afc --- /dev/null +++ b/compressor/seata-compressor-bzip2/src/main/resources/META-INF/native-image/io.seata/seata-compressor-bzip2/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.compressor.Compressor" + }, + "name": "io.seata.compressor.bzip2.BZip2Compressor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/compressor/seata-compressor-deflater/src/main/resources/META-INF/native-image/io.seata/seata-compressor-deflater/reflect-config.json b/compressor/seata-compressor-deflater/src/main/resources/META-INF/native-image/io.seata/seata-compressor-deflater/reflect-config.json new file mode 100644 index 00000000000..82cae57a764 --- /dev/null +++ b/compressor/seata-compressor-deflater/src/main/resources/META-INF/native-image/io.seata/seata-compressor-deflater/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.compressor.Compressor" + }, + "name": "io.seata.compressor.deflater.DeflaterCompressor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/compressor/seata-compressor-gzip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-gzip/reflect-config.json b/compressor/seata-compressor-gzip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-gzip/reflect-config.json new file mode 100644 index 00000000000..e86eb53c3e1 --- /dev/null +++ b/compressor/seata-compressor-gzip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-gzip/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.compressor.Compressor" + }, + "name": "io.seata.compressor.gzip.GzipCompressor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/compressor/seata-compressor-lz4/src/main/resources/META-INF/native-image/io.seata/seata-compressor-lz4/reflect-config.json b/compressor/seata-compressor-lz4/src/main/resources/META-INF/native-image/io.seata/seata-compressor-lz4/reflect-config.json new file mode 100644 index 00000000000..a0303f660de --- /dev/null +++ b/compressor/seata-compressor-lz4/src/main/resources/META-INF/native-image/io.seata/seata-compressor-lz4/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.compressor.Compressor" + }, + "name": "io.seata.compressor.lz4.Lz4Compressor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/compressor/seata-compressor-zip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zip/reflect-config.json b/compressor/seata-compressor-zip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zip/reflect-config.json new file mode 100644 index 00000000000..8e052e52bdb --- /dev/null +++ b/compressor/seata-compressor-zip/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zip/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.compressor.Compressor" + }, + "name": "io.seata.compressor.zip.ZipCompressor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/compressor/seata-compressor-zstd/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zstd/reflect-config.json b/compressor/seata-compressor-zstd/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zstd/reflect-config.json new file mode 100644 index 00000000000..772676f43fe --- /dev/null +++ b/compressor/seata-compressor-zstd/src/main/resources/META-INF/native-image/io.seata/seata-compressor-zstd/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.compressor.Compressor" + }, + "name": "io.seata.compressor.zstd.ZstdCompressor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-apollo/src/main/resources/META-INF/native-image/io.seata/seata-config-apollo/reflect-config.json b/config/seata-config-apollo/src/main/resources/META-INF/native-image/io.seata/seata-config-apollo/reflect-config.json new file mode 100644 index 00000000000..d5dad7e68db --- /dev/null +++ b/config/seata-config-apollo/src/main/resources/META-INF/native-image/io.seata/seata-config-apollo/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.apollo.ApolloConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-consul/src/main/resources/META-INF/native-image/io.seata/seata-config-consul/reflect-config.json b/config/seata-config-consul/src/main/resources/META-INF/native-image/io.seata/seata-config-consul/reflect-config.json new file mode 100644 index 00000000000..575a55ecc9e --- /dev/null +++ b/config/seata-config-consul/src/main/resources/META-INF/native-image/io.seata/seata-config-consul/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.consul.ConsulConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-core/pom.xml b/config/seata-config-core/pom.xml index 72098b12471..f167cca61e2 100644 --- a/config/seata-config-core/pom.xml +++ b/config/seata-config-core/pom.xml @@ -40,10 +40,6 @@ org.yaml snakeyaml - - net.bytebuddy - byte-buddy - diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java index e837ce78fae..f3e6bd6c224 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java @@ -15,17 +15,16 @@ */ package io.seata.config; +import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; + import io.seata.common.util.CollectionUtils; import io.seata.common.util.DurationUtil; import io.seata.common.util.StringUtils; -import net.bytebuddy.ByteBuddy; -import net.bytebuddy.implementation.InvocationHandlerAdapter; -import net.bytebuddy.matcher.ElementMatchers; /** * @author funkye @@ -101,8 +100,8 @@ public void onChangeEvent(ConfigurationChangeEvent event) { } public Configuration proxy(Configuration originalConfiguration) throws Exception { - return new ByteBuddy().subclass(Configuration.class).method(ElementMatchers.any()) - .intercept(InvocationHandlerAdapter.of((proxy, method, args) -> { + return (Configuration)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Configuration.class} + , (proxy, method, args) -> { String methodName = method.getName(); if (methodName.startsWith(METHOD_PREFIX) && !methodName.equalsIgnoreCase(METHOD_LATEST_CONFIG)) { String rawDataId = (String)args[0]; @@ -126,8 +125,8 @@ public Configuration proxy(Configuration originalConfiguration) throws Exception return wrapper == null ? null : wrapper.convertData(type); } return method.invoke(originalConfiguration, args); - })).make().load(originalConfiguration.getClass().getClassLoader()).getLoaded().getDeclaredConstructor() - .newInstance(); + } + ); } private static class ConfigurationCacheInstance { diff --git a/config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/proxy-config.json b/config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/proxy-config.json new file mode 100644 index 00000000000..e46ef9962f0 --- /dev/null +++ b/config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/proxy-config.json @@ -0,0 +1,10 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationCache" + }, + "interfaces": [ + "io.seata.config.Configuration" + ] + } +] \ No newline at end of file diff --git a/config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/reflect-config.json b/config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/reflect-config.json new file mode 100644 index 00000000000..361153750e9 --- /dev/null +++ b/config/seata-config-core/src/main/resources/META-INF/native-image/io.seata/seata-config-core/reflect-config.json @@ -0,0 +1,56 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.file.FileConfig" + }, + "name": "io.seata.config.file.SimpleFileConfig", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.io.File", + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.config.file.FileConfig" + }, + "name": "io.seata.config.file.YamlFileConfig", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.io.File", + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.config.processor.Processor" + }, + "name": "io.seata.config.processor.ProcessorProperties", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.config.processor.Processor" + }, + "name": "io.seata.config.processor.ProcessorYaml", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.file.FileConfig b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.file.FileConfig index 911c3d91a46..b44f1b5ce05 100644 --- a/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.file.FileConfig +++ b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.file.FileConfig @@ -1,2 +1,2 @@ io.seata.config.file.SimpleFileConfig -io.seata.config.file.YamlFileConfig +io.seata.config.file.YamlFileConfig \ No newline at end of file diff --git a/config/seata-config-custom/src/main/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json b/config/seata-config-custom/src/main/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json new file mode 100644 index 00000000000..9cece512be6 --- /dev/null +++ b/config/seata-config-custom/src/main/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.custom.CustomConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-custom/src/test/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json b/config/seata-config-custom/src/test/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json new file mode 100644 index 00000000000..babebe2a8f3 --- /dev/null +++ b/config/seata-config-custom/src/test/resources/META-INF/native-image/io.seata/seata-config-custom/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.CustomConfigurationProviderForTest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-config-etcd3/reflect-config.json b/config/seata-config-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-config-etcd3/reflect-config.json new file mode 100644 index 00000000000..00da19d813a --- /dev/null +++ b/config/seata-config-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-config-etcd3/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.etcd3.EtcdConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-nacos/src/main/resources/META-INF/native-image/io.seata/seata-config-nacos/reflect-config.json b/config/seata-config-nacos/src/main/resources/META-INF/native-image/io.seata/seata-config-nacos/reflect-config.json new file mode 100644 index 00000000000..c8ed1707fce --- /dev/null +++ b/config/seata-config-nacos/src/main/resources/META-INF/native-image/io.seata/seata-config-nacos/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.nacos.NacosConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-spring-cloud/src/main/resources/META-INF/native-image/io.seata/seata-config-spring-cloud/reflect-config.json b/config/seata-config-spring-cloud/src/main/resources/META-INF/native-image/io.seata/seata-config-spring-cloud/reflect-config.json new file mode 100644 index 00000000000..05f33a9d39b --- /dev/null +++ b/config/seata-config-spring-cloud/src/main/resources/META-INF/native-image/io.seata/seata-config-spring-cloud/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.springcloud.SpringCloudConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/config/seata-config-zk/src/main/resources/META-INF/native-image/io.seata/seata-config-zk/reflect-config.json b/config/seata-config-zk/src/main/resources/META-INF/native-image/io.seata/seata-config-zk/reflect-config.json new file mode 100644 index 00000000000..b3ed5b43182 --- /dev/null +++ b/config/seata-config-zk/src/main/resources/META-INF/native-image/io.seata/seata-config-zk/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ConfigurationProvider" + }, + "name": "io.seata.config.zk.ZookeeperConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/console/src/main/resources/META-INF/native-image/io.seata/seata-console/resource-config.json b/console/src/main/resources/META-INF/native-image/io.seata/seata-console/resource-config.json new file mode 100644 index 00000000000..2128dbb992b --- /dev/null +++ b/console/src/main/resources/META-INF/native-image/io.seata/seata-console/resource-config.json @@ -0,0 +1,9 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qstatic\/\\E.*" + } + ] + } +} diff --git a/core/src/main/resources/META-INF/native-image/io.seata/seata-core/reflect-config.json b/core/src/main/resources/META-INF/native-image/io.seata/seata-core/reflect-config.json new file mode 100644 index 00000000000..ec2f79715c4 --- /dev/null +++ b/core/src/main/resources/META-INF/native-image/io.seata/seata-core/reflect-config.json @@ -0,0 +1,188 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.constants.DubboConstants" + }, + "name": "org.apache.dubbo.rpc.RpcContext" + }, + { + "condition": { + "typeReachable": "io.seata.core.serializer.SerializerServiceLoader" + }, + "name": "io.seata.serializer.protobuf.ProtobufSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.auth.AuthSigner" + }, + "name": "io.seata.core.auth.DefaultAuthSigner", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.context.ContextCore" + }, + "name": "io.seata.core.context.ThreadLocalContextCore", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.context.ContextCore" + }, + "name": "io.seata.core.context.FastThreadLocalContextCore", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.rpc.hook.RpcHook" + }, + "name": "io.seata.core.rpc.hook.StatusRpcHook", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.lock.LockStoreSql" + }, + "name": "io.seata.core.store.db.sql.lock.MysqlLockStoreSql", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.lock.LockStoreSql" + }, + "name": "io.seata.core.store.db.sql.lock.OracleLockStoreSql", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.lock.LockStoreSql" + }, + "name": "io.seata.core.store.db.sql.lock.OceanbaseLockStoreSql", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.lock.LockStoreSql" + }, + "name": "io.seata.core.store.db.sql.lock.PostgresqlLockStoreSql", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.lock.LockStoreSql" + }, + "name": "io.seata.core.store.db.sql.lock.H2LockStoreSql", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.log.LogStoreSqls" + }, + "name": "io.seata.core.store.db.sql.log.MysqlLogStoreSqls", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.log.LogStoreSqls" + }, + "name": "io.seata.core.store.db.sql.log.OracleLogStoreSqls", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.log.LogStoreSqls" + }, + "name": "io.seata.core.store.db.sql.log.PostgresqlLogStoreSqls", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.log.LogStoreSqls" + }, + "name": "io.seata.core.store.db.sql.log.OceanbaseLogStoreSqls", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.sql.log.LogStoreSqls" + }, + "name": "io.seata.core.store.db.sql.log.H2LogStoreSqls", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-consul/src/main/resources/META-INF/native-image/io.seata/seata-discovery-consul/reflect-config.json b/discovery/seata-discovery-consul/src/main/resources/META-INF/native-image/io.seata/seata-discovery-consul/reflect-config.json new file mode 100644 index 00000000000..301a05860e6 --- /dev/null +++ b/discovery/seata-discovery-consul/src/main/resources/META-INF/native-image/io.seata/seata-discovery-consul/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.consul.ConsulRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-core/src/main/resources/META-INF/native-image/io.seata/seata-discovery-core/reflect-config.json b/discovery/seata-discovery-core/src/main/resources/META-INF/native-image/io.seata/seata-discovery-core/reflect-config.json new file mode 100644 index 00000000000..1a99d36dc36 --- /dev/null +++ b/discovery/seata-discovery-core/src/main/resources/META-INF/native-image/io.seata/seata-discovery-core/reflect-config.json @@ -0,0 +1,74 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.loadbalance.LoadBalance" + }, + "name": "io.seata.discovery.loadbalance.RoundRobinLoadBalance", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.discovery.loadbalance.LoadBalance" + }, + "name": "io.seata.discovery.loadbalance.RandomLoadBalance", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.discovery.loadbalance.LoadBalance" + }, + "name": "io.seata.discovery.loadbalance.ConsistentHashLoadBalance", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.discovery.loadbalance.LoadBalance" + }, + "name": "io.seata.discovery.loadbalance.LeastActiveLoadBalance", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.discovery.loadbalance.LoadBalance" + }, + "name": "io.seata.discovery.loadbalance.XIDLoadBalance", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.FileRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-custom/src/main/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json b/discovery/seata-discovery-custom/src/main/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json new file mode 100644 index 00000000000..a5116bcf110 --- /dev/null +++ b/discovery/seata-discovery-custom/src/main/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.custom.CustomRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-custom/src/test/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json b/discovery/seata-discovery-custom/src/test/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json new file mode 100644 index 00000000000..db8a46ecfdf --- /dev/null +++ b/discovery/seata-discovery-custom/src/test/resources/META-INF/native-image/io.seata/seata-discovery-custom/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.custom.CustomRegistryProviderForTest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-discovery-etcd3/reflect-config.json b/discovery/seata-discovery-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-discovery-etcd3/reflect-config.json new file mode 100644 index 00000000000..ad34373e0fd --- /dev/null +++ b/discovery/seata-discovery-etcd3/src/main/resources/META-INF/native-image/io.seata/seata-discovery-etcd3/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.etcd3.EtcdRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-eureka/src/main/resources/META-INF/native-image/io.seata/seata-discovery-eureka/reflect-config.json b/discovery/seata-discovery-eureka/src/main/resources/META-INF/native-image/io.seata/seata-discovery-eureka/reflect-config.json new file mode 100644 index 00000000000..a9a50eaa8ec --- /dev/null +++ b/discovery/seata-discovery-eureka/src/main/resources/META-INF/native-image/io.seata/seata-discovery-eureka/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.eureka.EurekaRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-nacos/src/main/resources/META-INF/native-image/io.seata/seata-discovery-nacos/reflect-config.json b/discovery/seata-discovery-nacos/src/main/resources/META-INF/native-image/io.seata/seata-discovery-nacos/reflect-config.json new file mode 100644 index 00000000000..391c28cdfe9 --- /dev/null +++ b/discovery/seata-discovery-nacos/src/main/resources/META-INF/native-image/io.seata/seata-discovery-nacos/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.nacos.NacosRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-redis/src/main/resources/META-INF/native-image/io.seata/seata-discovery-redis/reflect-config.json b/discovery/seata-discovery-redis/src/main/resources/META-INF/native-image/io.seata/seata-discovery-redis/reflect-config.json new file mode 100644 index 00000000000..fc26abafdff --- /dev/null +++ b/discovery/seata-discovery-redis/src/main/resources/META-INF/native-image/io.seata/seata-discovery-redis/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.redis.RedisRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-sofa/src/main/resources/META-INF/native-image/io.seata/seata-discovery-sofa/reflect-config.json b/discovery/seata-discovery-sofa/src/main/resources/META-INF/native-image/io.seata/seata-discovery-sofa/reflect-config.json new file mode 100644 index 00000000000..2e7bb3c74a5 --- /dev/null +++ b/discovery/seata-discovery-sofa/src/main/resources/META-INF/native-image/io.seata/seata-discovery-sofa/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.sofa.SofaRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/discovery/seata-discovery-zk/src/main/resources/META-INF/native-image/io.seata/seata-discovery-zk/reflect-config.json b/discovery/seata-discovery-zk/src/main/resources/META-INF/native-image/io.seata/seata-discovery-zk/reflect-config.json new file mode 100644 index 00000000000..301262c3441 --- /dev/null +++ b/discovery/seata-discovery-zk/src/main/resources/META-INF/native-image/io.seata/seata-discovery-zk/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.discovery.registry.RegistryProvider" + }, + "name": "io.seata.discovery.registry.zk.ZookeeperRegistryProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/integration/dubbo-alibaba/src/main/resources/META-INF/native-image/io.seata/seata-dubbo-alibaba/reflect-config.json b/integration/dubbo-alibaba/src/main/resources/META-INF/native-image/io.seata/seata-dubbo-alibaba/reflect-config.json new file mode 100644 index 00000000000..3aabc896ced --- /dev/null +++ b/integration/dubbo-alibaba/src/main/resources/META-INF/native-image/io.seata/seata-dubbo-alibaba/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "com.alibaba.dubbo.rpc.Filter" + }, + "name": "io.seata.integration.dubbo.alibaba.AlibabaDubboTransactionPropagationFilter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/integration/hsf/src/main/resources/META-INF/native-image/io.seata/seata-hsf/reflect-config.json b/integration/hsf/src/main/resources/META-INF/native-image/io.seata/seata-hsf/reflect-config.json new file mode 100644 index 00000000000..ec2ca59dbd1 --- /dev/null +++ b/integration/hsf/src/main/resources/META-INF/native-image/io.seata/seata-hsf/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "com.taobao.hsf.invocation.filter.RPCFilter" + }, + "name": "io.seata.integration.hsf.HsfTransactionFilter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/integration/motan/src/main/resources/META-INF/native-image/io.seata/seata-motan/reflect-config.json b/integration/motan/src/main/resources/META-INF/native-image/io.seata/seata-motan/reflect-config.json new file mode 100644 index 00000000000..20fc9d92636 --- /dev/null +++ b/integration/motan/src/main/resources/META-INF/native-image/io.seata/seata-motan/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "com.weibo.api.motan.filter.Filter" + }, + "name": "io.seata.integration.motan.MotanTransactionFilter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/integration/sofa-rpc/src/main/resources/META-INF/native-image/io.seata/seata-sofa-rpc/reflect-config.json b/integration/sofa-rpc/src/main/resources/META-INF/native-image/io.seata/seata-sofa-rpc/reflect-config.json new file mode 100644 index 00000000000..21eab9bdc03 --- /dev/null +++ b/integration/sofa-rpc/src/main/resources/META-INF/native-image/io.seata/seata-sofa-rpc/reflect-config.json @@ -0,0 +1,26 @@ +[ + { + "condition": { + "typeReachable": "com.alipay.sofa.rpc.filter.Filter" + }, + "name": "io.seata.integration.sofa.rpc.TransactionContextProviderFilter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.alipay.sofa.rpc.filter.Filter" + }, + "name": "io.seata.integration.sofa.rpc.TransactionContextConsumerFilter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/metrics/seata-metrics-exporter-prometheus/src/main/resources/META-INF/native-image/io.seata/seata-metrics-exporter-prometheus/reflect-config.json b/metrics/seata-metrics-exporter-prometheus/src/main/resources/META-INF/native-image/io.seata/seata-metrics-exporter-prometheus/reflect-config.json new file mode 100644 index 00000000000..2de446ee26e --- /dev/null +++ b/metrics/seata-metrics-exporter-prometheus/src/main/resources/META-INF/native-image/io.seata/seata-metrics-exporter-prometheus/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.metrics.exporter.Exporter" + }, + "name": "io.seata.metrics.exporter.prometheus.PrometheusExporter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/metrics/seata-metrics-registry-compact/src/main/resources/META-INF/native-image/io.seata/seata-metrics-registry-compact/reflect-config.json b/metrics/seata-metrics-registry-compact/src/main/resources/META-INF/native-image/io.seata/seata-metrics-registry-compact/reflect-config.json new file mode 100644 index 00000000000..5f241d7a6cd --- /dev/null +++ b/metrics/seata-metrics-registry-compact/src/main/resources/META-INF/native-image/io.seata/seata-metrics-registry-compact/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.metrics.registry.Registry" + }, + "name": "io.seata.metrics.registry.compact.CompactRegistry", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/pom.xml b/pom.xml index c60930ccad5..44071516399 100644 --- a/pom.xml +++ b/pom.xml @@ -53,6 +53,8 @@ rm rm-datasource spring + spring-aot + spring-framework-fake-for-java8 tcc test tm diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java b/rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java index 924fec80795..e185fb5477e 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/util/SeataXAResource.java @@ -22,7 +22,8 @@ * @since 2023/3/16 */ public interface SeataXAResource extends XAResource { + // OracleXAResource Loosely Coupled Branches - public static final int ORATRANSLOOSE = 65536; + int ORATRANSLOOSE = 65536; } diff --git a/rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/native-image.properties b/rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/native-image.properties new file mode 100644 index 00000000000..109df519963 --- /dev/null +++ b/rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/native-image.properties @@ -0,0 +1,16 @@ +# +# Copyright 1999-2019 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. + +Args = -H:+AddAllCharsets \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json b/rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json new file mode 100644 index 00000000000..64dde84a0af --- /dev/null +++ b/rm-datasource/src/main/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json @@ -0,0 +1,654 @@ +[ + { + "condition": { + "typeReachable": "com.mysql.jdbc.Driver" + }, + "name": "io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor", + "allDeclaredConstructors": true + }, + { + "condition": { + "typeReachable": "com.mysql.cj.jdbc.Driver" + }, + "name": "io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor", + "allDeclaredConstructors": true + }, + { + "condition": { + "typeReachable": "oracle.jdbc.driver.OracleDriver" + }, + "name": "io.seata.rm.datasource.exec.oracle.OracleInsertExecutor", + "allDeclaredConstructors": true + }, + { + "condition": { + "typeReachable": "org.postgresql.Driver" + }, + "name": "io.seata.rm.datasource.exec.postgresql.PostgresqlInsertExecutor", + "allDeclaredConstructors": true + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.BranchUndoLog" + }, + "name": "io.seata.rm.datasource.undo.BranchUndoLog", + "allPublicClasses": true, + "allPublicConstructors": true, + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allPublicMethods": true, + "allPublicFields": true, + "allDeclaredClasses": true + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.Row" + }, + "name": "io.seata.rm.datasource.sql.struct.Row", + "allPublicClasses": true, + "allPublicConstructors": true, + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allPublicMethods": true, + "allPublicFields": true, + "allDeclaredClasses": true + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.TableRecords" + }, + "name": "io.seata.rm.datasource.sql.struct.TableRecords", + "allPublicClasses": true, + "allPublicConstructors": true, + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allPublicMethods": true, + "allPublicFields": true, + "allDeclaredClasses": true + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.Field" + }, + "name": "io.seata.rm.datasource.sql.struct.Field", + "allPublicClasses": true, + "allPublicConstructors": true, + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allPublicMethods": true, + "allPublicFields": true, + "allDeclaredClasses": true + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords" + }, + "name": "io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords", + "allPublicClasses": true, + "allPublicConstructors": true, + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allPublicMethods": true, + "allPublicFields": true, + "allDeclaredClasses": true + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.SQLUndoLog" + }, + "name": "io.seata.rm.datasource.undo.SQLUndoLog", + "allPublicClasses": true, + "allPublicConstructors": true, + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allPublicMethods": true, + "allPublicFields": true, + "allDeclaredClasses": true + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache" + }, + "name": "com.github.benmanes.caffeine.cache.SIMSW", + "methods": [ + { + "name": "", + "parameterTypes": [ + "com.github.benmanes.caffeine.cache.Caffeine", + "com.github.benmanes.caffeine.cache.AsyncCacheLoader", + "boolean" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache" + }, + "name": "com.github.benmanes.caffeine.cache.PDWMS", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.util.XAUtils" + }, + "name": "oracle.jdbc.driver.T4CXAConnection", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.sql.Connection" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.util.XAUtils" + }, + "name": "oracle.jdbc.xa.client.OracleXAConnection", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.sql.Connection" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.jdbc.Util", + "methods": [ + { + "name": "isJdbc4", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.jdbc.Connection", + "methods": [ + { + "name": "getPinGlobalTxToPhysicalConnection", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.jdbc.jdbc2.optional.SuspendableXAConnection", + "methods": [ + { + "name": "", + "parameterTypes": [ + "com.mysql.jdbc.Connection" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.jdbc.jdbc2.optional.JDBC4SuspendableXAConnection", + "methods": [ + { + "name": "", + "parameterTypes": [ + "com.mysql.jdbc.Connection" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.jdbc.jdbc2.optional.MysqlXAConnection", + "methods": [ + { + "name": "", + "parameterTypes": [ + "com.mysql.jdbc.Connection", + "boolean" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.cj.jdbc.JdbcConnection", + "methods": [ + { + "name": "getPropertySet", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.mysql.cj.jdbc.JdbcConnection" + }, + "name": "com.mysql.cj.conf.PropertySet", + "methods": [ + { + "name": "getBooleanReadableProperty", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.mysql.cj.jdbc.JdbcConnection" + }, + "name": "com.mysql.cj.conf.ReadableProperty", + "methods": [ + { + "name": "getValue", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.mysql.cj.jdbc.JdbcConnection" + }, + "name": "com.mysql.cj.conf.RuntimeProperty", + "methods": [ + { + "name": "getValue", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.cj.api.jdbc.JdbcConnection", + "methods": [ + { + "name": "getPropertySet", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.mysql.cj.api.jdbc.JdbcConnection" + }, + "name": "com.mysql.cj.api.conf.PropertySet", + "methods": [ + { + "name": "getBooleanReadableProperty", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.mysql.cj.api.jdbc.JdbcConnection" + }, + "name": "com.mysql.cj.api.conf.ReadableProperty", + "methods": [ + { + "name": "getValue", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.cj.jdbc.SuspendableXAConnection", + "methods": [ + { + "name": "getInstance", + "parameterTypes": [ + "com.mysql.cj.jdbc.JdbcConnection" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.alibaba.druid.util.MySqlUtils" + }, + "name": "com.mysql.cj.jdbc.MysqlXAConnection", + "methods": [ + { + "name": "getInstance", + "parameterTypes": [ + "com.mysql.cj.jdbc.JdbcConnection", + "boolean" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.model.ResourceManager" + }, + "name": "io.seata.rm.datasource.DataSourceManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.model.ResourceManager" + }, + "name": "io.seata.rm.datasource.xa.ResourceManagerXA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.AbstractRMHandler" + }, + "name": "io.seata.rm.RMHandlerAT", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.AbstractRMHandler" + }, + "name": "io.seata.rm.RMHandlerXA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.exec.InsertExecutor" + }, + "name": "io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor", + "methods": [ + { + "name": "", + "parameterTypes": [ + "io.seata.rm.datasource.StatementProxy", + "io.seata.rm.datasource.exec.StatementCallback", + "io.seata.sqlparser.SQLRecognizer" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.exec.InsertExecutor" + }, + "name": "io.seata.rm.datasource.exec.oracle.OracleInsertExecutor", + "methods": [ + { + "name": "", + "parameterTypes": [ + "io.seata.rm.datasource.StatementProxy", + "io.seata.rm.datasource.exec.StatementCallback", + "io.seata.sqlparser.SQLRecognizer" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.exec.InsertExecutor" + }, + "name": "io.seata.rm.datasource.exec.postgresql.PostgresqlInsertExecutor", + "methods": [ + { + "name": "", + "parameterTypes": [ + "io.seata.rm.datasource.StatementProxy", + "io.seata.rm.datasource.exec.StatementCallback", + "io.seata.sqlparser.SQLRecognizer" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.TableMetaCache" + }, + "name": "io.seata.rm.datasource.sql.struct.cache.MysqlTableMetaCache", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.TableMetaCache" + }, + "name": "io.seata.rm.datasource.sql.struct.cache.OracleTableMetaCache", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.sql.struct.TableMetaCache" + }, + "name": "io.seata.rm.datasource.sql.struct.cache.PostgresqlTableMetaCache", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoExecutorHolder" + }, + "name": "io.seata.rm.datasource.undo.mysql.MySQLUndoExecutorHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoExecutorHolder" + }, + "name": "io.seata.rm.datasource.undo.oracle.OracleUndoExecutorHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoExecutorHolder" + }, + "name": "io.seata.rm.datasource.undo.postgresql.PostgresqlUndoExecutorHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogManager" + }, + "name": "io.seata.rm.datasource.undo.mysql.MySQLUndoLogManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogManager" + }, + "name": "io.seata.rm.datasource.undo.oracle.OracleUndoLogManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogManager" + }, + "name": "io.seata.rm.datasource.undo.postgresql.PostgresqlUndoLogManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogParser" + }, + "name": "io.seata.rm.datasource.undo.parser.FastjsonUndoLogParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogParser" + }, + "name": "io.seata.rm.datasource.undo.parser.JacksonUndoLogParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogParser" + }, + "name": "io.seata.rm.datasource.undo.parser.ProtostuffUndoLogParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogParser" + }, + "name": "io.seata.rm.datasource.undo.parser.KryoUndoLogParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.UndoLogParser" + }, + "name": "io.seata.rm.datasource.undo.parser.FstUndoLogParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.KeywordChecker" + }, + "name": "io.seata.rm.datasource.undo.oracle.keyword.OracleKeywordChecker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.KeywordChecker" + }, + "name": "io.seata.rm.datasource.undo.mysql.keyword.MySQLKeywordChecker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.KeywordChecker" + }, + "name": "io.seata.rm.datasource.undo.postgresql.keyword.PostgresqlKeywordChecker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/rm-datasource/src/test/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json b/rm-datasource/src/test/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json new file mode 100644 index 00000000000..2e31117e9ce --- /dev/null +++ b/rm-datasource/src/test/resources/META-INF/native-image/io.seata/seata-rm-datasource/reflect-config.json @@ -0,0 +1,74 @@ +[ + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.SQLOperateRecognizerHolder" + }, + "name": "io.seata.sqlparser.druid.mysql.MySQLOperateRecognizerHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.SQLOperateRecognizerHolder" + }, + "name": "io.seata.sqlparser.druid.oracle.OracleOperateRecognizerHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.SQLOperateRecognizerHolder" + }, + "name": "io.seata.sqlparser.druid.postgresql.PostgresqlOperateRecognizerHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.KeywordChecker" + }, + "name": "io.seata.rm.datasource.undo.h2.keyword.H2KeywordChecker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.SQLRecognizerFactory" + }, + "name": "io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.util.DbTypeParser" + }, + "name": "io.seata.sqlparser.druid.DruidDelegatingDbTypeParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory index f4b2f829968..e360e22891c 100644 --- a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory +++ b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory @@ -1,17 +1 @@ -# -# Copyright 1999-2019 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. -# - -io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory +io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory \ No newline at end of file diff --git a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.druid.SQLOperateRecognizerHolder b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.druid.SQLOperateRecognizerHolder index e7a870fdf31..0e290f5bd49 100644 --- a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.druid.SQLOperateRecognizerHolder +++ b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.druid.SQLOperateRecognizerHolder @@ -1,19 +1,3 @@ -# -# Copyright 1999-2019 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. -# - io.seata.sqlparser.druid.mysql.MySQLOperateRecognizerHolder io.seata.sqlparser.druid.oracle.OracleOperateRecognizerHolder io.seata.sqlparser.druid.postgresql.PostgresqlOperateRecognizerHolder \ No newline at end of file diff --git a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser index 983f0c35c92..a1eca58fd2a 100644 --- a/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser +++ b/rm-datasource/src/test/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser @@ -1,17 +1 @@ -# -# Copyright 1999-2019 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. -# - -io.seata.sqlparser.druid.DruidDelegatingDbTypeParser +io.seata.sqlparser.druid.DruidDelegatingDbTypeParser \ No newline at end of file diff --git a/saga/seata-saga-engine-store/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine-store/reflect-config.json b/saga/seata-saga-engine-store/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine-store/reflect-config.json new file mode 100644 index 00000000000..f9655b50f39 --- /dev/null +++ b/saga/seata-saga-engine-store/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine-store/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.saga.engine.pcext.StateHandlerInterceptor" + }, + "name": "io.seata.saga.engine.pcext.interceptors.InSagaBranchHandlerInterceptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine/reflect-config.json b/saga/seata-saga-engine/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine/reflect-config.json new file mode 100644 index 00000000000..c0e1bb0ad5c --- /dev/null +++ b/saga/seata-saga-engine/src/main/resources/META-INF/native-image/io.seata/seata-saga-engine/reflect-config.json @@ -0,0 +1,50 @@ +[ + { + "condition": { + "typeReachable": "io.seata.saga.engine.pcext.StateHandlerInterceptor" + }, + "name": "io.seata.saga.engine.pcext.interceptors.ServiceTaskHandlerInterceptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.saga.engine.pcext.StateHandlerInterceptor" + }, + "name": "io.seata.saga.engine.pcext.interceptors.ScriptTaskHandlerInterceptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.saga.engine.pcext.StateHandlerInterceptor" + }, + "name": "io.seata.saga.engine.pcext.interceptors.LoopTaskHandlerInterceptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.saga.engine.pcext.StateRouterInterceptor" + }, + "name": "io.seata.saga.engine.pcext.interceptors.EndStateRouterInterceptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/saga/seata-saga-rm/src/main/resources/META-INF/native-image/io.seata/seata-saga-rm/reflect-config.json b/saga/seata-saga-rm/src/main/resources/META-INF/native-image/io.seata/seata-saga-rm/reflect-config.json new file mode 100644 index 00000000000..3fa805310e7 --- /dev/null +++ b/saga/seata-saga-rm/src/main/resources/META-INF/native-image/io.seata/seata-saga-rm/reflect-config.json @@ -0,0 +1,26 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.model.ResourceManager" + }, + "name": "io.seata.saga.rm.SagaResourceManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.AbstractRMHandler" + }, + "name": "io.seata.saga.rm.RMHandlerSaga", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager b/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager index 69bc38af6f9..4ec5cba1d35 100644 --- a/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager +++ b/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager @@ -1 +1 @@ -io.seata.saga.rm.SagaResourceManager +io.seata.saga.rm.SagaResourceManager \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/resources/META-INF/native-image/io.seata/seata-saga-statelang/reflect-config.json b/saga/seata-saga-statelang/src/main/resources/META-INF/native-image/io.seata/seata-saga-statelang/reflect-config.json new file mode 100644 index 00000000000..006a4cb149b --- /dev/null +++ b/saga/seata-saga-statelang/src/main/resources/META-INF/native-image/io.seata/seata-saga-statelang/reflect-config.json @@ -0,0 +1,26 @@ +[ + { + "condition": { + "typeReachable": "io.seata.saga.statelang.parser.JsonParser" + }, + "name": "io.seata.saga.statelang.parser.impl.FastjsonParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.saga.statelang.parser.JsonParser" + }, + "name": "io.seata.saga.statelang.parser.impl.JacksonJsonParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/seata-plugin/seata-jackson-parser-oracle/src/main/resources/META-INF/native-image/io.seata/seata-jackson-parser-oracle/reflect-config.json b/seata-plugin/seata-jackson-parser-oracle/src/main/resources/META-INF/native-image/io.seata/seata-jackson-parser-oracle/reflect-config.json new file mode 100644 index 00000000000..057d1b94032 --- /dev/null +++ b/seata-plugin/seata-jackson-parser-oracle/src/main/resources/META-INF/native-image/io.seata/seata-jackson-parser-oracle/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.rm.datasource.undo.parser.spi.JacksonSerializer" + }, + "name": "io.seata.plugin.jackson.parser.oracle.OracleTimestampJacksonSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java index 4268bca0133..957d11dea8d 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java @@ -16,12 +16,13 @@ package io.seata.spring.boot.autoconfigure.provider; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.time.Duration; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Stream; import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.holder.ObjectHolder; @@ -32,8 +33,6 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cglib.proxy.Enhancer; -import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.lang.Nullable; @@ -60,8 +59,8 @@ public class SpringBootConfigurationProvider implements ExtConfigurationProvider @Override public Configuration provide(Configuration originalConfiguration) { - return (Configuration)Enhancer.create(originalConfiguration.getClass(), - (MethodInterceptor)(proxy, method, args, methodProxy) -> { + return (Configuration)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Configuration.class} + , (proxy, method, args) -> { if (method.getName().startsWith(INTERCEPT_METHOD_PREFIX) && args.length > 0) { Object result; String rawDataId = (String)args[0]; @@ -115,7 +114,7 @@ public Configuration provide(Configuration originalConfiguration) { }); } - private Object getDefaultValueFromPropertyObject(String dataId) throws IllegalAccessException { + private Object getDefaultValueFromPropertyObject(String dataId) throws IllegalAccessException, InvocationTargetException { String propertyPrefix = getPropertyPrefix(dataId); String propertySuffix = getPropertySuffix(dataId); @@ -149,17 +148,31 @@ private Object getDefaultValueFromPropertyObject(String dataId) throws IllegalAc * @author xingfudeshi@gmail.com */ @Nullable - private Object getDefaultValueFromPropertyObject(Object propertyObj, String fieldName) throws IllegalAccessException { - Optional fieldOptional = Stream.of(propertyObj.getClass().getDeclaredFields()) - .filter(f -> f.getName().equalsIgnoreCase(fieldName)).findAny(); + private Object getDefaultValueFromPropertyObject(Object propertyObj, String fieldName) throws IllegalAccessException, InvocationTargetException { + try { + Field field = propertyObj.getClass().getDeclaredField(fieldName); - // Get defaultValue from the field - if (fieldOptional.isPresent()) { - Field field = fieldOptional.get(); if (!Map.class.isAssignableFrom(field.getType())) { field.setAccessible(true); return field.get(propertyObj); } + } catch (NoSuchFieldException e) { + Method method = null; + try { + method = propertyObj.getClass().getMethod("get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1)); + } catch (NoSuchMethodException ex) { + try { + method = propertyObj.getClass().getMethod("is" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1)); + } catch (NoSuchMethodException exc) { + LOGGER.warn("The get method not found for the field '{}#{}'.", propertyObj.getClass().getSimpleName(), fieldName); + } + } + if (method != null) { + if (!Map.class.isAssignableFrom(method.getReturnType())) { + method.setAccessible(true); + return method.invoke(propertyObj); + } + } } return null; diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/proxy-config.json b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/proxy-config.json new file mode 100644 index 00000000000..86bc6c1305f --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/proxy-config.json @@ -0,0 +1,10 @@ +[ + { + "condition": { + "typeReachable": "io.seata.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider" + }, + "interfaces": [ + "io.seata.config.Configuration" + ] + } +] \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/reflect-config.json b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/reflect-config.json new file mode 100644 index 00000000000..abadecf024e --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/native-image/io.seata/seata-spring-autoconfigure-core/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.config.ExtConfigurationProvider" + }, + "name": "io.seata.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/serializer/seata-serializer-fst/src/main/resources/META-INF/native-image/io.seata/seata-serializer-fst/reflect-config.json b/serializer/seata-serializer-fst/src/main/resources/META-INF/native-image/io.seata/seata-serializer-fst/reflect-config.json new file mode 100644 index 00000000000..de413f4bd77 --- /dev/null +++ b/serializer/seata-serializer-fst/src/main/resources/META-INF/native-image/io.seata/seata-serializer-fst/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.serializer.Serializer" + }, + "name": "io.seata.serializer.fst.FstSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/serializer/seata-serializer-hessian/src/main/resources/META-INF/native-image/io.seata/seata-serializer-hessian/reflect-config.json b/serializer/seata-serializer-hessian/src/main/resources/META-INF/native-image/io.seata/seata-serializer-hessian/reflect-config.json new file mode 100644 index 00000000000..4d6f3e586e7 --- /dev/null +++ b/serializer/seata-serializer-hessian/src/main/resources/META-INF/native-image/io.seata/seata-serializer-hessian/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.serializer.Serializer" + }, + "name": "io.seata.serializer.hessian.HessianSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/serializer/seata-serializer-kryo/src/main/resources/META-INF/native-image/io.seata/seata-serializer-kryo/reflect-config.json b/serializer/seata-serializer-kryo/src/main/resources/META-INF/native-image/io.seata/seata-serializer-kryo/reflect-config.json new file mode 100644 index 00000000000..41aadd953bf --- /dev/null +++ b/serializer/seata-serializer-kryo/src/main/resources/META-INF/native-image/io.seata/seata-serializer-kryo/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.serializer.Serializer" + }, + "name": "io.seata.serializer.kryo.KryoSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/serializer/seata-serializer-protobuf/src/main/resources/META-INF/native-image/io.seata/seata-serializer-protobuf/reflect-config.json b/serializer/seata-serializer-protobuf/src/main/resources/META-INF/native-image/io.seata/seata-serializer-protobuf/reflect-config.json new file mode 100644 index 00000000000..0e85dad04ba --- /dev/null +++ b/serializer/seata-serializer-protobuf/src/main/resources/META-INF/native-image/io.seata/seata-serializer-protobuf/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.serializer.Serializer" + }, + "name": "io.seata.serializer.protobuf.ProtobufSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/serializer/seata-serializer-seata/src/main/resources/META-INF/native-image/io.seata/seata-serializer-seata/reflect-config.json b/serializer/seata-serializer-seata/src/main/resources/META-INF/native-image/io.seata/seata-serializer-seata/reflect-config.json new file mode 100644 index 00000000000..140bfe99f60 --- /dev/null +++ b/serializer/seata-serializer-seata/src/main/resources/META-INF/native-image/io.seata/seata-serializer-seata/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.serializer.Serializer" + }, + "name": "io.seata.serializer.seata.SeataSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/server/pom.xml b/server/pom.xml index b0eac164b3d..1924128aa50 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -31,6 +31,7 @@ ${spring-boot.version} ${spring-framework.version} + 0.9.20 @@ -160,7 +161,7 @@ com.h2database h2 - + mysql mysql-connector-java @@ -371,6 +372,120 @@ + + native + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + repackage + + repackage + + + + process-aot + + process-aot + + + + + io.seata.server.ServerApplication + + paketobuildpacks/builder:tiny + + true + + + + + + org.graalvm.buildtools + native-maven-plugin + ${native-build-tools-plugin.version} + + ${project.build.outputDirectory} + + true + + 22.3 + + -H:+ReportExceptionStackTraces + -H:+PrintAnalysisCallTree + + -H:+ExhaustiveHeapScan + + + + + add-reachability-metadata + + add-reachability-metadata + + + + build-native + + compile-no-fork + + + + + + + + + nativeTest + + + org.junit.platform + junit-platform-launcher + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + process-test-aot + + process-test-aot + + + + + + org.graalvm.buildtools + native-maven-plugin + ${native-build-tools-plugin.version} + + ${project.build.outputDirectory} + + true + + 22.3 + + + + native-test + + test + + + + + + + release-seata diff --git a/server/src/main/java/io/seata/server/ServerApplication.java b/server/src/main/java/io/seata/server/ServerApplication.java index e168ad65c06..f61ec5f62a1 100644 --- a/server/src/main/java/io/seata/server/ServerApplication.java +++ b/server/src/main/java/io/seata/server/ServerApplication.java @@ -15,8 +15,7 @@ */ package io.seata.server; -import java.io.IOException; - +import io.seata.common.aot.NativeUtils; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -25,8 +24,26 @@ */ @SpringBootApplication(scanBasePackages = {"io.seata"}) public class ServerApplication { - public static void main(String[] args) throws IOException { - // run the spring-boot application - SpringApplication.run(ServerApplication.class, args); + + public static void main(String[] args) throws Throwable { + try { + // run the spring-boot application + SpringApplication.run(ServerApplication.class, args); + } catch (Throwable t) { + // This exception is used to end `spring-boot-maven-plugin:process-aot`, so ignore it. + if ("org.springframework.boot.SpringApplication$AbandonedRunException".equals(t.getClass().getName())) { + throw t; + } + + // In the `native-image`, if an exception occurs prematurely during the startup process, the exception log will not be recorded, + // so here we sleep for 20 seconds to observe the exception information. + if (NativeUtils.inNativeImage()) { + t.printStackTrace(); + Thread.sleep(20000); + } + + throw t; + } } + } diff --git a/server/src/main/java/io/seata/server/console/controller/BranchSessionController.java b/server/src/main/java/io/seata/server/console/controller/BranchSessionController.java index 62ffac67c06..6310688b11d 100644 --- a/server/src/main/java/io/seata/server/console/controller/BranchSessionController.java +++ b/server/src/main/java/io/seata/server/console/controller/BranchSessionController.java @@ -16,12 +16,14 @@ package io.seata.server.console.controller; import javax.annotation.Resource; + import io.seata.server.console.service.BranchSessionService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * Branch Session Controller + * * @author zhongxiang.wang */ @RestController @@ -31,5 +33,4 @@ public class BranchSessionController { @Resource(type = BranchSessionService.class) private BranchSessionService branchSessionService; - } diff --git a/server/src/main/java/io/seata/server/console/controller/GlobalLockController.java b/server/src/main/java/io/seata/server/console/controller/GlobalLockController.java index ac20ebf14ba..b9478111859 100644 --- a/server/src/main/java/io/seata/server/console/controller/GlobalLockController.java +++ b/server/src/main/java/io/seata/server/console/controller/GlobalLockController.java @@ -17,18 +17,18 @@ import javax.annotation.Resource; -import io.seata.server.console.param.GlobalLockParam; import io.seata.console.result.PageResult; -import io.seata.server.console.vo.GlobalLockVO; +import io.seata.server.console.param.GlobalLockParam; import io.seata.server.console.service.GlobalLockService; +import io.seata.server.console.vo.GlobalLockVO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; - /** * Global Lock Controller + * * @author zhongxiang.wang */ @RestController @@ -40,6 +40,7 @@ public class GlobalLockController { /** * Query locks by param + * * @param param the param * @return the list of GlobalLockVO */ diff --git a/server/src/main/java/io/seata/server/console/controller/GlobalSessionController.java b/server/src/main/java/io/seata/server/console/controller/GlobalSessionController.java index 9bd79d95622..6c7ee50ba9f 100644 --- a/server/src/main/java/io/seata/server/console/controller/GlobalSessionController.java +++ b/server/src/main/java/io/seata/server/console/controller/GlobalSessionController.java @@ -17,10 +17,10 @@ import javax.annotation.Resource; -import io.seata.server.console.param.GlobalSessionParam; import io.seata.console.result.PageResult; -import io.seata.server.console.vo.GlobalSessionVO; +import io.seata.server.console.param.GlobalSessionParam; import io.seata.server.console.service.GlobalSessionService; +import io.seata.server.console.vo.GlobalSessionVO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; @@ -28,6 +28,7 @@ /** * Global Session Controller + * * @author zhongxiang.wang */ @RestController @@ -39,8 +40,9 @@ public class GlobalSessionController { /** * Query all globalSession + * * @param param param for query globalSession - * @return the list of GlobalSessionVO + * @return the list of GlobalSessionVO */ @GetMapping("query") public PageResult query(@ModelAttribute GlobalSessionParam param) { diff --git a/server/src/main/resources/META-INF/native-image/io.seata/server/reflect-config.json b/server/src/main/resources/META-INF/native-image/io.seata/server/reflect-config.json new file mode 100644 index 00000000000..9d762dfbaca --- /dev/null +++ b/server/src/main/resources/META-INF/native-image/io.seata/server/reflect-config.json @@ -0,0 +1,362 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.rpc.RegisterCheckAuthHandler" + }, + "name": "io.seata.server.auth.DefaultCheckAuthHandler", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.DataSourceProvider" + }, + "name": "io.seata.server.store.DbcpDataSourceProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.DataSourceProvider" + }, + "name": "io.seata.server.store.DruidDataSourceProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.db.DataSourceProvider" + }, + "name": "io.seata.server.store.HikariDataSourceProvider", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.DistributedLocker" + }, + "name": "io.seata.server.storage.redis.lock.RedisDistributedLocker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.core.store.DistributedLocker" + }, + "name": "io.seata.server.storage.db.lock.DataBaseDistributedLocker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.coordinator.AbstractCore" + }, + "name": "io.seata.server.transaction.at.ATCore", + "methods": [ + { + "name": "", + "parameterTypes": [ + "io.seata.core.rpc.RemotingServer" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.coordinator.AbstractCore" + }, + "name": "io.seata.server.transaction.tcc.TccCore", + "methods": [ + { + "name": "", + "parameterTypes": [ + "io.seata.core.rpc.RemotingServer" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.coordinator.AbstractCore" + }, + "name": "io.seata.server.transaction.saga.SagaCore", + "methods": [ + { + "name": "", + "parameterTypes": [ + "io.seata.core.rpc.RemotingServer" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.coordinator.AbstractCore" + }, + "name": "io.seata.server.transaction.xa.XACore", + "methods": [ + { + "name": "", + "parameterTypes": [ + "io.seata.core.rpc.RemotingServer" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.lock.LockManager" + }, + "name": "io.seata.server.storage.db.lock.DataBaseLockManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.lock.LockManager" + }, + "name": "io.seata.server.storage.file.lock.FileLockManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.lock.LockManager" + }, + "name": "io.seata.server.storage.redis.lock.RedisLockManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.session.SessionManager" + }, + "name": "io.seata.server.storage.file.session.FileSessionManager", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.String", + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.session.SessionManager" + }, + "name": "io.seata.server.storage.db.session.DataBaseSessionManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + }, + { + "name": "", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.server.session.SessionManager" + }, + "name": "io.seata.server.storage.redis.session.RedisSessionManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + }, + { + "name": "", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.google.inject.internal.TypeConverterBindingProcessor" + }, + "name": "java.lang.Integer", + "methods": [ + { + "name": "parseInteger", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.google.inject.internal.TypeConverterBindingProcessor" + }, + "name": "java.lang.Long", + "methods": [ + { + "name": "parseLong", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.google.inject.internal.TypeConverterBindingProcessor" + }, + "name": "java.lang.Boolean", + "methods": [ + { + "name": "parseBoolean", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.google.inject.internal.TypeConverterBindingProcessor" + }, + "name": "java.lang.Byte", + "methods": [ + { + "name": "parseByte", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.google.inject.internal.TypeConverterBindingProcessor" + }, + "name": "java.lang.Short", + "methods": [ + { + "name": "parseShort", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.google.inject.internal.TypeConverterBindingProcessor" + }, + "name": "java.lang.Float", + "methods": [ + { + "name": "parseFloat", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "com.google.inject.internal.TypeConverterBindingProcessor" + }, + "name": "java.lang.Double", + "methods": [ + { + "name": "parseDouble", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.netty.channel.socket.nio.SelectorProviderUtil" + }, + "name": "java.nio.channels.spi.SelectorProvider", + "methods": [ + { + "name": "openServerSocketChannel", + "parameterTypes": [ + "java.net.ProtocolFamily" + ] + } + ] + }, + { + "condition": { + "typeReachable": "io.netty.channel.DefaultChannelConfig" + }, + "name": "io.netty.buffer.ByteBufAllocator" + }, + { + "condition": { + "typeReachable": "io.netty.channel.DefaultChannelConfig" + }, + "name": "io.netty.buffer.ByteBufUtil" + }, + { + "condition": { + "typeReachable": "io.netty.util.ResourceLeakDetector" + }, + "name": "io.netty.buffer.AbstractByteBufAllocator", + "allDeclaredMethods": true + }, + { + "condition": { + "typeReachable": "io.netty.util.ResourceLeakDetector" + }, + "name": "io.netty.buffer.AdvancedLeakAwareByteBuf", + "allDeclaredMethods": true + }, + { + "condition": { + "typeReachable": "io.netty.util.ResourceLeakDetector" + }, + "name": "io.netty.util.ReferenceCountUtil", + "allDeclaredMethods": true + } +] \ No newline at end of file diff --git a/server/src/main/resources/META-INF/native-image/io.seata/server/resource-config.json b/server/src/main/resources/META-INF/native-image/io.seata/server/resource-config.json new file mode 100644 index 00000000000..73b72ff3d84 --- /dev/null +++ b/server/src/main/resources/META-INF/native-image/io.seata/server/resource-config.json @@ -0,0 +1,21 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qlogback\/\\E.*" + }, + { + "pattern": "\\Qlua\/redislocker\/redislock.lua\\E" + }, + { + "pattern": "\\Qapplication.yml\\E" + }, + { + "pattern": "\\Qbanner.txt\\E" + }, + { + "pattern": "\\Qlogback-spring.xml\\E" + } + ] + } +} \ No newline at end of file diff --git a/spring-aot/pom.xml b/spring-aot/pom.xml new file mode 100644 index 00000000000..b0fb14ed7cf --- /dev/null +++ b/spring-aot/pom.xml @@ -0,0 +1,58 @@ + + + + + io.seata + seata-parent + ${revision} + + 4.0.0 + + seata-spring-aot + pom + + ${project.artifactId} ${project.version} + spring-aot top parent for Seata built with Maven + + + seata-spring-aot-core + seata-spring-aot-client + + + + + org.springframework + spring-context + + + + ${project.groupId} + seata-spring-framework-fake-for-java8 + ${project.version} + provided + + + + + diff --git a/spring-aot/seata-spring-aot-client/pom.xml b/spring-aot/seata-spring-aot-client/pom.xml new file mode 100644 index 00000000000..52de9fd9751 --- /dev/null +++ b/spring-aot/seata-spring-aot-client/pom.xml @@ -0,0 +1,51 @@ + + + + + io.seata + seata-spring-aot + ${revision} + + 4.0.0 + + seata-spring-aot-client + + ${project.artifactId} ${project.version} + spring-aot-client for Seata built with Maven + + + + ${project.groupId} + seata-spring-aot-core + ${project.version} + + + ${project.groupId} + seata-spring + ${project.version} + + + + com.alibaba + druid + provided + true + + + diff --git a/spring-aot/seata-spring-aot-client/src/main/java/io/seata/spring/aot/SeataLocalTCCBeanRegistrationAotProcessor.java b/spring-aot/seata-spring-aot-client/src/main/java/io/seata/spring/aot/SeataLocalTCCBeanRegistrationAotProcessor.java new file mode 100644 index 00000000000..c6e266d2bf2 --- /dev/null +++ b/spring-aot/seata-spring-aot-client/src/main/java/io/seata/spring/aot/SeataLocalTCCBeanRegistrationAotProcessor.java @@ -0,0 +1,89 @@ +/* + * Copyright 1999-2019 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.spring.aot; + +import java.util.Set; + +import io.seata.common.util.ReflectionUtil; +import io.seata.rm.tcc.api.LocalTCC; +import io.seata.spring.annotation.GlobalTransactionScanner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.hint.ReflectionHints; +import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; +import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; +import org.springframework.beans.factory.aot.BeanRegistrationCode; +import org.springframework.beans.factory.support.RegisteredBean; + +import static io.seata.spring.aot.AotUtils.ALL_MEMBER_CATEGORIES; +import static org.springframework.aot.hint.MemberCategory.INVOKE_PUBLIC_METHODS; + +/** + * The seata-client bean registration AOT processor + * + * @author wang.liang + */ +class SeataLocalTCCBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(SeataLocalTCCBeanRegistrationAotProcessor.class); + + @Override + public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { + Class beanClass = registeredBean.getBeanClass(); + if (GlobalTransactionScanner.isTccAutoProxy(beanClass)) { + return new SeataTccBeanRegistrationAotContribution(beanClass); + } + return null; + } + + + /** + * The seata tcc bean registration AOT contribution + */ + private static class SeataTccBeanRegistrationAotContribution implements BeanRegistrationAotContribution { + + private final Class beanClass; + + + public SeataTccBeanRegistrationAotContribution(Class beanClass) { + this.beanClass = beanClass; + } + + + @Override + public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { + ReflectionHints reflectionHints = generationContext.getRuntimeHints().reflection(); + + // register the bean class + registerClassAndItsInterfacesIfLocalTcc(reflectionHints, beanClass); + + // register the interface classes + Set> interfaceClasses = ReflectionUtil.getInterfaces(beanClass); + for (Class interClass : interfaceClasses) { + registerClassAndItsInterfacesIfLocalTcc(reflectionHints, interClass); + } + } + + private void registerClassAndItsInterfacesIfLocalTcc(ReflectionHints reflectionHints, Class clazz) { + if (clazz.isAnnotationPresent(LocalTCC.class)) { + reflectionHints.registerType(clazz, INVOKE_PUBLIC_METHODS); + LOGGER.info("TCC: Register reflection type '{}' (annotated `@LocalTCC`) with member categories {}", clazz.getName(), INVOKE_PUBLIC_METHODS); + AotUtils.registerAllOfClass(false, reflectionHints, clazz, ALL_MEMBER_CATEGORIES); + } + } + } +} diff --git a/spring-aot/seata-spring-aot-client/src/main/resources/META-INF/spring/aot.factories b/spring-aot/seata-spring-aot-client/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..c58d25f79b4 --- /dev/null +++ b/spring-aot/seata-spring-aot-client/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\ +io.seata.spring.aot.SeataLocalTCCBeanRegistrationAotProcessor \ No newline at end of file diff --git a/spring-aot/seata-spring-aot-core/pom.xml b/spring-aot/seata-spring-aot-core/pom.xml new file mode 100644 index 00000000000..ad270c9d829 --- /dev/null +++ b/spring-aot/seata-spring-aot-core/pom.xml @@ -0,0 +1,39 @@ + + + + + io.seata + seata-spring-aot + ${revision} + + 4.0.0 + + seata-spring-aot-core + + ${project.artifactId} ${project.version} + spring-aot-core for Seata built with Maven + + + + ${project.groupId} + seata-core + ${project.version} + + + diff --git a/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/AotUtils.java b/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/AotUtils.java new file mode 100644 index 00000000000..1d25d7df30c --- /dev/null +++ b/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/AotUtils.java @@ -0,0 +1,247 @@ +/* + * Copyright 1999-2019 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.spring.aot; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +import io.seata.common.aot.NativeUtils; +import io.seata.common.util.ReflectionUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.ReflectionHints; +import org.springframework.core.SpringProperties; +import org.springframework.core.io.Resource; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import static io.seata.common.loader.EnhancedServiceLoader.SERVICES_DIRECTORY; +import static org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_CONSTRUCTORS; +import static org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_METHODS; + +/** + * The AOT utils + * + * @author wang.liang + */ +public class AotUtils extends NativeUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(AotUtils.class); + + public static final String SPRING_AOT_ENABLED = "spring.aot.enabled"; + + + /** + * Usually used for serialization + */ + public static final MemberCategory[] ALL_MEMBER_CATEGORIES = MemberCategory.values(); + + /** + * Only used for load class + */ + public static final MemberCategory[] EMPTY_MEMBER_CATEGORIES = new MemberCategory[0]; + + public static final MemberCategory[] MEMBER_CATEGORIES_FOR_INSTANTIATE = new MemberCategory[]{INVOKE_DECLARED_CONSTRUCTORS}; + + public static final MemberCategory[] MEMBER_CATEGORIES_FOR_INSTANTIATE_AND_INVOKE = new MemberCategory[]{INVOKE_DECLARED_CONSTRUCTORS, INVOKE_DECLARED_METHODS}; + + + /** + * Whether AOT enabled + * + * @return the boolean + */ + public static boolean isSpringAotEnabled() { + return SpringProperties.getFlag(SPRING_AOT_ENABLED); + } + + + //region # Register type to ReflectionHints + + public static void registerType(ReflectionHints reflectionHints, Class clazz, MemberCategory... memberCategories) { + reflectionHints.registerType(clazz, memberCategories); + if (LOGGER.isDebugEnabled()) { + LOGGER.info("Register reflection type '{}' with member categories {}", clazz.getName(), memberCategories); + } + } + + public static void registerType(ReflectionHints reflectionHints, String className, MemberCategory... memberCategories) { + try { + Class clazz = ReflectionUtil.getClassByName(className); + registerType(reflectionHints, clazz, memberCategories); + } catch (ClassNotFoundException e) { + LOGGER.warn("Register reflection type failed: class not found '{}'.", className); + } catch (NoClassDefFoundError e) { + if (LOGGER.isDebugEnabled()) { + LOGGER.warn("Register reflection type '{}' error:", className, e); + } else { + LOGGER.warn("Register reflection type '{}' error: {}: {}", className, e.getClass().getName(), e.getMessage()); + } + } + } + + public static void registerTypes(ReflectionHints reflectionHints, MemberCategory[] memberCategories, String... classNames) { + for (String className : classNames) { + try { + registerType(reflectionHints, ReflectionUtil.getClassByName(className), memberCategories); + } catch (ClassNotFoundException e) { + LOGGER.warn("Register reflection type failed: class not found '{}'.", className); + } catch (NoClassDefFoundError e) { + if (LOGGER.isDebugEnabled()) { + LOGGER.warn("Register reflection type '{}' error:", className, e); + } else { + LOGGER.warn("Register reflection type '{}' error: {}: {}", className, e.getClass().getName(), e.getMessage()); + } + } + } + } + + public static void registerTypes(ReflectionHints reflectionHints, MemberCategory[] memberCategories, Class... classes) { + for (Class clazz : classes) { + registerType(reflectionHints, clazz, memberCategories); + } + } + + /** + * Register the types for serialize, without knowing the type of the serializer + * + * @param reflectionHints the reflection hints + * @param classes the classes + */ + public static void registerTypesForSerialize(ReflectionHints reflectionHints, Class... classes) { + registerTypes(reflectionHints, ALL_MEMBER_CATEGORIES, classes); + } + + public static void registerTypesForSerialize(ReflectionHints reflectionHints, String... classNames) { + registerTypes(reflectionHints, ALL_MEMBER_CATEGORIES, classNames); + } + + + //region ## Register 'classpath*:META-INF/services/*' to ReflectionHints + + public static void registerServices(ReflectionHints reflectionHints, String location, @Nullable Predicate predicate, MemberCategory... memberCategories) { + Resource[] resources = ResourceUtil.getResources(location); + for (Resource resource : resources) { + if (predicate != null && !predicate.test(resource)) { + continue; + } + + try (InputStreamReader isr = new InputStreamReader(resource.getInputStream()); BufferedReader br = new BufferedReader(isr)) { + br.lines().forEach(className -> { + AotUtils.registerTypes(reflectionHints, memberCategories, className); + }); + } catch (IOException e) { + LOGGER.error("Register services '{}' fail:", resource.getFilename(), e); + } + } + } + + public static void registerServices(ReflectionHints reflectionHints, String location, MemberCategory... memberCategories) { + registerServices(reflectionHints, location, null, memberCategories); + } + + public static void registerServices(ReflectionHints reflectionHints, @Nullable Predicate predicate, MemberCategory... memberCategories) { + registerServices(reflectionHints, "classpath*:" + SERVICES_DIRECTORY + "*", predicate, memberCategories); + } + + public static void registerServices(ReflectionHints reflectionHints, MemberCategory... memberCategories) { + registerServices(reflectionHints, "classpath*:" + SERVICES_DIRECTORY + "*", null, memberCategories); + } + + //endregion ## + + + //region ## Register all of class to ReflectionHints + + /** + * Recursively register the class and its supper classes, interfaces, fields, and the parameters of methods to the reflection hints. + * + * @param clazz the class + * @param registerSelf whether register self + * @param reflectionHints the reflection hints + * @param memberCategories the member categories + */ + public static void registerAllOfClass(boolean registerSelf, ReflectionHints reflectionHints, Class clazz, MemberCategory... memberCategories) { + registerAllOfClassInternal(new HashSet<>(), registerSelf, reflectionHints, clazz, memberCategories); + } + + private static void registerAllOfClassInternal(@NonNull Set> cache, boolean registerSelf, ReflectionHints reflectionHints, Class clazz, MemberCategory... memberCategories) { + if (clazz == null) { + return; + } + + if (clazz.isPrimitive() || clazz.isEnum() || clazz.isAnnotation()) { + return; + } + + if (clazz.isArray()) { + registerAllOfClassInternal(cache, true, reflectionHints, clazz.getComponentType(), memberCategories); + return; + } + + if (ReflectionUtil.isJavaClass(clazz)) { + return; + } + + // Cached to prevent endless loops + if (cache.contains(clazz)) { + return; + } + cache.add(clazz); + + // register self + if (registerSelf) { + registerType(reflectionHints, clazz, memberCategories); + } + + // register the interfaces + Set> interfaceClasses = ReflectionUtil.getInterfaces(clazz); + for (Class interfaceClass : interfaceClasses) { + if (!interfaceClass.equals(clazz)) { + registerAllOfClassInternal(cache, true, reflectionHints, interfaceClass, memberCategories); + } + } + + // register the supper class + registerAllOfClassInternal(cache, true, reflectionHints, clazz.getSuperclass(), memberCategories); + + // register the fields + Field[] fields = ReflectionUtil.getAllFields(clazz); + for (Field field : fields) { + registerAllOfClassInternal(cache, true, reflectionHints, field.getType(), memberCategories); + } + + // register the parameters of methods + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + Class[] parameterTypes = method.getParameterTypes(); + for (Class parameterType : parameterTypes) { + registerAllOfClassInternal(cache, true, reflectionHints, parameterType, memberCategories); + } + } + } + + //endregion ## + + //endregion # +} diff --git a/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/ResourceUtil.java b/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/ResourceUtil.java new file mode 100644 index 00000000000..6d21deb3c7f --- /dev/null +++ b/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/ResourceUtil.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2019 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.spring.aot; + +import java.io.IOException; + +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +/** + * Resource util. + * + * @author wang.liang + */ +class ResourceUtil { + + private static final ResourcePatternResolver RESOURCE_RESOLVER = new PathMatchingResourcePatternResolver(); + + public static Resource[] getResources(String location) { + try { + return RESOURCE_RESOLVER.getResources(location); + } catch (IOException e) { + return new Resource[0]; + } + } +} \ No newline at end of file diff --git a/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/SeataServicesRuntimeHints.java b/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/SeataServicesRuntimeHints.java new file mode 100644 index 00000000000..1d4412790db --- /dev/null +++ b/spring-aot/seata-spring-aot-core/src/main/java/io/seata/spring/aot/SeataServicesRuntimeHints.java @@ -0,0 +1,68 @@ +/* + * Copyright 1999-2019 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.spring.aot; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.core.io.Resource; +import org.springframework.lang.Nullable; + +import static io.seata.common.loader.EnhancedServiceLoader.SEATA_DIRECTORY; +import static io.seata.common.loader.EnhancedServiceLoader.SERVICES_DIRECTORY; + +/** + * The seata /META-INF/services runtime hints registrar + * + * @author wang.liang + */ +class SeataServicesRuntimeHints implements RuntimeHintsRegistrar { + + private static final Set OTHER_SERVICES = new HashSet<>(); + + static { + OTHER_SERVICES.add("com.alibaba.dubbo.rpc.Filter"); + OTHER_SERVICES.add("com.alipay.sofa.rpc.filter.Filter"); + OTHER_SERVICES.add("com.taobao.hsf.invocation.filter.RPCFilter"); + OTHER_SERVICES.add("com.weibo.api.motan.filter.Filter"); + } + + + @Override + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { + // Register the services to reflection hints in 'META-INF/services', only the services required by seata. + Predicate predicate = this::isSeataServicesResource; + AotUtils.registerServices(hints.reflection(), "classpath*:" + SERVICES_DIRECTORY + "*", predicate, AotUtils.MEMBER_CATEGORIES_FOR_INSTANTIATE); + AotUtils.registerServices(hints.reflection(), "classpath*:" + SEATA_DIRECTORY + "*", predicate, AotUtils.MEMBER_CATEGORIES_FOR_INSTANTIATE); + } + + + private boolean isSeataServicesResource(Resource resource) { + if (resource.getFilename() == null) { + return false; + } + + if (resource.getFilename().startsWith("io.seata.")) { + return true; + } + + return OTHER_SERVICES.contains(resource.getFilename()); + } + +} diff --git a/spring-framework-fake-for-java8/pom.xml b/spring-framework-fake-for-java8/pom.xml new file mode 100644 index 00000000000..993c0fd2b25 --- /dev/null +++ b/spring-framework-fake-for-java8/pom.xml @@ -0,0 +1,63 @@ + + + + + io.seata + seata-parent + ${revision} + + 4.0.0 + + seata-spring-framework-fake-for-java8 + + ${project.artifactId} ${project.version} + spring-framework-fake-for-java8 for Seata built with Maven + + + + org.springframework + spring-beans + + + + jakarta.servlet + jakarta.servlet-api + provided + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + true + + + + org.apache.maven.plugins + maven-pmd-plugin + + true + + + + + diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/generate/GenerationContext.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/generate/GenerationContext.java new file mode 100644 index 00000000000..e226ca4b6b9 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/generate/GenerationContext.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.generate; + +import org.springframework.aot.hint.RuntimeHints; + +/** + * GenerationContext's fake + * + * @author Phillip Webb + * @author Stephane Nicoll + * @since 6.0 + */ +public interface GenerationContext { + +// GeneratedClasses getGeneratedClasses(); +// +// GeneratedFiles getGeneratedFiles(); + + RuntimeHints getRuntimeHints(); + + GenerationContext withName(String name); + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ExecutableMode.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ExecutableMode.java new file mode 100644 index 00000000000..6ee04575cf2 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ExecutableMode.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +import org.springframework.lang.Nullable; + +/** + * ExecutableMode's fake + * + * @author Stephane Nicoll + * @since 6.0 + */ +public enum ExecutableMode { + + INTROSPECT, + + INVOKE; + + boolean includes(@Nullable ExecutableMode other) { + return true; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/MemberCategory.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/MemberCategory.java new file mode 100644 index 00000000000..d1c47657421 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/MemberCategory.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +/** + * MemberCategory's fake + * + * @author Andy Clement + * @author Sebastien Deleuze + * @author Stephane Nicoll + * @since 6.0 + */ +public enum MemberCategory { + + PUBLIC_FIELDS, + + DECLARED_FIELDS, + + INTROSPECT_PUBLIC_CONSTRUCTORS, + + INTROSPECT_DECLARED_CONSTRUCTORS, + + INVOKE_PUBLIC_CONSTRUCTORS, + + INVOKE_DECLARED_CONSTRUCTORS, + + INTROSPECT_PUBLIC_METHODS, + + INTROSPECT_DECLARED_METHODS, + + INVOKE_PUBLIC_METHODS, + + INVOKE_DECLARED_METHODS, + + PUBLIC_CLASSES, + + DECLARED_CLASSES; + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ProxyHints.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ProxyHints.java new file mode 100644 index 00000000000..509953be3a3 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ProxyHints.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +/** + * ProxyHints's fake + * + * @author Stephane Nicoll + * @since 6.0 + */ +public class ProxyHints { + +// public Stream jdkProxyHints() { +// return null; +// } +// +// public ProxyHints registerJdkProxy(Consumer jdkProxyHint) { +// return this; +// } + + public ProxyHints registerJdkProxy(TypeReference... proxiedInterfaces) { + return this; + } + + public ProxyHints registerJdkProxy(Class... proxiedInterfaces) { + return this; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ReflectionHints.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ReflectionHints.java new file mode 100644 index 00000000000..d84b1b742e9 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ReflectionHints.java @@ -0,0 +1,90 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import org.springframework.lang.Nullable; + +/** + * ReflectionHints's fake + * + * @author Stephane Nicoll + * @author Phillip Webb + * @author Andy Wilkinson + * @since 6.0 + */ +public class ReflectionHints { + +// public Stream typeHints() { +// return null; +// } +// +// @Nullable +// public TypeHint getTypeHint(TypeReference type) { +// return null; +// } +// +// @Nullable +// public TypeHint getTypeHint(Class type) { +// return null; +// } +// +// public ReflectionHints registerType(TypeReference type, Consumer typeHint) { +// return this; +// } + + public ReflectionHints registerType(TypeReference type, MemberCategory... memberCategories) { + return this; + } + +// public ReflectionHints registerType(Class type, Consumer typeHint) { +// return this; +// } + + public ReflectionHints registerType(Class type, MemberCategory... memberCategories) { + return this; + } + +// public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader, +// String typeName, Consumer typeHint) { +// return this; +// } + + public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader, + String typeName, MemberCategory... memberCategories) { + return this; + } + +// public ReflectionHints registerTypes(Iterable types, Consumer typeHint) { +// return this; +// } + + public ReflectionHints registerField(Field field) { + return this; + } + + public ReflectionHints registerConstructor(Constructor constructor, ExecutableMode mode) { + return this; + } + + public ReflectionHints registerMethod(Method method, ExecutableMode mode) { + return this; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ResourceHints.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ResourceHints.java new file mode 100644 index 00000000000..1f679d84dcb --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/ResourceHints.java @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +import org.springframework.core.io.Resource; + +/** + * ResourceHints's fake + * + * @author Stephane Nicoll + * @author Sam Brannen + * @since 6.0 + */ +public class ResourceHints { + +// public Stream resourcePatternHints() { +// return null; +// } +// +// public Stream resourceBundleHints() { +// return null; +// } +// +// public ResourceHints registerPatternIfPresent(@Nullable ClassLoader classLoader, String location, +// Consumer resourceHint) { +// return this; +// } +// +// public ResourceHints registerPattern(@Nullable Consumer resourceHint) { +// return this; +// } + + public ResourceHints registerPattern(String include) { + return this; + } + + public void registerResource(Resource resource) { + } + +// public ResourceHints registerType(TypeReference type) { +// return this; +// } + + public ResourceHints registerType(Class type) { + return this; + } + +// public ResourceHints registerResourceBundle(String baseName, @Nullable Consumer resourceHint) { +// return this; +// } + + public ResourceHints registerResourceBundle(String baseName) { + return this; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHints.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHints.java new file mode 100644 index 00000000000..4bb99528d1d --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHints.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +/** + * RuntimeHints's fake + * + * @author Stephane Nicoll + * @author Janne Valkealahti + * @since 6.0 + */ +public class RuntimeHints { + + public ReflectionHints reflection() { + return null; + } + + public ResourceHints resources() { + return null; + } + + public SerializationHints serialization() { + return null; + } + + public ProxyHints proxies() { + return null; + } + + public ReflectionHints jni() { + return null; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHintsRegistrar.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHintsRegistrar.java new file mode 100644 index 00000000000..caf9898d155 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/RuntimeHintsRegistrar.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +import org.springframework.lang.Nullable; + +/** + * RuntimeHintsRegistrar's fake + * + * @author Brian Clozel + * @author Stephane Nicoll + * @since 6.0 + */ +@FunctionalInterface +public interface RuntimeHintsRegistrar { + + void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader); + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/SerializationHints.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/SerializationHints.java new file mode 100644 index 00000000000..9a0a7bf5ce3 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/SerializationHints.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +import java.io.Serializable; + +/** + * SerializationHints's fake + * + * @author Stephane Nicoll + * @since 6.0 + * @see Serializable + */ +public class SerializationHints { + +// public Stream javaSerializationHints() { +// return null; +// } +// +// public SerializationHints registerType(TypeReference type, @Nullable Consumer serializationHint) { +// return this; +// } + + public SerializationHints registerType(TypeReference type) { + return this; + } + +// public SerializationHints registerType(Class type, @Nullable Consumer serializationHint) { +// return this; +// } + + public SerializationHints registerType(Class type) { + return this; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/TypeReference.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/TypeReference.java new file mode 100644 index 00000000000..69463bbba32 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/aot/hint/TypeReference.java @@ -0,0 +1,54 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.aot.hint; + +import java.util.List; + +import org.springframework.lang.Nullable; + +/** + * TypeReference's fake + * + * @author Stephane Nicoll + * @since 6.0 + */ +public interface TypeReference { + + String getName(); + + String getCanonicalName(); + + String getPackageName(); + + String getSimpleName(); + + @Nullable + TypeReference getEnclosingType(); + + static TypeReference of(Class type) { + return null; + } + + static TypeReference of(String className) { + return null; + } + + static List listOf(Class... types) { + return null; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java new file mode 100644 index 00000000000..c1d8ffcc346 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.beans.factory.aot; + +import org.springframework.aot.generate.GenerationContext; + +/** + * BeanRegistrationAotContribution's fake + * + * @author Phillip Webb + * @author Stephane Nicoll + * @since 6.0 + * @see BeanRegistrationAotProcessor + */ +@FunctionalInterface +public interface BeanRegistrationAotContribution { + +// default BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments( +// GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) { +// return codeFragments; +// } + + void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode); + +// static BeanRegistrationAotContribution withCustomCodeFragments(UnaryOperator defaultCodeFragments) { +// return null; +// } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotProcessor.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotProcessor.java new file mode 100644 index 00000000000..d83519f2cfe --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotProcessor.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.beans.factory.aot; + +import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.lang.Nullable; + +/** + * BeanRegistrationAotProcessor's fake + * + * @author Phillip Webb + * @author Stephane Nicoll + * @since 6.0 + */ +@FunctionalInterface +public interface BeanRegistrationAotProcessor { + + @Nullable + BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean); + + default boolean isBeanExcludedFromAotProcessing() { + return true; + } + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCode.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCode.java new file mode 100644 index 00000000000..4fe0eb4aab1 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCode.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.beans.factory.aot; + +/** + * BeanRegistrationCode's fake + * + * @author Phillip Webb + * @since 6.0 + */ +public interface BeanRegistrationCode { + +// ClassName getClassName(); +// +// GeneratedMethods getMethods(); +// +// void addInstancePostProcessor(MethodReference methodReference); + +} diff --git a/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java new file mode 100644 index 00000000000..e698f6554e9 --- /dev/null +++ b/spring-framework-fake-for-java8/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java @@ -0,0 +1,97 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.beans.factory.support; + +import java.lang.reflect.Executable; +import java.util.function.Supplier; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.core.ResolvableType; +import org.springframework.lang.Nullable; + +/** + * RegisteredBean's fake + * + * @author Phillip Webb + * @since 6.0 + */ +public final class RegisteredBean { + + private RegisteredBean(ConfigurableListableBeanFactory beanFactory, Supplier beanName, + boolean generatedBeanName, Supplier mergedBeanDefinition, + @Nullable RegisteredBean parent) { + } + + + public static RegisteredBean of(ConfigurableListableBeanFactory beanFactory, String beanName) { + return null; + } + + public static RegisteredBean ofInnerBean(RegisteredBean parent, BeanDefinitionHolder innerBean) { + return null; + } + + public static RegisteredBean ofInnerBean(RegisteredBean parent, BeanDefinition innerBeanDefinition) { + return null; + } + + public static RegisteredBean ofInnerBean(RegisteredBean parent, + @Nullable String innerBeanName, BeanDefinition innerBeanDefinition) { + return null; + } + + + public String getBeanName() { + return null; + } + + public boolean isGeneratedBeanName() { + return true; + } + + public ConfigurableListableBeanFactory getBeanFactory() { + return null; + } + + public Class getBeanClass() { + return null; + } + + public ResolvableType getBeanType() { + return null; + } + + public RootBeanDefinition getMergedBeanDefinition() { + return null; + } + + public boolean isInnerBean() { + return true; + } + + @Nullable + public RegisteredBean getParent() { + return null; + } + + public Executable resolveConstructorOrFactoryMethod() { + return null; + } + +} diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java index ef455ea6e54..435b660b267 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -25,7 +25,9 @@ import javax.annotation.Nullable; +import io.seata.common.aot.NativeUtils; import io.seata.common.util.CollectionUtils; +import io.seata.common.util.ReflectionUtil; import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationCache; import io.seata.config.ConfigurationChangeEvent; @@ -36,6 +38,7 @@ import io.seata.core.rpc.netty.RmNettyRemotingClient; import io.seata.core.rpc.netty.TmNettyRemotingClient; import io.seata.rm.RMClient; +import io.seata.rm.tcc.api.LocalTCC; import io.seata.spring.annotation.scannercheckers.PackageScannerChecker; import io.seata.spring.tcc.TccActionInterceptor; import io.seata.spring.util.OrderUtil; @@ -492,9 +495,31 @@ private MethodDesc makeMethodDesc(GlobalTransactional anno, Method method) { return new MethodDesc(anno, method); } + public static boolean isTccAutoProxy(Class beanClass) { + Set> interfaceClasses = ReflectionUtil.getInterfaces(beanClass); + for (Class interClass : interfaceClasses) { + if (interClass.isAnnotationPresent(LocalTCC.class)) { + return true; + } + } + return beanClass.isAnnotationPresent(LocalTCC.class); + } + @Override protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource customTargetSource) throws BeansException { + if (NativeUtils.isSpringAotProcessing()) { + if (isTccAutoProxy(beanClass)) { + LOGGER.info("Proxy TCC service: {}", beanName); + return new Object[]{new TccActionInterceptor()}; + } else if (existsAnnotation(beanClass)) { + LOGGER.info("Proxy TM bean: {}", beanName); + return new Object[]{new GlobalTransactionalInterceptor(failureHandlerHook)}; + } else { + return DO_NOT_PROXY; + } + } + return new Object[]{interceptor}; } diff --git a/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java b/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java index b5fdb69d4d3..39b4fbe163a 100644 --- a/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java +++ b/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator.java @@ -15,11 +15,12 @@ */ package io.seata.spring.annotation.datasource; -import javax.sql.DataSource; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import javax.sql.DataSource; +import io.seata.common.aot.NativeUtils; import io.seata.core.model.BranchType; import io.seata.rm.datasource.DataSourceProxy; import io.seata.rm.datasource.SeataDataSourceProxy; @@ -59,6 +60,15 @@ private Object[] buildAdvisors(String dataSourceProxyMode) { @Override protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource customTargetSource) { + if (NativeUtils.isSpringAotProcessing()) { + if (!DataSource.class.isAssignableFrom(beanClass)) { + return DO_NOT_PROXY; + } + + if (this.shouldSkip(beanClass, beanName)) { + return DO_NOT_PROXY; + } + } return advisors; } diff --git a/spring/src/main/resources/META-INF/native-image/io.seata/seata-spring/reflect-config.json b/spring/src/main/resources/META-INF/native-image/io.seata/seata-spring/reflect-config.json new file mode 100644 index 00000000000..9557379d24d --- /dev/null +++ b/spring/src/main/resources/META-INF/native-image/io.seata/seata-spring/reflect-config.json @@ -0,0 +1,57 @@ +[ + { + "condition": { + "typeReachable": "io.seata.spring.annotation.datasource.SeataAutoDataSourceProxyAdvice" + }, + "name": "javax.sql.DataSource", + "allDeclaredMethods": true + }, + { + "condition": { + "typeReachable": "io.seata.spring.tcc.TccAnnotationProcessor" + }, + "name": "org.apache.dubbo.config.annotation.Reference" + }, + { + "condition": { + "typeReachable": "io.seata.spring.tcc.TccAnnotationProcessor" + }, + "name": "com.alipay.sofa.runtime.api.annotation.SofaReference" + }, + { + "condition": { + "typeReachable": "io.seata.spring.annotation.ScannerChecker" + }, + "name": "io.seata.spring.annotation.scannercheckers.PackageScannerChecker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.spring.annotation.ScannerChecker" + }, + "name": "io.seata.spring.annotation.scannercheckers.ConfigBeansScannerChecker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.spring.annotation.ScannerChecker" + }, + "name": "io.seata.spring.annotation.scannercheckers.ScopeBeansScannerChecker", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-antlr/reflect-config.json b/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-antlr/reflect-config.json new file mode 100644 index 00000000000..dac2a097694 --- /dev/null +++ b/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-antlr/reflect-config.json @@ -0,0 +1,38 @@ +[ + { + "condition": { + "typeReachable": "io.seata.sqlparser.antlr.SQLOperateRecognizerHolder" + }, + "name": "io.seata.sqlparser.antlr.mysql.MySQLOperateRecognizerHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.SQLRecognizerFactory" + }, + "name": "io.seata.sqlparser.antlr.AntlrDelegatingSQLRecognizerFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.antlr.AntlrDelegatingSQLRecognizerFactory" + }, + "name": "io.seata.sqlparser.antlr.mysql.AntlrMySQLRecognizerFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory b/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory index f8b91af9ded..492fd8b21f5 100644 --- a/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory +++ b/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory @@ -1 +1 @@ -io.seata.sqlparser.antlr.AntlrDelegatingSQLRecognizerFactory +io.seata.sqlparser.antlr.AntlrDelegatingSQLRecognizerFactory \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.antlr.SQLOperateRecognizerHolder b/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.antlr.SQLOperateRecognizerHolder index 177e9a18ffa..f3fa7ac6320 100644 --- a/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.antlr.SQLOperateRecognizerHolder +++ b/sqlparser/seata-sqlparser-antlr/src/main/resources/META-INF/services/io.seata.sqlparser.antlr.SQLOperateRecognizerHolder @@ -1 +1 @@ -io.seata.sqlparser.antlr.mysql.MySQLOperateRecognizerHolder +io.seata.sqlparser.antlr.mysql.MySQLOperateRecognizerHolder \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/reflect-config.json b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/reflect-config.json new file mode 100644 index 00000000000..a174a6e7942 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/reflect-config.json @@ -0,0 +1,86 @@ +[ + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.DruidDelegatingDbTypeParser" + }, + "name": "io.seata.sqlparser.druid.DruidDbTypeParserImpl", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory" + }, + "name": "io.seata.sqlparser.druid.DruidSQLRecognizerFactoryImpl", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.SQLOperateRecognizerHolder" + }, + "name": "io.seata.sqlparser.druid.mysql.MySQLOperateRecognizerHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.SQLOperateRecognizerHolder" + }, + "name": "io.seata.sqlparser.druid.oracle.OracleOperateRecognizerHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.SQLOperateRecognizerHolder" + }, + "name": "io.seata.sqlparser.druid.postgresql.PostgresqlOperateRecognizerHolder", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.SQLRecognizerFactory" + }, + "name": "io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.sqlparser.util.DbTypeParser" + }, + "name": "io.seata.sqlparser.druid.DruidDelegatingDbTypeParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/resource-config.json b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/resource-config.json new file mode 100644 index 00000000000..2b4710d907e --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/native-image/io.seata/seata-sqlparser-druid/resource-config.json @@ -0,0 +1,12 @@ +{ + "resources": { + "includes": [ + { + "condition": { + "typeReachable": "io.seata.sqlparser.druid.DefaultDruidLoader" + }, + "pattern": "\\Qlib\/sqlparser\/druid.jar\\E" + } + ] + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory index aeb0a351b7f..e360e22891c 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory +++ b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.SQLRecognizerFactory @@ -1 +1 @@ -io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory +io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser index a7a3494b374..a1eca58fd2a 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser +++ b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/io.seata.sqlparser.util.DbTypeParser @@ -1 +1 @@ -io.seata.sqlparser.druid.DruidDelegatingDbTypeParser +io.seata.sqlparser.druid.DruidDelegatingDbTypeParser \ No newline at end of file diff --git a/style/seata_suppressions.xml b/style/seata_suppressions.xml index eb7923380da..a933135d00b 100644 --- a/style/seata_suppressions.xml +++ b/style/seata_suppressions.xml @@ -31,4 +31,6 @@ files="[\\/]antlr[\\/]mysql[\\/]antlr[\\/]"/> + \ No newline at end of file diff --git a/tcc/src/main/resources/META-INF/native-image/io.seata/seata-tcc/reflect-config.json b/tcc/src/main/resources/META-INF/native-image/io.seata/seata-tcc/reflect-config.json new file mode 100644 index 00000000000..8b2f82a9ebd --- /dev/null +++ b/tcc/src/main/resources/META-INF/native-image/io.seata/seata-tcc/reflect-config.json @@ -0,0 +1,98 @@ +[ + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.parser.HSFRemotingParser" + }, + "name": "com.taobao.hsf.app.api.util.HSFApiConsumerBean" + }, + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.parser.HSFRemotingParser" + }, + "name": "com.taobao.hsf.app.api.util.HSFApiProviderBean" + }, + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.parser.HSFRemotingParser" + }, + "name": "com.taobao.hsf.app.spring.util.HSFSpringConsumerBean" + }, + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.parser.HSFRemotingParser" + }, + "name": "com.taobao.hsf.app.spring.util.HSFSpringProviderBean" + }, + { + "condition": { + "typeReachable": "io.seata.core.model.ResourceManager" + }, + "name": "io.seata.rm.tcc.TCCResourceManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.AbstractRMHandler" + }, + "name": "io.seata.rm.tcc.RMHandlerTCC", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.RemotingParser" + }, + "name": "io.seata.rm.tcc.remoting.parser.DubboRemotingParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.RemotingParser" + }, + "name": "io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.RemotingParser" + }, + "name": "io.seata.rm.tcc.remoting.parser.SofaRpcRemotingParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.rm.tcc.remoting.RemotingParser" + }, + "name": "io.seata.rm.tcc.remoting.parser.HSFRemotingParser", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/tcc/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager b/tcc/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager index b572908a4c9..c1b29118bb3 100644 --- a/tcc/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager +++ b/tcc/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager @@ -1 +1 @@ -io.seata.rm.tcc.TCCResourceManager +io.seata.rm.tcc.TCCResourceManager \ No newline at end of file diff --git a/test/src/test/resources/META-INF/native-image/io.seata/seata-test/reflect-config.json b/test/src/test/resources/META-INF/native-image/io.seata/seata-test/reflect-config.json new file mode 100644 index 00000000000..769abd68314 --- /dev/null +++ b/test/src/test/resources/META-INF/native-image/io.seata/seata-test/reflect-config.json @@ -0,0 +1,50 @@ +[ + { + "condition": { + "typeReachable": "io.seata.common.loader.LoaderTestSPI" + }, + "name": "io.seata.common.loader.LoaderTestImpl1", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.common.loader.LoaderTestSPI" + }, + "name": "io.seata.common.loader.LoaderTestImpl2", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.saga.engine.pcext.StateHandlerInterceptor" + }, + "name": "io.seata.saga.engine.mock.MockStateHandlerInterceptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReachable": "io.seata.saga.engine.pcext.StateRouterInterceptor" + }, + "name": "io.seata.saga.engine.mock.MockStateRouterInterceptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file diff --git a/tm/src/main/resources/META-INF/native-image/io.seata/seata-tm/reflect-config.json b/tm/src/main/resources/META-INF/native-image/io.seata/seata-tm/reflect-config.json new file mode 100644 index 00000000000..b108a5bb2e3 --- /dev/null +++ b/tm/src/main/resources/META-INF/native-image/io.seata/seata-tm/reflect-config.json @@ -0,0 +1,14 @@ +[ + { + "condition": { + "typeReachable": "io.seata.core.model.TransactionManager" + }, + "name": "io.seata.tm.DefaultTransactionManager", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] \ No newline at end of file From 65bc25f50c98b708a8ad4fe5f43bfb42d369eff4 Mon Sep 17 00:00:00 2001 From: liuqiufeng <775038282@qq.com> Date: Sun, 2 Jul 2023 18:18:45 +0800 Subject: [PATCH 71/76] feature: console integration saga-statemachine-designer (#5695) --- .../resources/static/console-fe/.eslintrc | 3 +- .../resources/static/console-fe/.gitignore | 3 +- .../static/console-fe/build/copyDesigner.js | 50 +++++ .../static/console-fe/build/copyFile.js | 21 ++- .../resources/static/console-fe/package.json | 4 +- .../resources/static/console-fe/src/app.tsx | 174 +++++++++--------- .../src/components/Header/Header.tsx | 71 ++++--- .../src/components/Iframe/Iframe.tsx | 59 ++++++ .../src/components/Iframe/index.scss | 15 ++ .../console-fe/src/components/Iframe/index.ts | 18 ++ .../static/console-fe/src/locales/en-us.ts | 1 + .../static/console-fe/src/locales/zh-cn.ts | 1 + .../static/console-fe/src/router.tsx | 4 +- .../static/console-fe/src/utils/request.ts | 2 +- .../src/main/resources/static/css/main.css | 7 +- console/src/main/resources/static/js/main.js | 31 ++-- .../saga-statemachine-designer/designer.html | 22 +++ .../saga-statemachine-designer/dist/bundle.js | 42 +++++ 18 files changed, 398 insertions(+), 130 deletions(-) create mode 100644 console/src/main/resources/static/console-fe/build/copyDesigner.js create mode 100644 console/src/main/resources/static/console-fe/src/components/Iframe/Iframe.tsx create mode 100644 console/src/main/resources/static/console-fe/src/components/Iframe/index.scss create mode 100644 console/src/main/resources/static/console-fe/src/components/Iframe/index.ts create mode 100644 console/src/main/resources/static/saga-statemachine-designer/designer.html create mode 100644 console/src/main/resources/static/saga-statemachine-designer/dist/bundle.js diff --git a/console/src/main/resources/static/console-fe/.eslintrc b/console/src/main/resources/static/console-fe/.eslintrc index bbb6e5c046a..1064957e137 100644 --- a/console/src/main/resources/static/console-fe/.eslintrc +++ b/console/src/main/resources/static/console-fe/.eslintrc @@ -30,6 +30,7 @@ "generator-star-spacing": "off", "wrap-iife": "off", "arrow-parens": "off", - "indent": "off" + "indent": "off", + "react/jsx-filename-extension": [2, { "extensions": [".js", ".jsx", ".ts", ".tsx"] }] } } diff --git a/console/src/main/resources/static/console-fe/.gitignore b/console/src/main/resources/static/console-fe/.gitignore index 5539ad8a506..03cbb7cf655 100644 --- a/console/src/main/resources/static/console-fe/.gitignore +++ b/console/src/main/resources/static/console-fe/.gitignore @@ -13,4 +13,5 @@ npm-debug.log* # test test/uirecorder.log test/reports -test/screenshots/* \ No newline at end of file +test/screenshots/* +/public/saga-statemachine-designer/ diff --git a/console/src/main/resources/static/console-fe/build/copyDesigner.js b/console/src/main/resources/static/console-fe/build/copyDesigner.js new file mode 100644 index 00000000000..32408fab96e --- /dev/null +++ b/console/src/main/resources/static/console-fe/build/copyDesigner.js @@ -0,0 +1,50 @@ +/** + * Copyright 1999-2019 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. + */ + +const fs = require('fs'); +const path = require('path'); +const childProcess = require('child_process') + +const mkdir = dir => { + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir); + } +}; + +// copy seata-saga-statemachine-designer to console +const designerDir = path.join(__dirname, '../../../../../../../saga/seata-saga-statemachine-designer'); +if (!fs.existsSync(path.join(designerDir, "dist"))) { + // if seata-saga-statemachine-designer not build, build this + childProcess.execSync('cd ' + designerDir + '&& npm install && npm run build') +} + +// copy file +const designerDestDir = path.join(__dirname,'../public/saga-statemachine-designer'); +const designerHtmlFileName = path.join(designerDestDir, 'designer.html'); +const designerBundleFileName = path.join(designerDestDir, 'dist/bundle.js'); + +mkdir(path.dirname(designerHtmlFileName)); +mkdir(path.dirname(designerBundleFileName)); + +fs.createReadStream(path.join(designerDir, 'index.html')) +.pipe( + fs.createWriteStream(designerHtmlFileName) + ); + +fs.createReadStream(path.join(designerDir, 'dist/bundle.js')) +.pipe( + fs.createWriteStream(designerBundleFileName) + ); \ No newline at end of file diff --git a/console/src/main/resources/static/console-fe/build/copyFile.js b/console/src/main/resources/static/console-fe/build/copyFile.js index af4cfcb1bde..41a486ceeac 100644 --- a/console/src/main/resources/static/console-fe/build/copyFile.js +++ b/console/src/main/resources/static/console-fe/build/copyFile.js @@ -42,4 +42,23 @@ copyList.forEach(_fileName => { const readStream = fs.createReadStream(srcFileName); const writeStream = fs.createWriteStream(destFileName); readStream.pipe(writeStream); -}); \ No newline at end of file +}); + +// copy seata-saga-statemachine-designer from console-fe/public to console resource folder +const designerDir = path.join(__dirname, '../public/saga-statemachine-designer'); +const designerDestDir = path.join(destDir, 'saga-statemachine-designer'); +const designerHtmlFileName = path.join(designerDestDir, 'designer.html'); +const designerBundleFileName = path.join(designerDestDir, 'dist/bundle.js'); + +mkdir(path.dirname(designerHtmlFileName)); +mkdir(path.dirname(designerBundleFileName)); + +fs.createReadStream(path.join(designerDir, 'designer.html')) +.pipe( + fs.createWriteStream(designerHtmlFileName) + ); + +fs.createReadStream(path.join(designerDir, 'dist/bundle.js')) +.pipe( + fs.createWriteStream(designerBundleFileName) + ); \ No newline at end of file diff --git a/console/src/main/resources/static/console-fe/package.json b/console/src/main/resources/static/console-fe/package.json index 27e9cb09c69..37a9f39dea4 100644 --- a/console/src/main/resources/static/console-fe/package.json +++ b/console/src/main/resources/static/console-fe/package.json @@ -4,8 +4,8 @@ "description": "console fe", "main": "index.js", "scripts": { - "start": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.conf.js", - "build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js && node build/copyFile.js", + "start": "node build/copyDesigner.js && cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.conf.js", + "build": "node build/copyDesigner.js && cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js && node build/copyFile.js", "eslint": "eslint --ext .js src/", "eslint-fix": "eslint --ext .js --fix src/" }, diff --git a/console/src/main/resources/static/console-fe/src/app.tsx b/console/src/main/resources/static/console-fe/src/app.tsx index b0b134f64ab..08e6c7254a9 100644 --- a/console/src/main/resources/static/console-fe/src/app.tsx +++ b/console/src/main/resources/static/console-fe/src/app.tsx @@ -19,13 +19,14 @@ import { connect } from 'react-redux'; import { Dispatch } from 'redux'; import { Router, Route, Switch, Redirect, RouteComponentProps } from 'react-router-dom'; import { ConfigProvider, Loading } from '@alicloud/console-components'; -import { createHashHistory, History } from "history"; +import { createHashHistory, History } from 'history'; import CCConsoleMenu from '@alicloud/console-components-console-menu'; import { GlobalStateModel } from '@/reducers'; import { changeLanguage, LocaleStateModel, getCurrentLanguage } from '@/reducers/locale'; import Layout from '@/layout'; import Login from '@/pages/Login'; import router from '@/router'; +import Iframe from './components/Iframe'; export const history: History = createHashHistory(); (window as any).globalHistory = history; @@ -35,100 +36,109 @@ export type OwnProps = any; export type StateToPropsType = LocaleStateModel; export type DispathToPropsType = { - changeLanguage: (lang: string) => void + changeLanguage: (lang: string) => void; }; export type AppPropsType = StateToPropsType & DispathToPropsType & RouteComponentProps & OwnProps; export type AppStateType = { - loading: object; -} + loading: object; +}; class App extends React.Component { - static propTypes = { - locale: PropTypes.object, - changeLanguage: PropTypes.func, - }; - - state: AppStateType = { - loading: {}, + static propTypes = { + locale: PropTypes.object, + changeLanguage: PropTypes.func, + }; + + state: AppStateType = { + loading: {}, + }; + + constructor(props: AppPropsType) { + super(props); + } + + componentDidMount() { + console.log('this.props: ', this.props, history); + const language: string = getCurrentLanguage(); + this.props.changeLanguage(language); + } + + get menu() { + const { locale }: AppPropsType = this.props; + const { MenuRouter = {} } = locale; + const { overview, transactionInfo, globalLockInfo, sagaStatemachineDesigner } = MenuRouter; + return { + items: [ + // { + // key: '/Overview', + // label: overview, + // }, + { + key: '/transaction/list', + label: transactionInfo, + }, + { + key: '/globallock/list', + label: globalLockInfo, + }, + { + key: '/sagastatemachinedesigner', + label: sagaStatemachineDesigner, + }, + ], + header: 'Seata', + onItemClick: (key: string) => history.push(key), }; - - constructor(props: AppPropsType) { - super(props); - } - - componentDidMount() { - console.log('this.props: ', this.props, history); - const language: string = getCurrentLanguage(); - this.props.changeLanguage(language); - } - - get menu() { - const { locale }: AppPropsType = this.props; - const { MenuRouter = {} } = locale; - const { overview,transactionInfo,globalLockInfo } = MenuRouter; - return { - items: [ - // { - // key: '/Overview', - // label: overview, - // }, - { - key: '/TransactionInfo', - label: transactionInfo, - }, - { - key:'/GlobalLockInfo', - label: globalLockInfo, - } - ], - header: 'Seata', - onItemClick: (key: string) => history.push(key) - } - } - - get router() { - return ( - - - - }> - } /> - {router.map(item => ( - - ))} - - - - ); - } - - render() { - const { locale } = this.props; - const { loading } = this.state; - return ( - - - {this.router} - - - ); - } + } + + get router() { + return ( + + + + ( + + )} + > + } /> + ( +