Understanding transaction attributes

In this post we’ll be talking about a subject that is little explored by most of the developers: Transaction attributes. When we’re creating a service (EJB, Spring..), we can either control the transaction manually (BMT – Bean Managed Transaction) or delegate this responsibility to the container (CMT – Container Managed Transaction). CMT is used in most of the cases and with declarative configuration and it’s for this type of configuration that the transaction attributes exist. They define, for example, if your method must or must not be invoked from within a transactional scope.

Just to make things easier and clearer, the term client in this post means the caller, that can be a standalone application, an EJB, a Spring Service, etc.

Types of transaction attributes

There are 6 types of transaction attributes:

Required

This is the default one. It means that the method can or cannot be invoked from within a transactional scope, but that it will obligatorily be executed inside a transaction.
If the client invokes it from a transaction, the method will be executed insided this same transaction, and the client is responsible for performing commit/rollback. If the client is not running a transaction, then a new transaction will be created to run the method and, by the end of its execution, the transaction will be committed/rolled back. This attribute is the most used one.

RequiresNew

It means that regardless of the client be running a transaction or not, a new transaction will be created to run the this method and, by the end of its execution, this transaction will be committed/rolled back.
If the client is running a transaction, it will be suspended until the completion of the new transaction. It’s worth to note that they are 2 distinct transactions, they are isolated from each other.

NotSupported

It means that the method will always be executed out of the transactional scope. If the client is running a transaction, it’s suspended until the method finishes. As the code is executed out of the transactional scope, it does not impact on the original transaction. If the client is not running a transaction, the method will be executed normally and no transaction will be created.

Supports

It means that the method will be executed in or out of a transaction, depending on the caller. If the caller invokes the method out of a transactional scope, no transaction will be created and the method will be executed out of a transaction. However, if the caller invokes this method from within a transaction, it will be executed within this same transaction.

Mandatory

It means that every time the caller invokes the method, if must be done from within a running transaction. In this case, the method will be executed within this same transaction. If the caller invokes the method out of a transactional scope, an exception will be thrown and the method won’t be executed.

Never

It means the caller must never be in a running transaction when it invokes the method. In this case, the method will be executed normally without creating any transaction. If the caller invokes the method from within a running transaction, an exception will be thrown and the method won’t be executed.

Defining the transaction attribute

Let’s briefly see how to declare the transaction attribute for your services using both EJB and Spring.

EJB

The simplest way to define the transaction attribute in an EJB is through annotations. This configuration can be done at class, method or both levels. For the declaration, the annotation @javax.ejb.TransactionAttribute must be used and the following values are accepted (of type javax.ejb.TransactionAttributeType):

  • TransactionAttributeType.REQUIRED
  • TransactionAttributeType.REQUIRES_NEW
  • TransactionAttributeType.NOT_SUPPORTED
  • TransactionAttributeType.SUPPORTS
  • TransactionAttributeType.MANDATORY
  • TransactionAttributeType.NEVER

Example:

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

@Stateless
//TransactionAttribute is only valid if TransactionManagement == TransactionManagementType.CONTAINER.
//That's the default value, so you can remove this annotation
@TransactionManagement(TransactionManagementType.CONTAINER)
//Required is the default value. This annotation can be removed.
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class Services {

	//No annotation uses the value defined at class level.
	public void service1() {

	}

	//Overrides the value defined at class level only for this method.
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void service2() {

	}

}

As any EJB configuration, XML option is also available. More details can be found here.

Spring

The configuration for Spring is very similar to the EJB one and can also be done by both annotations and XML. More details can be found here and here.

Conclusion

Despite the default configuration for transaction attribute be enough for most of the cases, it’s important to know what other options you have. This way, you can make fine adjustments that may be required for your application to work properly.

8 thoughts on “Understanding transaction attributes

  1. Luciano,

    O que esses escopos interferem na conexao ? Se for Mandatory ou required ele vai aproveitar a mesma conexão aberta ? E no caso de requires_new ele vai abrir uma nova conexao ?

    Obrigado.

    Abs,

    Rodrigo

    Like

  2. Luciano muito bom o post, bem objetivo. Estou com um problema onde minhas entidades são buscadas por um serviço ao retornar pra minha controller elas são detached, onde eu irei salvar uma entidade nova com referencia a estas entidades antes buscadas e o hibernate me fala que estão transientes e lança a famosa exception TransientObjectException.
    Estava vendo a documentação e me corrigi se eu estiver errado mas o padrão do JTA é session-per-request. Pra resolver este caso meu teria quer dar load() nas entidades de referencia dentro do escopo do serviço que salva a nova entidade.
    Sabe alguma outra solução?

    Like

    1. Olá Raul,
      Não sei se entendi muito bem sua pergunta..o escopo da transação pode ser definida de forma automática no seu EJB/Spring Bean..ou você pode iniciá-la e fechá-la manualmente..enfim, pode ser feito de várias maneiras.
      Abs!

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s