Manage transactions in Java EE @Transactional

Asked

Viewed 502 times

6

I’m having trouble trying to "inherit" the transaction from Java EE of my layer of service to the layer of repository. My intention is for the transaction to target my service function. Enabling me to do rollback if you have an error in your execution.

However, when I define the @Transactional of repository as Mandatory:

  • Returns a error saying that no active transaction exists

When I leave no parameter, default REQUIRED:

  • The repository creates a new transaction when an error occurs
  • Won’t let me do rollback of the modifications

How to send the transaction and allow to do rollback without problems using the @Transacional?

Service class.

@Inject
@InstanciaInject
MandadoRepositorio mandadoRepositorio;
@Transactional(rollbackOn = RuntimeException.class, 
                    value = Transactional.TxType.REQUIRES_NEW)
protected void metodoPrincipal() {
    String idPessoa = cookie.getIdPessoa().toString();
    mandadoPagRepositorio.alterarSituacaoMandadoBB(codigoDocumento, idPessoa);
}

Repositorio.class

public class MandadoRepositorio {
    @Transactional(Transactional.TxType.MANDATORY)
    public int alterarSituacaoMandadoBB(String param1, String param2) {
        return criarProcedure("PROCEDURE_NAME")
          .registrarInputOpcionalComValorPorNome("codigo", param1)
          .registrarInputOpcionalComValorPorNome("id", param2)
          .executeUpdate()
          .getUpdateCount();
    }
}

POM.xml

<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.2</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>javax.ejb</groupId>
    <artifactId>javax.ejb-api</artifactId>
    <version>3.2</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.interceptor</groupId>
    <artifactId>javax.interceptor-api</artifactId>
    <version>1.2.2</version>
</dependency>

Editing:

  • The class has been updated Mandadorepositorio.class
  • No use of Annotations @Stateless or @Statefull of the EJB
  • could you kindly include your class calling the repository with the Imports? And any statements if there are any (@Stateless, @TransactionManagement...)

  • @nullptr I tried to do the editing with as much detail as possible, just modifying the names of the methods and class. All annotations are duly recorded.

1 answer

6


When you use @Transactional(Transactional.TxType.MANDATORY), obligatorily you need to be with an open transaction before calling the method if you don’t get the exception as you yourself observed. You can read in the specification of MANDATORY

Just like any method annotated with @Transactional, will automatically give rollback if the exception released is of Runtime type, so you do not need the parameter rollbackOn at your service.

By default checked exceptions do not result in the Transactional Interceptor marking the transaction for rollback and instances of Runtimeexception and its subclasses do. This default behavior can be modified by specifying exceptions that result in the Interceptor marking the transaction for rollback and/or exceptions that do not result in rollback.

Excerpt from specification.

Based on this, what may be happening in your case, is that the exception being cast should not be "unchecked".

Having an Unchecked exception you should get the expected behavior "Out of the box"

EDIT

For you to use CDI with @Transactional, your application needs to be configured with the beans.xml to activate CDI. If you use the attribute bean-discovery-mode="all" in the beans.xml all your classes will already be automatically managed by CDI, but with the scope @Dependent which means that bean’s life cycle is coupled to the bean that uses a certain class. So the main hierarchy class must be annotated with some of the CDI scopes (@RequestScoped, @Singleton, @SessionScoped, etc.).

By configuring your classes correctly, you should get the expected JTA behavior.

Example of Beans.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee xmlns.jcp.org/xml/ns/javaee/…" 
bean-discovery-mode="all"> 
</beans>

Now using the annotations of EJB, the EJB container already manages the entire transaction part for you, without the need for you to use the annotation @Transactional.

  • theoretically I have an open transaction. Since in my Service layer I call metodoPrincipal() and I indicated her to create a new request for each action. I ended up solving the question using the annotation @Stateless of the EJB. But not to say exactly why.

  • Your class with the metodoPrincipal() is managed via CDI? @Stateless all private methods become transactional by default, so it usually works when you annotate the class with @Stateless. You don’t even need to write down the methods with @Transactional EJB container takes care of that for you. Unless you need more control over the transaction, ai vc can use JTA notes.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.