为什么要创建 JBoss 所有这些交易

Why create JBoss all those transactions

我有一个 Restfull 服务,登录:

@POST
@Path("login")
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Response login(Credentials credentials) {
   // ask database if token exist
   // create token if necessary
}

当必须创建令牌时,我希望只有一个事务,但在日志记录中我发现有 4 个提交。 None 执行事务的 bean 用 @TransactionAttribute 注释。

为什么有 4 个提交?

2021-03-03 16:34:17,586 DEBUG [xx.x.LoginResource] (default task-1) Login
2021-03-03 16:34:17,586 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.begin
2021-03-03 16:34:17,591 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.commit
2021-03-03 16:34:17,592 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.begin
2021-03-03 16:34:17,594 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.commit
2021-03-03 16:34:17,595 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.begin
2021-03-03 16:34:17,596 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.begin
2021-03-03 16:34:17,597 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.commit
2021-03-03 16:34:17,610 TRACE [com.arjuna.ats.jta] (default task-1) BaseTransaction.commit

方法级注释 @TransactionAttribute 暗示使用 Container-Managed Transactions. As per JAX-RS specification, JAX-RS resources do not constitute a transaction boundary by themself, therefore they are not subject to the Container-Managed Transactions 的意图。

从 JavaEE 6 开始,只有 EJB 受制于 Container-Managed Transactions. JAX-RS specification 明确记录与支持 EJB 的容器的集成(重点是我的):

In a product that also supports EJB, an implementation MUST support use of stateless and singleton session beans as root resource classes, providers and Application subclasses. JAX-RS annotations MAY be applied to a bean’s local interface or directly to a no-interface bean. If an ExceptionMapper for a EJBException or subclass is not included with an application then exceptions thrown by an EJB resource class or provider method MUST be treated as EJB application exceptions: the embedded cause of the EJBException MUST be unwrapped and processed as described in section 3.3.4.

在这种特殊情况下,在 class 级别添加 javax.ejb.Stateless 注释就足够了:

@Path("/")
@Stateless
public class LoginResource {

    @POST
    @Path("login")
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public Response login(Credentials credentials) {
        // ask database if token exist
        // create token if necessary
    }

}

您也可以省略方法级别 @TransactionAttribute(TransactionAttributeType.REQUIRED),因为它是 EJB 的 default transaction attribute