You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2018/10/21 00:39:07 UTC

[incubator-servicecomb-saga] branch master updated (5fb192b -> 181a7bd)

This is an automated email from the ASF dual-hosted git repository.

ningjiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git.


    from 5fb192b  Pulish the test script
     new 9163487  SCB-963 Make TCC coordinate method transactional.
     new 181a7bd  SCB-963 Make saga compensation method transactional.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../saga/omega/context/CallbackContext.java        |  4 +-
 .../spring/CompensableAnnotationProcessor.java     |  4 +-
 .../transaction/spring/MethodCheckingCallback.java | 46 +++++++++++++++++++++-
 .../spring/ParticipateAnnotationProcessor.java     |  4 +-
 .../transaction/spring/TccInterceptorTest.java     |  7 +---
 .../omega/transaction/spring/TccUserService.java   | 23 +++++------
 .../spring/TransactionalUserService.java           | 12 +++---
 7 files changed, 71 insertions(+), 29 deletions(-)


[incubator-servicecomb-saga] 01/02: SCB-963 Make TCC coordinate method transactional.

Posted by ni...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git

commit 91634874da8703203476db725d90cd8b97c0e687
Author: cherrylzhao <zh...@126.com>
AuthorDate: Fri Oct 19 18:00:10 2018 +0800

    SCB-963 Make TCC coordinate method transactional.
---
 .../saga/omega/context/CallbackContext.java        |  4 +-
 .../transaction/spring/MethodCheckingCallback.java | 46 +++++++++++++++++++++-
 .../spring/ParticipateAnnotationProcessor.java     |  4 +-
 .../transaction/spring/TccInterceptorTest.java     |  7 +---
 .../omega/transaction/spring/TccUserService.java   | 23 +++++------
 .../spring/TransactionalUserService.java           | 12 +++---
 6 files changed, 69 insertions(+), 27 deletions(-)

diff --git a/omega/omega-context/src/main/java/org/apache/servicecomb/saga/omega/context/CallbackContext.java b/omega/omega-context/src/main/java/org/apache/servicecomb/saga/omega/context/CallbackContext.java
index 0fe2613..cf5ab50 100644
--- a/omega/omega-context/src/main/java/org/apache/servicecomb/saga/omega/context/CallbackContext.java
+++ b/omega/omega-context/src/main/java/org/apache/servicecomb/saga/omega/context/CallbackContext.java
@@ -35,9 +35,9 @@ public class CallbackContext {
     this.omegaContext = omegaContext;
   }
 
-  public void addCallbackContext(Method compensationMethod, Object target) {
+  public void addCallbackContext(String key, Method compensationMethod, Object target) {
     compensationMethod.setAccessible(true);
-    contexts.put(compensationMethod.toString(), new CallbackContextInternal(target, compensationMethod));
+    contexts.put(key, new CallbackContextInternal(target, compensationMethod));
   }
 
   public void apply(String globalTxId, String localTxId, String callbackMethod, Object... payloads) {
diff --git a/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/MethodCheckingCallback.java b/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/MethodCheckingCallback.java
index 8a2ac13..6c52313 100644
--- a/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/MethodCheckingCallback.java
+++ b/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/MethodCheckingCallback.java
@@ -18,11 +18,15 @@
 package org.apache.servicecomb.saga.omega.transaction.spring;
 
 import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import org.apache.servicecomb.saga.omega.context.CallbackContext;
 import org.apache.servicecomb.saga.omega.transaction.OmegaException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.aop.framework.AdvisedSupport;
+import org.springframework.aop.framework.AopProxy;
+import org.springframework.aop.support.AopUtils;
 import org.springframework.util.ReflectionUtils.MethodCallback;
 
 public abstract class MethodCheckingCallback implements MethodCallback {
@@ -45,12 +49,50 @@ public abstract class MethodCheckingCallback implements MethodCallback {
     for (String each : candidates) {
       try {
         Method signature = bean.getClass().getDeclaredMethod(each, method.getParameterTypes());
-        callbackContext.addCallbackContext(signature, bean);
+        String key = getTargetBean(bean).getClass().getDeclaredMethod(each, method.getParameterTypes()).toString();
+        callbackContext.addCallbackContext(key, signature, bean);
         LOG.debug("Found callback method [{}] in {}", each, bean.getClass().getCanonicalName());
-      } catch (NoSuchMethodException ex) {
+      } catch (Exception ex) {
         throw new OmegaException(
             "No such " + callbackType + " method [" + each + "] found in " + bean.getClass().getCanonicalName(), ex);
       }
     }
   }
+
+  private Object getTargetBean(Object proxy) throws Exception {
+    if(!AopUtils.isAopProxy(proxy)) {
+      return proxy;
+    }
+
+    if(AopUtils.isJdkDynamicProxy(proxy)) {
+      return getJdkDynamicProxyTargetObject(proxy);
+    } else {
+      return getCglibProxyTargetObject(proxy);
+    }
+  }
+
+  private Object getCglibProxyTargetObject(Object proxy) throws Exception {
+    Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
+    h.setAccessible(true);
+    Object dynamicAdvisedInterceptor = h.get(proxy);
+
+    Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
+    advised.setAccessible(true);
+
+    Object result = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
+    return result;
+  }
+
+
+  private Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
+    Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
+    h.setAccessible(true);
+    AopProxy aopProxy = (AopProxy) h.get(proxy);
+
+    Field advised = aopProxy.getClass().getDeclaredField("advised");
+    advised.setAccessible(true);
+
+    Object result = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
+    return result;
+  }
 }
diff --git a/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/ParticipateAnnotationProcessor.java b/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/ParticipateAnnotationProcessor.java
index 5cef9ff..80583bd 100644
--- a/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/ParticipateAnnotationProcessor.java
+++ b/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/ParticipateAnnotationProcessor.java
@@ -36,13 +36,13 @@ class ParticipateAnnotationProcessor implements BeanPostProcessor {
 
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-    checkMethod(bean);
-    checkFields(bean);
     return bean;
   }
 
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+    checkMethod(bean);
+    checkFields(bean);
     return bean;
   }
 
diff --git a/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccInterceptorTest.java b/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccInterceptorTest.java
index bc9148b..7f43476 100644
--- a/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccInterceptorTest.java
+++ b/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccInterceptorTest.java
@@ -69,9 +69,6 @@ public class TccInterceptorTest {
   private List<String> messages;
 
   @Autowired
-  private OmegaContext omegaContext;
-
-  @Autowired
   private TccUserServiceMain tccUserServiceMain;
 
   @Autowired
@@ -95,7 +92,6 @@ public class TccInterceptorTest {
   public void tearDown() throws Exception {
     messages.clear();
     userRepository.deleteAll();
-    omegaContext.clear();
   }
 
   @AfterClass
@@ -152,7 +148,8 @@ public class TccInterceptorTest {
     );
 
     User result = userRepository.findByUsername(user.username());
-    assertThat(result, is(nullValue()));
+    assertThat(result.username(), is(user.username()));
+    assertThat(result.email(), is(user.email()));
 
     result = userRepository.findByUsername(jack.username());
     assertThat(result, is(nullValue()));
diff --git a/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccUserService.java b/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccUserService.java
index 8223a87..31da4c9 100644
--- a/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccUserService.java
+++ b/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TccUserService.java
@@ -20,26 +20,28 @@ package org.apache.servicecomb.saga.omega.transaction.spring;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.servicecomb.saga.omega.context.OmegaContext;
+import javax.annotation.Resource;
 import org.apache.servicecomb.saga.omega.transaction.annotations.Participate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 
 @Component
-class TccUserService {
+@Transactional
+public class TccUserService {
   static final String ILLEGAL_USER = "Illegal User";
-  private final UserRepository userRepository;
+
 
   @Autowired
   TccUserService(UserRepository userRepository) {
     this.userRepository = userRepository;
   }
 
+  @Resource
+  private UserRepository userRepository;
+
   @Participate(confirmMethod = "confirm", cancelMethod = "cancel")
-  User add(User user) {
+  public User add(User user) {
     // Only for the validation check
     if (ILLEGAL_USER.equals(user.username())) {
       throw new IllegalArgumentException("User is illegal");
@@ -47,15 +49,14 @@ class TccUserService {
     return userRepository.save(user);
   }
 
-  void confirm(User user) {
+  public void confirm(User user) {
     User result = userRepository.findByUsername(user.username());
     // Just make sure we can get the resource and keep doing other business
     assertThat(result, is(user));
   }
 
-  void cancel(User user) {
+  public void cancel(User user) {
     userRepository.delete(user);
+    throw new RuntimeException("transaction test");
   }
-
-
 }
diff --git a/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java b/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java
index 0618109..11bc437 100644
--- a/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java
+++ b/omega/omega-spring-tx/src/test/java/org/apache/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java
@@ -20,9 +20,11 @@ package org.apache.servicecomb.saga.omega.transaction.spring;
 import org.apache.servicecomb.saga.omega.transaction.annotations.Compensable;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 
 @Component
-class TransactionalUserService {
+@Transactional
+public class TransactionalUserService {
   static final String ILLEGAL_USER = "Illegal User";
   private final UserRepository userRepository;
 
@@ -38,19 +40,19 @@ class TransactionalUserService {
   }
 
   @Compensable(compensationMethod = "delete")
-  User add(User user) {
+  public User add(User user) {
     if (ILLEGAL_USER.equals(user.username())) {
       throw new IllegalArgumentException("User is illegal");
     }
     return userRepository.save(user);
   }
 
-  void delete(User user) {
+  public void delete(User user) {
     userRepository.delete(user);
   }
 
   @Compensable(retries = 2, compensationMethod = "delete")
-  User add(User user, int count) {
+  public User add(User user, int count) {
     if (this.count < count) {
       this.count += 1;
       throw new IllegalStateException("Retry harder");
@@ -59,7 +61,7 @@ class TransactionalUserService {
     return userRepository.save(user);
   }
 
-  void delete(User user, int count) {
+  public void delete(User user, int count) {
     resetCount();
     userRepository.delete(user);
   }


[incubator-servicecomb-saga] 02/02: SCB-963 Make saga compensation method transactional.

Posted by ni...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git

commit 181a7bd9efa064c59d58338d7b03e98bcbf1cceb
Author: cherrylzhao <zh...@126.com>
AuthorDate: Fri Oct 19 18:02:57 2018 +0800

    SCB-963 Make saga compensation method transactional.
---
 .../saga/omega/transaction/spring/CompensableAnnotationProcessor.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/CompensableAnnotationProcessor.java b/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/CompensableAnnotationProcessor.java
index 790394f..254c3e7 100644
--- a/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/CompensableAnnotationProcessor.java
+++ b/omega/omega-spring-tx/src/main/java/org/apache/servicecomb/saga/omega/transaction/spring/CompensableAnnotationProcessor.java
@@ -36,13 +36,13 @@ class CompensableAnnotationProcessor implements BeanPostProcessor {
 
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-    checkMethod(bean);
-    checkFields(bean);
     return bean;
   }
 
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+    checkMethod(bean);
+    checkFields(bean);
     return bean;
   }