自动注册XA Resource Spring Boot [英] Automatically register XA Resource Spring Boot

查看:175
本文介绍了自动注册XA Resource Spring Boot的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过持久支持PostgreSQL的Hazelcast和JPA在我的Spring Boot应用程序中实现XA事务.将Atomikos Spring Boot启动器放在我的pom.xml中可以加载JtaTransactionManager,以将其与@Transactional批注一起使用,但是Hazelcast XA资源并未参与该事务.

I'm trying to implement XA transactions in my Spring Boot app across Hazelcast and JPA persisting to PostgreSQL. Putting the Atomikos Spring Boot starter in my pom.xml got it to load the JtaTransactionManager to be used with the @Transactional annotations, but the Hazelcast XA Resource is not being enlisted with the transaction.

我如何让Spring Boot在使用JtaTransactionManager的AOP事务拦截器的一部分中自动使用JTA UserTransaction来招募我的XA资源?

How do I get Spring Boot to automatically enlist my XA Resources with the JTA UserTransaction as part of the AOP transaction interceptor that's using the JtaTransactionManager?

推荐答案

我通过使用注释和AspectJ Aspect解决了此问题,如此处.另请参阅,以定义匹配类或方法级别注释的切入点,您可能需要执行以下操作:

I solved this by using an annotation and AspectJ Aspect as described here. Also see this for defining the pointcuts to match either class or method level annotations, and you may need to do this:

@EnableTransactionManagement(order = Ordered.HIGHEST_PRECEDENCE) 

使事务拦截器在调用此代码之前发生.

to have the transaction interceptor happen before this code is called.

@Aspect
@Component
public class XAResourceAspect {
  @Autowired
  JtaTransactionManager jtaTransactionManager;

  @Autowired
  ApplicationContext applicationContext;

  @Pointcut("within(@XAResource *)")
  public void beanAnnotatedWithAnnotation() {}

  @Pointcut("execution(public * *(..))")
  public void publicMethod() {}

 @Pointcut("publicMethod() && beanAnnotatedWithAnnotation()")
  public void publicMethodInsideAnnotatedClass() {}

  private ThreadLocal<Map<Transaction, Set<String>>> enlistedResources = new ThreadLocal<>();

  @Around("@annotation(ppi.nestup.v3.annotation.XAResource) || publicMethodInsideAnnotatedClass()")
  public Object enlistResources(ProceedingJoinPoint joinPoint) throws Throwable {
    boolean setThreadLocal = false;
    Transaction transaction = jtaTransactionManager.getTransactionManager().getTransaction();
    if (transaction != null) {
      Map<Transaction, Set<String>> transactionMap = enlistedResources.get();
      LOG.info("Enlisting resources for joinpoint " + joinPoint + " and transaction " + transaction);
      if (transactionMap == null) {
        transactionMap = new HashMap<>();
        enlistedResources.set(transactionMap);
        setThreadLocal = true;
        LOG.info("Created new ThreadLocal for transaction " + transaction);
      } else {
        LOG.info("Found existing ThreadLocal " + transactionMap);
      }
      transactionMap.computeIfAbsent(transaction, k -> new HashSet<>());
      MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      Method method = signature.getMethod();
      Class withinType = joinPoint.getSourceLocation().getWithinType();

      XAResource annotation = method.getAnnotation(XAResource.class);
      if (annotation == null) {
        annotation = (XAResource) withinType.getAnnotation(XAResource.class);
      }
      String[] resourceNames = annotation.value();
      for (String name : resourceNames) {
        if (!transactionMap.get(transaction).contains(name)) {
          javax.transaction.xa.XAResource resource =
            (javax.transaction.xa.XAResource) applicationContext.getBean(name);
          try {
            transaction.enlistResource(resource);
          } catch (IllegalStateException e) {
            LOG.error("Caught exception trying to enlist resource " + name + " for transaction " + transaction + " and joinpoint " + joinPoint);
            e.printStackTrace();
          }
          transactionMap.get(transaction).add(name);
        }
      }
    }

    Object proceed = joinPoint.proceed();
    if (setThreadLocal) {
      LOG.info("Removing threadlocal");
      enlistedResources.remove();
    }
    return proceed;
  }
}

我还没有做很多测试,但是到目前为止,它已经可以工作了.

I haven't done a lot of testing of this yet, but it's working so far.

这篇关于自动注册XA Resource Spring Boot的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆