I have a Restfull service, login:
@POST
@Path("login")
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Response login(Credentials credentials) {
// ask database if token exist
// create token if necessary
}
When the token has to be created, I expect only one transaction, but in the logging I find 4 commits. None of the beans that does the transactions are annotated with @TransactionAttribute.
Why are there 4 commits?
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
Method-level annotation @TransactionAttribute
hints at the intent to use 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.
As of JavaEE 6, only EJBs are subject to Container-Managed Transactions. JAX-RS specification explicitly documents the integration with an EJB-enabled container (emphasis is mine):
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 anExceptionMapper
for aEJBException
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 theEJBException
MUST be unwrapped and processed as described in section 3.3.4.
In this particular case, it is enough to add the javax.ejb.Stateless
annotation at the class level:
@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
}
}
You may also omit method-level @TransactionAttribute(TransactionAttributeType.REQUIRED)
, as it is a default transaction attribute for EJBs.