Guillermo Luque
Guillermo Luque

Reputation: 1426

How can I get a database transaction in a JAX-RS method which does operations on many JPA entities?

According to the following sample class:

@Stateless
@Path("/evento")
public class EventoEndpoint {

    @PersistenceContext
    private EntityManager em;

    @POST
    @Consumes("application/json")
    public Response create(Evento entity) throws Exception {            

        // Get a record from Bitacora table
        TypedQuery<Bitacora> findBitacora = em.createQuery(
                    "SELECT b FROM Bitacora b WHERE b.id = :bitacoraId",
                    Bitacora.class);
        findBitacora.setParameter("bitacoraId", entity.getBitacora().getId());
        Bitacora bitacora = findBitacora.getSingleResult();

        // Increment by one a field from the current bitacora record
        Long interno = bitacora.getInterno() + 1;

        // Assign the new number to entity.interno property
        entity.setInterno(interno);

        // Update number in bitacora record
        bitacora.setInterno(interno);

        // save bitacora record
        em.persist(bitacora);

        // an intentionally launched exception
        if (interno > 0) throw new Exception("error en el sistema");

        // save the entity
        em.persist(entity); 

        // return a response
        return Response.ok(user).build();
    }
}

I expected that in this case, a call to the post method from a HTTP client had had to launch the exception so the database operations involved must to rollback.

It means, there should be no changes in database records at all.

Obviously that has not happened, because after launch the method, one entity is affected in database (bitacora) and the other one not (evento).

So, what is wrong in my code or how can I get a database transaction inside of a JAX-RS method?

Upvotes: 1

Views: 201

Answers (1)

B&#225;rtfai Tam&#225;s
B&#225;rtfai Tam&#225;s

Reputation: 2464

Checked exceptions in EJBs are Application Exceptions by default. Throwing an Application Exception doesn't rollback the transaction unless configured to do so.

You can

  • configure your exception to rollback the transaction, either via @ApplicationException(rollback=true) or the deployment descriptor.
  • call EJBContext.setRollbackOnly() method to explicitly rollback the transaction.

The spec contains all the details in chapters Support for Transactions and Exception Handling.

Upvotes: 2

Related Questions