Configuring Container-Managed Enterprise Components
Unlike regular client applications, enterprise components (EJBs) provide support for declarative transactions. Transactional attributes are associated with the component methods at deployment time, rather than being explicitly demarcated in the code.
The Declarative Transaction Model
In the declarative transaction model, it is the application server's responsibility to demarcate and manage the transaction based on the values declared in the deployment descriptors.
Container-Managed Transaction Attributes
Six transactional attributes may be assigned to an enterprise component:
These transaction attributes are configured in the enterprise component's ejb-jar.xml deployment descriptor, such as
<transaction-type>Container or Bean</transaction-type>
<trans-attribute>Mandatory or Supports or
Required or Requires New or Never or Not Supported</trans-attribute>
Transactional attributes can be configured to apply to the entire component or to a single method in the component's remote interface.
If attributes are specified at both the component and method levels, the method-level value takes precedence over the component-level value.
Let's look at each of these attributes in a little more detail, paying attention to what happens to a method call to a component when a transaction does or does not exist.
The NotSupported attribute ensures that the underlying component instance does not operate within a global transaction:
If a method is called from within a transaction, the container suspends the transaction before calling the component's method. When the component method returns, the container resumes the client's transaction before returning control to the client.
If a method is not called from within any transaction, the method will be called successfully.
This is not supported for Entity EJBs because all Entity EJB transactions must be managed by the container!
The Supports attribute ensures that the underlying component instance is included in any client-started transaction. However, the container will not start a transaction for the client. If the client does not start a transaction before calling the component's method, the component won't take part in any subsequent transactions. This mechanism allows a component to operate only within the client demarcation boundaries: Whether or not the method is called from within a global transaction, the method will always be called successfully.
The Mandatory attribute ensures that the component's method can be invoked by a client only if the client passes a global transaction to that component. This mechanism thereby forces the client program to always demarcate its own transaction boundaries:
If a method is called from within a transaction, the method call returns from the component successfully.
If a method is not called from within any transaction, the container does not start a transaction and a TransactionRequiredException is thrown because there must already be an underlying transaction.
The Required attribute forces a method call on a component to be always executed within a transaction started by either the client or the container:
If a method is called from within a transaction, the method call to the component returns successfully.
If a method is not called from within a transaction, the container first starts one, and then the method call returns from the component successfully.
The RequiresNew attribute ensures that the container always starts a transaction. It forces the component to execute within a new transaction that is to be started by the container only. The container always starts a localized transaction before calling any of the EJB's methods:
If a method is called from within a transaction, the client's transaction is suspended for the duration of the call to the component. The container starts its own localized transaction.
This scenario should be avoided because if an error occurs within the EJB, the error localization is the container only, even when the client might need to know about it!
If a method is not called from within any transaction, the container starts a localized transaction, and then the method call returns from the component successfully.
The Never attribute ensures that a method call to a component is never to take place within a transaction:
If a method is called from within a transaction, a RemoteException exception is thrown.
If a method is not called from within any transaction, the method call to the component is returned successfully.