gpt4 book ai didi

ejb - CDI + EJB 3 + EJB 事务

转载 作者:行者123 更新时间:2023-12-04 02:14:17 30 4
gpt4 key购买 nike

我需要审核 ejb bean 的调用。说审计我的意思是将当前登录的用户、方法名称、附加描述等信息写入数据库。我决定使用 CDI 装饰器来做到这一点:

@Decorator
public class AccountServiceBeanDecorator implements AccountService {

@Inject
@Delegate
@Any
AccountService accountService;

@EJB
private AuditService auditService;

@Override
public Account createAccount(Account account) {
auditService.saveAudit("Method: createAccount", currentUser, "Creating account by admin");
return accountService.createAccount(account);
}

}

和装饰类:

@Stateless
public class AccountServiceBean implements AccountService {

@Override
public Account createAccount(Account account) {
...
}
}

现在如果我从另一个 ejb 无状态 bean 调用 AccountService,事务会发生什么情况?

@Stateless
public ApplicationFacadeBean implements ApplicationFacade {

@EJB
private AccountService accountService;

@Override
public Account createAccount(Account account) {
return accountService.createAccount(account);
}

}

我想在装饰器 (AccountServiceBeanDecorator) 和装饰类 (AccountServiceBean) 中记录事务状态,因此我将 TransactionSynchronizationRegistry 作为资源注入(inject)到两个类中:

@Decorator
public class AccountServiceBeanDecorator implements AccountService {

@Inject
@Delegate
@Any
AccountService accountService;

@EJB
private AuditService auditService;

@Resource
private TransactionSynchronizationRegistry reg;

@Override
public Account createAccount(Account account) {
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
log.info("tx ({}): {}", new Object[] {reg.getTransactionStatus(), reg.getTransactionKey()});
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
auditService.saveAudit("Method: createAccount", currentUser, "Creating account by admin");
return accountService.createAccount(account);
}

}

@Stateless
public class AccountServiceBean implements AccountService {

@Resource
private TransactionSynchronizationRegistry reg;

@Override
public Account createAccount(Account account) {

log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
log.info("tx ({}): {}", new Object[] {reg.getTransactionStatus(), reg.getTransactionKey()});
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
...
}
}

我收到奇怪的行为:

  • 装饰器日志

    tx (0): JavaEETransactionImpl: txId=6 nonXAResource=null jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@68fb15d0]]] 
  • 第二个日志出现 NullPointerException(reg 为空)。

有人能给我解释一下吗?是否在与 ApplicationFacade 相同的事务中调用 AccountServiceBean 类?

谢谢

最佳答案

首先:我不会将 ejbs 与 cdi 拦截器混合使用。 ejbs 在拦截器实现上有它。

第二:拦截器与拦截器所在的ejb在同一个事务中执行。

可能的解决方案:

  • 创建正确的 ejb 拦截器
  • 将拦截器放在方法/类周围
  • 使用像这样的方法创建第二个 ejb (MyLoggerBean) logToDatabase(String message) 并使用 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)< 注释此方法/强>
  • 在拦截器内部创建一个这样的类成员:@EJB private MyLoggerBean loggerBean
  • 在您的 @AroundInvoke 注释方法中,您可以调用 loggerBean。 logToDatabase(...)

这将从拦截器所在的 ejb 的当前事务内部创建一个新事务

--> 我知道我的英语不是很好。但我希望你能理解我认为应该起作用的方法。如果我有时间,我会在 github 上做一个例子...

关于ejb - CDI + EJB 3 + EJB 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23120113/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com