diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index 419f3f63371..5aa6c195674 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -14,6 +14,7 @@ Add changes here for all PR submitted to the 2.x branch. - [[#7104](https://github.com/apache/incubator-seata/pull/7104)] fix impl of supportsSourceType is not defined - [[#7116](https://github.com/apache/incubator-seata/pull/7116)] fix prefix: seata.server.raft.ssl should not be null - [[#7112](https://github.com/apache/incubator-seata/pull/7112)] bugfix: remove the condition that IPv6 must start with fe80 +- [[#7107](https://github.com/apache/incubator-seata/pull/7107)] fix the issue of failing to parse annotations in TCC mode when the business object is a proxy object. ### optimize: @@ -50,6 +51,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [funky-eyes](https://github.com/funky-eyes) - [psxjoy](https://github.com/psxjoy) - [xiaoxiangyeyu0](https://github.com/xiaoxiangyeyu0) - +- [wxrqforever](https://github.com/wxrqforever) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. \ No newline at end of file diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index 2f7d72c5ef5..315feafa6d5 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -14,6 +14,7 @@ - [[#7104](https://github.com/apache/incubator-seata/pull/7104)] 修复SeataApplicationListener在低版本springboot未实现supportsSourceType方法的问题 - [[#7116](https://github.com/apache/incubator-seata/pull/7116)] 修复 seata.server.raft.ssl 前缀不存在的问题 - [[#7112](https://github.com/apache/incubator-seata/pull/7112)] 校验是否IPv6网络ip取消必须以fe80开始的条件 +- [[#7107](https://github.com/apache/incubator-seata/pull/7107)] 修复tcc模式下,当业务对象为代理对象时,解析注解失败问题。 ### optimize: @@ -49,5 +50,6 @@ - [funky-eyes](https://github.com/funky-eyes) - [psxjoy](https://github.com/psxjoy) - [xiaoxiangyeyu0](https://github.com/xiaoxiangyeyu0) +- [wxrqforever](https://github.com/wxrqforever) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 \ No newline at end of file diff --git a/spring/src/test/java/org/apache/seata/spring/SpringLocalTccTest.java b/spring/src/test/java/org/apache/seata/spring/SpringLocalTccTest.java new file mode 100644 index 00000000000..f4a72799c12 --- /dev/null +++ b/spring/src/test/java/org/apache/seata/spring/SpringLocalTccTest.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.spring; + +import java.io.IOException; +import org.apache.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler; +import org.apache.seata.rm.tcc.interceptor.parser.TccActionInterceptorParser; +import org.apache.seata.spring.tcc.TccAnnoAtInterAction; +import org.apache.seata.spring.tcc.TccAnnoAtInterActionImpl; +import org.apache.seata.spring.tcc.TccAnnoAtInterImplAction; +import org.apache.seata.spring.tcc.TccAnnoAtInterImplActionImpl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.aop.MethodBeforeAdvice; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.aop.support.NameMatchMethodPointcutAdvisor; + + +public class SpringLocalTccTest { + + + @BeforeAll + public static void init() throws IOException { + System.setProperty("config.type", "file"); + System.setProperty("config.file.name", "file.conf"); + System.setProperty("txServiceGroup", "default_tx_group"); + System.setProperty("service.vgroupMapping.default_tx_group", "default"); + } + + @Test + void testParserInterfaceToProxyForSpringCGLIB() throws Exception { + //local tcc anno at interface impl + { + TccActionInterceptorParser tccActionInterceptorParser = new TccActionInterceptorParser(); + TccAnnoAtInterImplActionImpl tccAction = new TccAnnoAtInterImplActionImpl(); + TccAnnoAtInterImplAction proxyTccAction = createSpringCGLIBProxy(tccAction, "doSomething", TccAnnoAtInterImplAction.class); + ProxyInvocationHandler proxyInvocationHandler = tccActionInterceptorParser.parserInterfaceToProxy(proxyTccAction, proxyTccAction.getClass().getName()); + Assertions.assertNotNull(proxyInvocationHandler); + } + + //local tcc anno at interface + { + TccActionInterceptorParser tccActionInterceptorParser = new TccActionInterceptorParser(); + TccAnnoAtInterActionImpl tccAction = new TccAnnoAtInterActionImpl(); + TccAnnoAtInterAction proxyTccAction = createSpringCGLIBProxy(tccAction, "doSomething", TccAnnoAtInterAction.class); + ProxyInvocationHandler proxyInvocationHandler = tccActionInterceptorParser.parserInterfaceToProxy(proxyTccAction, proxyTccAction.getClass().getName()); + Assertions.assertNotNull(proxyInvocationHandler); + } + } + + private T createSpringCGLIBProxy(T target, String methodName, Class interfaceClass) { + ProxyFactory proxyFactory = new ProxyFactory(target); + proxyFactory.setProxyTargetClass(true); + MethodBeforeAdvice advice = (method, args1, target1) -> System.out.println("test"); + NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(advice); + advisor.addMethodName(methodName); + proxyFactory.addAdvisor(advisor); + return interfaceClass.cast(proxyFactory.getProxy()); + } +} diff --git a/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterAction.java b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterAction.java new file mode 100644 index 00000000000..9b756237354 --- /dev/null +++ b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterAction.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.spring.tcc; + +import org.apache.seata.rm.tcc.api.BusinessActionContext; +import org.apache.seata.rm.tcc.api.LocalTCC; +import org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction; + +@LocalTCC +public interface TccAnnoAtInterAction { + + /** + * Prepare boolean. + * + * @param actionContext the action context + * @return the boolean + */ + @TwoPhaseBusinessAction(name = "TccAnnoAtInterAction", commitMethod = "commit", rollbackMethod = "rollback") + boolean prepare(BusinessActionContext actionContext); + + /** + * Commit boolean. + * + * @param actionContext the action context + * @return the boolean + */ + boolean commit(BusinessActionContext actionContext); + + /** + * Rollback boolean. + * + * @param actionContext the action context + * @return the boolean + */ + boolean rollback(BusinessActionContext actionContext); + +} diff --git a/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterActionImpl.java b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterActionImpl.java new file mode 100644 index 00000000000..37427ea2325 --- /dev/null +++ b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterActionImpl.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.spring.tcc; + +import org.apache.seata.rm.tcc.api.BusinessActionContext; + +public class TccAnnoAtInterActionImpl implements TccAnnoAtInterAction { + + @Override + public boolean prepare(BusinessActionContext actionContext) { + return false; + } + + @Override + public boolean commit(BusinessActionContext actionContext) { + return false; + } + + @Override + public boolean rollback(BusinessActionContext actionContext) { + return false; + } +} diff --git a/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterImplAction.java b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterImplAction.java new file mode 100644 index 00000000000..04fd8a7d41f --- /dev/null +++ b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterImplAction.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.spring.tcc; + +import org.apache.seata.rm.tcc.api.BusinessActionContext; + + +public interface TccAnnoAtInterImplAction { + + /** + * Prepare boolean. + * + * @param actionContext the action context + * @return the boolean + */ + boolean prepare(BusinessActionContext actionContext); + + /** + * Commit boolean. + * + * @param actionContext the action context + * @return the boolean + */ + boolean commit(BusinessActionContext actionContext); + + /** + * Rollback boolean. + * + * @param actionContext the action context + * @return the boolean + */ + boolean rollback(BusinessActionContext actionContext); + +} diff --git a/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterImplActionImpl.java b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterImplActionImpl.java new file mode 100644 index 00000000000..0b25b21044f --- /dev/null +++ b/spring/src/test/java/org/apache/seata/spring/tcc/TccAnnoAtInterImplActionImpl.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.spring.tcc; + +import org.apache.seata.rm.tcc.api.BusinessActionContext; +import org.apache.seata.rm.tcc.api.LocalTCC; +import org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction; + + +@LocalTCC +public class TccAnnoAtInterImplActionImpl implements TccAnnoAtInterImplAction { + + @Override + @TwoPhaseBusinessAction(name = "TccAnnoAtInterImplAction", commitMethod = "commit", rollbackMethod = "rollback") + public boolean prepare(BusinessActionContext actionContext) { + return false; + } + + @Override + public boolean commit(BusinessActionContext actionContext) { + return false; + } + + @Override + public boolean rollback(BusinessActionContext actionContext) { + return false; + } +} diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java index dc6a9d34248..718f1c8f2bd 100644 --- a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java +++ b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java @@ -121,6 +121,7 @@ private Annotation parseAnnotation(Method methodKey) throws NoSuchMethodExceptio if (twoPhaseBusinessAction == null && targetBean.getClass() != null) { Set> interfaceClasses = ReflectionUtil.getInterfaces(targetBean.getClass()); if (interfaceClasses != null) { + NoSuchMethodException exception = null; for (Class interClass : interfaceClasses) { try { Method m = interClass.getMethod(method.getName(), method.getParameterTypes()); @@ -131,9 +132,12 @@ private Annotation parseAnnotation(Method methodKey) throws NoSuchMethodExceptio break; } } catch (NoSuchMethodException e) { - throw new RuntimeException(e); + exception = e; } } + if (twoPhaseBusinessAction == null && exception != null) { + throw new RuntimeException(exception); + } } } return twoPhaseBusinessAction; diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java index 9d506919aaa..e014d012960 100644 --- a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java +++ b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java @@ -22,6 +22,7 @@ import org.apache.seata.core.model.Resource; import org.apache.seata.integration.tx.api.interceptor.ActionContextUtil; import org.apache.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler; +import org.apache.seata.integration.tx.api.interceptor.parser.DefaultTargetClassParser; import org.apache.seata.integration.tx.api.interceptor.parser.IfNeedEnhanceBean; import org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser; import org.apache.seata.integration.tx.api.interceptor.parser.NeedEnhanceEnum; @@ -40,8 +41,10 @@ public class TccActionInterceptorParser implements InterfaceParser { @Override - public ProxyInvocationHandler parserInterfaceToProxy(Object target, String objectName) { - Map> methodClassMap = ReflectionUtil.findMatchMethodClazzMap(target.getClass(), method -> method.isAnnotationPresent(getAnnotationClass())); + public ProxyInvocationHandler parserInterfaceToProxy(Object target, String objectName) + throws Exception { + Class targetClass = DefaultTargetClassParser.get().findTargetClass(target); + Map> methodClassMap = ReflectionUtil.findMatchMethodClazzMap(targetClass, method -> method.isAnnotationPresent(getAnnotationClass())); Set methodsToProxy = methodClassMap.keySet(); if (methodsToProxy.isEmpty()) { return null; diff --git a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java b/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java index 867b9c2de9c..870c08be1cc 100644 --- a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java +++ b/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java @@ -65,7 +65,7 @@ public void clearTccResource(){ } @Test - void parserInterfaceToProxy() { + void parserInterfaceToProxy() throws Exception { //given TccActionInterceptorParser tccActionInterceptorParser = new TccActionInterceptorParser();