This is an automated email from the ASF dual-hosted git repository. jianbin pushed a commit to branch 2.x in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push: new 1d5c55ac1c bugfix: fix order() behavior in GlobalTransactionalInterceptorHandler to ensure correct sorting of invocation handlers (#7570) 1d5c55ac1c is described below commit 1d5c55ac1c89c1ab883ccf75d5f4f95688384d9f Author: keepConcentration <phm...@gmail.com> AuthorDate: Wed Aug 13 16:42:40 2025 +0900 bugfix: fix order() behavior in GlobalTransactionalInterceptorHandler to ensure correct sorting of invocation handlers (#7570) --- changes/en-us/2.x.md | 6 +- changes/zh-cn/2.x.md | 3 +- .../handler/AbstractProxyInvocationHandler.java | 5 + .../GlobalTransactionalInterceptorHandler.java | 5 + .../handler/ProxyInvocationHandler.java | 4 +- .../parser/DefaultInterfaceParserTest.java | 137 +++++++++++++++++++++ 6 files changed, 154 insertions(+), 6 deletions(-) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index 52df620a7a..702f5b4425 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -32,6 +32,7 @@ Add changes here for all PR submitted to the 2.x branch. - [[#7546](https://github.com/seata/seata/pull/7546)] fix client spring version compatible - [[#7505](https://github.com/apache/incubator-seata/pull/7505)] prevent Netty I/O thread blocking by async channel release via reconnectExecutor - [[#7563](https://github.com/apache/incubator-seata/pull/7563)] Fix NPE when server-side filter is disabled and filter chain is null. +- [[#7568](https://github.com/apache/incubator-seata/pull/7568)] Fix order() behavior in GlobalTransactionalInterceptorHandler to ensure correct sorting of invocation handlers @@ -39,8 +40,8 @@ Add changes here for all PR submitted to the 2.x branch. - [[#7478](https://github.com/apache/incubator-seata/pull/7484)] optimize: remove client id metric - [[#7557](https://github.com/seata/seata/pull/7557)] upgrade some npmjs dependencies -- [[#7577](https://github.com/seata/seata/pull/7577)] remove the 4MB size limit when decompressing with zstd -- [[#7578](https://github.com/seata/seata/pull/7578)] zstd decompression is changed from jni to ZstdInputStream +- [[#7577](https://github.com/seata/seata/pull/7577)] remove the 4MB size limit when decompressing with zstd +- [[#7578](https://github.com/seata/seata/pull/7578)] zstd decompression is changed from jni to ZstdInputStream ### security: @@ -76,6 +77,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [KoKimSS](https://github.com/KoKimSS) - [maple525866](https://github.com/maple525866) - [funky-eyes](https://github.com/funky-eyes) +- [keepConcentration](https://github.com/keepConcentration) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index e53d7a531d..d6a6930b2a 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -32,7 +32,7 @@ - [[#7546](https://github.com/seata/seata/pull/7546)] 修复客户端spring版本兼容 - [[#7505](https://github.com/apache/incubator-seata/pull/7505)] 通过使用 reconnectExecutor 异步释放 channel,防止阻塞 Netty I/O 线程 - [[#7563](https://github.com/apache/incubator-seata/pull/7563)] 修复在未开启服务端过滤器的状态下导致的过滤器链空指针异常 - +- [[#7568](https://github.com/apache/incubator-seata/pull/7568)] 修复 GlobalTransactionalInterceptorHandler 中的 order() 方法行为,确保拦截器的正确排序 ### optimize: @@ -74,6 +74,7 @@ - [KoKimSS](https://github.com/KoKimSS) - [maple525866](https://github.com/maple525866) - [funky-eyes](https://github.com/funky-eyes) +- [keepConcentration](https://github.com/keepConcentration) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/AbstractProxyInvocationHandler.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/AbstractProxyInvocationHandler.java index 7ebe914c56..2c0df8ee57 100644 --- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/AbstractProxyInvocationHandler.java +++ b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/AbstractProxyInvocationHandler.java @@ -62,6 +62,11 @@ public abstract class AbstractProxyInvocationHandler implements ProxyInvocationH return this.order; } + @Override + public int order() { + return this.order; + } + @Override public void setNextProxyInvocationHandler(ProxyInvocationHandler next) { this.nextInvocationHandlerChain = next; diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/GlobalTransactionalInterceptorHandler.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/GlobalTransactionalInterceptorHandler.java index 3731a63b10..aa70dfd3bb 100644 --- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/GlobalTransactionalInterceptorHandler.java +++ b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/GlobalTransactionalInterceptorHandler.java @@ -442,4 +442,9 @@ public class GlobalTransactionalInterceptorHandler extends AbstractProxyInvocati public String type() { return InvocationHandlerType.GlobalTransactional.name(); } + + @Override + public int order() { + return 0; + } } diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/ProxyInvocationHandler.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/ProxyInvocationHandler.java index 0891c68991..9cf3410e9a 100644 --- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/ProxyInvocationHandler.java +++ b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/interceptor/handler/ProxyInvocationHandler.java @@ -32,9 +32,7 @@ public interface ProxyInvocationHandler extends SeataInterceptor { String type(); - default int order() { - return 0; - } + int order(); void setNextProxyInvocationHandler(ProxyInvocationHandler next); } diff --git a/integration-tx-api/src/test/java/org/apache/seata/integration/tx/api/interceptor/parser/DefaultInterfaceParserTest.java b/integration-tx-api/src/test/java/org/apache/seata/integration/tx/api/interceptor/parser/DefaultInterfaceParserTest.java new file mode 100644 index 0000000000..5a57b49778 --- /dev/null +++ b/integration-tx-api/src/test/java/org/apache/seata/integration/tx/api/interceptor/parser/DefaultInterfaceParserTest.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.integration.tx.api.interceptor.parser; + +import org.apache.seata.integration.tx.api.interceptor.InvocationWrapper; +import org.apache.seata.integration.tx.api.interceptor.SeataInterceptorPosition; +import org.apache.seata.integration.tx.api.interceptor.handler.AbstractProxyInvocationHandler; +import org.apache.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DefaultInterfaceParserTest { + + @Test + public void testHandlerOrdering() { + // Create handlers with different orders + TestHandler handler1 = new TestHandler("handler1", 3); + TestHandler handler2 = new TestHandler("handler2", 1); + TestHandler handler3 = new TestHandler("handler3", 2); + + // Add handlers to a list + List<ProxyInvocationHandler> handlers = new ArrayList<>(); + handlers.add(handler1); + handlers.add(handler2); + handlers.add(handler3); + + // Sort handlers using the same comparator as in DefaultInterfaceParser + Collections.sort(handlers, Comparator.comparingInt(ProxyInvocationHandler::order)); + + // Verify the order + assertEquals("handler2", handlers.get(0).type()); + assertEquals("handler3", handlers.get(1).type()); + assertEquals("handler1", handlers.get(2).type()); + } + + @Test + public void testSetOrderAndSorting() { + // Create handlers with different order values + TestHandler handler1 = new TestHandler("handler1", 1); + TestHandler handler2 = new TestHandler("handler2", 2); + TestHandler handler3 = new TestHandler("handler3", 3); + TestHandler handler4 = new TestHandler("handler4", 4); + + // Set order values using setOrder method + handler1.setOrder(4); + handler2.setOrder(3); + handler3.setOrder(2); + handler4.setOrder(1); + + // Add handlers to list + List<ProxyInvocationHandler> handlers = new ArrayList<>(); + handlers.add(handler1); + handlers.add(handler2); + handlers.add(handler3); + handlers.add(handler4); + + // Verify order values before sorting + assertEquals(4, handlers.get(0).order()); + assertEquals(3, handlers.get(1).order()); + assertEquals(2, handlers.get(2).order()); + assertEquals(1, handlers.get(3).order()); + + // Sort handlers by order() method + Collections.sort(handlers, Comparator.comparingInt(ProxyInvocationHandler::order)); + + // Verify sorted order + assertEquals("handler4", handlers.get(0).type()); // order: 1 + assertEquals("handler3", handlers.get(1).type()); // order: 2 + assertEquals("handler2", handlers.get(2).type()); // order: 3 + assertEquals("handler1", handlers.get(3).type()); // order: 4 + + // Verify order values after sorting + assertEquals(1, handlers.get(0).order()); + assertEquals(2, handlers.get(1).order()); + assertEquals(3, handlers.get(2).order()); + assertEquals(4, handlers.get(3).order()); + } + + /** + * Test implementation of ProxyInvocationHandler + */ + private static class TestHandler extends AbstractProxyInvocationHandler { + private final String name; + + public TestHandler(String name, int order) { + this.name = name; + this.order = order; + } + + @Override + protected Object doInvoke(InvocationWrapper invocation) throws Throwable { + return null; + } + + @Override + public Set<String> getMethodsToProxy() { + return new HashSet<>(); + } + + @Override + public SeataInterceptorPosition getPosition() { + return SeataInterceptorPosition.BeforeTransaction; + } + + @Override + public String type() { + return name; + } + + @Override + public int order() { + return this.order; + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org For additional commands, e-mail: notifications-h...@seata.apache.org