首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CDI + EJB 3+ EJB事务

CDI + EJB 3+ EJB事务
EN

Stack Overflow用户
提问于 2014-04-16 21:05:03
回答 2查看 516关注 0票数 3

我需要审计ejb bean的调用。说审计,我指的是写信息,如当前日志记录的用户,方法名称,数据库的附加描述。我决定用CDI装饰器来做:

代码语言:javascript
复制
@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);
  }

}

还有被装饰的班级:

代码语言:javascript
复制
@Stateless
public class AccountServiceBean implements AccountService {

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

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

代码语言:javascript
复制
@Stateless
public ApplicationFacadeBean implements ApplicationFacade {

  @EJB
  private AccountService accountService;

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

}

我想记录装饰器(AccountServiceBeanDecorator)和装饰类(AccountServiceBean)中的事务状态,所以我在这两个类中注入了TransactionSynchronizationRegistry作为资源:

代码语言:javascript
复制
@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);
  }

}

代码语言:javascript
复制
@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 localTxStatus=0
  • 第二个日志上的NullPointerException (reg为空)。

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

谢谢

EN

回答 2

Stack Overflow用户

发布于 2015-01-22 20:12:17

first: i不会将ejbs与cdi拦截器混合。ejbs将其用于拦截器实现。

第二步:拦截器在与拦截器所在的事务相同的事务中执行。

可能的解决方案:

  • 创建正确的ejb拦截器
  • 将拦截器放在方法/类周围
  • 使用以下方法创建第二个ejb (MyLoggerBean) (字符串消息),并使用@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)对该方法进行注释
  • 在拦截器内部创建如下类成员:@EJB私有MyLoggerBean loggerBean
  • @AroundInvoke注释的方法中,可以调用loggerBean。logToDatabase(.)

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

--我知道我的英语不是很好。但我希望你明白我认为什么应该有效。如果我有时间,我在github上做个例子.

票数 1
EN

Stack Overflow用户

发布于 2014-04-20 02:13:39

嗯..。你用的是什么容器?通常,我不会怀疑CDI装饰师在EJB上工作.我想不出在JEE规范中我遇到的任何东西都能提供证据。

但是,面对你的问题,我是用拦截器,而不是装饰器。这些都得到EJB规范的支持.总之,这是我的代码,在您的情况下,您需要从上下文中获取变量:

代码语言:javascript
复制
import java.lang.reflect.Method;

import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

public class InvocationCountInterceptor {
    @Inject
    private InvocationCounter counter;

    @AroundInvoke
    public Object intercept(InvocationContext ctx) throws Exception {
        Object returnValue = ctx.proceed();
        Class<? extends Object> className = ctx.getTarget().getClass();
        Method methodName = ctx.getMethod();
        counter.incrementCounter(className, methodName);
        return returnValue;
    }
}

然后,不管您想要审计哪个EJB或EJB方法,我只是添加了以下内容:@Interceptors(InvocationCountInterceptor.class)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23120113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档