Exceptions and Transactions

Exceptions have a large impact on the outcome of transactions.

System Exceptions Versus Application Exceptions

System exceptions are java.lang.RuntimeException and its subtypes, including EJBException. An application exception is any exception that does not extend java.lang.RuntimeException or java.rmi.RemoteException.

Warning

An application exception must never extend the RuntimeException, the RemoteException, or one of their subtypes.

Transactions are automatically rolled back if a system exception is thrown from an enterprise bean method. Transactions are not automatically rolled back if an application exception is thrown. If you remember these two rules, you will be well prepared to deal with exceptions and transactions in EJB. The bookPassage( ) method illustrates how to use application exceptions:

public TicketDO bookPassage(CreditCardDO card, double price)
    throws IncompleteConversationalState {
                   
    if (customer == null || cruise == null || cabin == null) {
        throw new IncompleteConversationalState( );
    }
    try {
        ReservationHomeLocal resHome = (ReservationHomeLocal)
            jndiContext.lookup("java:comp/env/ejb/ReservationHomeLocal");
            
        ReservationLocal reservation =
            resHome.create(customer, cruise, cabin, price);
                
        Object ref = 
            jndiContext.lookup("java:comp/env/ejb/ProcessPaymentHomeRemote");

        ProcessPaymentHomeRemote ppHome = (ProcessPaymentHomeRemote)
            PortableRemoteObject.narrow(ref, ProcessPaymentHomeRemote.class);
            
        ProcessPaymentRemote process = ppHome.create( );
        process.byCredit(customer, card, price);

        TicketDO ticket = new TicketDO(customer,cruise,cabin,price);

        return ticket;
    } catch(Exception e) {
        throw new EJBException(e);
    }
}

System exceptions

System exceptions include RuntimeException and its subclasses. The EJBException is a subclass of the RuntimeException, so it is considered a system exception.

System exceptions always cause a transaction to roll back when they are thrown from an enterprise bean method. Any RuntimeException (EJBException, NullPointerException, IndexOutOfBoundsException, and so on) thrown within the bookPassage( ) method is handled by the container automatically and results in a transaction rollback. In Java, RuntimeException types do not need to be declared in the throws clause of the method signature or handled using try/catch blocks; they are automatically thrown from the method.

The container handles system exceptions automatically; it will always:

  • Roll back the transaction.

  • Log the exception to alert the system administrator.

  • Discard the EJB instance.

When a system exception is thrown from the callback methods (ejbLoad( ), ejbActivate( ), and so on) are treated the same as exceptions thrown from business methods.

While EJB requires system exceptions must be logged, it does not specify how exceptions should be logged or the format of the log file. The exact mechanism for recording exceptions and reporting them to the system administrator is left to the vendor.

When a system exception occurs, the EJB instance is discarded, which means that it is dereferenced and garbage collected. The container assumes that the EJB instance may have corrupt variables or otherwise be unstable and is therefore unsafe to use.

The impact of discarding an EJB instance depends on the enterprise bean’s type. In the case of stateless session beans and entity beans, the client does not notice that the instance was discarded. These instance types are not dedicated to a particular client; they are swapped in and out of an instance pool, so any instance can service a new request. With stateful session beans, however, the impact on the client is severe. Stateful session beans are dedicated to a single client and maintain conversational state. Discarding a stateful bean instance destroys the instance’s conversational state and invalidates the client’s reference to the EJB. When stateful session instances are discarded, subsequent invocations of the EJB’s methods by the client result in a NoSuchObjectException, a subclass of the RemoteException.[51]

With message-driven beans, a system exception thrown by the onMessage( ) method or one of the callback methods (ejbCreate( ) or ejbRemove( )) will cause the bean instance to be discarded. If the MDB was a BMT bean, the message it was handling may or may not be redelivered, depending on when the EJB container acknowledges delivery. In the case of container-managed transactions, the container will roll back the transaction, so the message will not be acknowledged and may be redelivered.

In session and entity beans, when a system exception occurs and the instance is discarded, a RemoteException is always thrown to remote clients—that is, clients using the beans’ remote component interfaces. If the client started the transaction, which was then propagated to the EJB, a system exception (thrown by the enterprise bean method) will be caught by the container and rethrown as a javax.transaction.TransactionRolledbackException. The TransactionRolledbackException is a subtype of the RemoteException; it is a more explicit indication to the client that a rollback occurred.

In EJB session and entity beans, when a system exception occurs and the instance is discarded, an EJBException is always thrown to any local enterprise bean clients (i.e., clients using the enterprise bean’s local component interfaces). If the client started the transaction and it was then propagated to the EJB, a system exception (thrown by the enterprise bean method) will be caught by the container and rethrown as a javax.ejb.TransactionRolledbackLocalException. The TransactionRolledbackLocalException is a subtype of the EJBException; it is a more explicit indication to the client that a rollback occurred. In all other cases, whether the EJB is container-managed or bean-managed, a RuntimeException thrown from within the enterprise bean method will be caught by the container and rethrown as an EJBException.

An EJBException should generally be thrown when a subsystem throws an exception, such as JDBC throwing a SQLException or JMS throwing a JMSException. In some cases, however, the bean developer may attempt to handle the exception and retry an operation rather then throw an EJBException. This should be done only when the exceptions thrown by the subsystem and their repercussions on the transaction are well understood. As a rule of thumb, rethrow subsystem exceptions as EJBExceptions and allow the EJB container to roll back the transaction and discard the bean instance.

Warning

The callback methods defined in the javax.ejb.EntityBean and javax.ejb.SessionBean interfaces declare the java.rmi.RemoteException in their throws clauses. This is left over from EJB 1.0 and has been deprecated since EJB 1.1. You should never throw RemoteExceptions from callback methods or any other bean class methods.

Application exceptions

An application exception is normally thrown in response to a business-logic error, as opposed to a system error. Application exceptions are always delivered directly to the client, without being repackaged as RemoteException or EJBException types. They do not typically cause transactions to roll back; the client usually has an opportunity to recover after an application exception is thrown. For example, the bookPassage( ) method throws an application exception called IncompleteConversationalState; this is an application exception because it does not extend RuntimeException or RemoteException. The IncompleteConversationalState exception is thrown if one of the arguments passed into the bookPassage( ) method is null. (Application errors are frequently used to report validation errors like this.) In this case, the exception is thrown before tasks are started and is clearly not the result of a subsystem failure (e.g., JDBC, JMS, Java RMI, JNDI).

Because it is an application exception, throwing an IncompleteConversationalState exception does not result in a transaction rollback. The exception is thrown before any work is done, avoiding unnecessary processing by the bookPassage( ) method and providing the client (the enterprise bean or application that invoked the bookPassage( ) method) with an opportunity to recover and possibly retry the method call with valid arguments.

Business methods defined in the remote and local interfaces can throw any kind of application exception. These application exceptions must be declared in the method signatures of the remote and local interfaces and in the corresponding methods in the enterprise EJB classes.

The EJB create, find, and remove methods can also throw several exceptions defined in the javax.ejb package: CreateException, DuplicateKeyException, FinderException, ObjectNotFoundException, and RemoveException. These exceptions are considered application exceptions: they are delivered to the client as-is, without being repackaged as RemoteExceptions. Furthermore, these exceptions don’t necessarily cause a transaction to roll back, giving the client the opportunity to retry the operation. These exceptions may be thrown by the EJBs themselves; in the case of container-managed persistence, the container can also throw any of these exceptions while handling the EJB’s create, find, or remove methods (ejbCreate( ), ejbFind( ), and ejbRemove( )). The container might, for example, throw a CreateException if it encounters a bad argument while attempting to insert a record for a container-managed EJB. You can always choose to throw a standard application exception from the appropriate method regardless of how persistence is managed.

Here is a detailed explanation of the five standard application exceptions and the situations in which they are thrown:

CreateException

CreateException is thrown by the create( ) method in the remote interface. The container can throw this exception if the container is managing persistence, or it can be thrown explicitly by the EJB developer in the ejbCreate( ) or ejbPostCreate( ) methods. It indicates that an application error (invalid arguments, etc.) occurred while the EJB was being created. If the container throws this exception, it may or may not roll back the transaction. Explicit transaction methods must be used to determine the outcome. Bean developers should roll back the transaction before throwing this exception only if data integrity is a concern.

DuplicateKeyException

DuplicateKeyException is a subtype of CreateException; it is thrown by the create( ) method in the remote interface. The container can throw this exception if the container is managing persistence, or it can be thrown explicitly by the EJB developer in the ejbCreate( ) method. It indicates that an EJB with the same primary key already exists in the database. The EJB provider or container typically does not roll the transaction back before throwing this exception.

FinderException

FinderException is thrown by the find methods in the home interface. The container can throw this exception if the container is managing persistence, or it can be thrown explicitly by the EJB developer in the ejbFind( ) methods. It indicates that an application error (invalid arguments, etc.) occurred while the container was attempting to find the EJBs. Do not use this method to indicate that entities were not found. Multi-entity find methods return an empty collection if no entities were found; single-entity find methods throw an ObjectNotFoundException to indicate that no object was found. The EJB provider or container typically does not roll the transaction back before throwing this exception.

ObjectNotFoundException

ObjectNotFoundException is thrown from a single-entity find method to indicate the container could not find the requested entity. This exception can be thrown either by the container (if the container is managing persistence) or explicitly by the EJB developer in the ejbFind( ) methods. It shouldn’t be thrown to indicate a business-logic error (invalid arguments, etc.). Use the FinderException to indicate business-logic errors in single-entity find methods. The ObjectNotFoundException is thrown by single-entity find methods only to indicate that the entity requested was not found. Find methods that return multiple entities should return an empty collection if nothing is found. The EJB provider or container typically does not roll the transaction back before throwing this exception.

RemoveException

The RemoveException is thrown from the remove( ) methods in the remote and home interfaces. The container can throw this exception if the container is managing persistence, or it can be thrown explicitly by the EJB developer in the ejbRemove( ) method. It indicates that an application error has occurred while the EJB was being removed. The transaction may or may not have been rolled back by the container before throwing this exception. Explicit transaction methods must be used to determine the outcome. Bean developers should roll back the transaction before throwing the exception only if data integrity is a concern.

Table 16-1 summarizes the interactions between different types of exceptions and transactions in session and entity beans.

Table 16-1. Exception summary for session and entity beans

Transaction scope

Transaction type attributes

Exception thrown

Container’s action

Client’s view

Client-initiated transaction.

The transaction is started by the client (application or EJB) and propagated to the enterprise bean method.

transaction-type =Container

transaction-attribute = Required | Mandatory |Supports

Application exception

If the EJB invoked setRollbackOnly( ), mark the client’s transaction for rollback.

Rethrow the application exception.

Receives the application exception. The client’s transaction may or may not have been marked for rollback.

System exception

Mark the client’s transaction for rollback.

Log the error.

Discard the instance.

Rethrow the JTA TransactionRolledbackException to remote clients or the javax.ejb.TransactionRolledbackLocalException to EJB local clients.

Remote clients receive the JTA TransactionRolledbackException; local clients receive the javax.ejb.TransactionRolledbackLocalException.

The client’s transaction has been rolled back.

Container-mangaged transaction.

The transaction started when the EJB’s method was invoked and will end when the method completes.

transaction-type =Container

transaction-attribute = Required | RequiresNew

Application exception

If the EJB invoked setRollbackOnly( ), roll back the transaction and rethrow the application exception.

If the EJB did not explicitly roll back the transaction, attempt to commit the transaction and rethrow the application exception.

Receives the application exception. The EJB’s transaction may or may not have been rolled back. The client’s transaction is not affected.

System exception

Roll back the transaction.

Log the error.

Discard the instance.

Rethrow the RemoteException to remote clients or the EJBException to EJB local clients.

Remote clients receive the RemoteException; local EJB clients receive the EJBException.

The EJB’s transaction was rolled back.

The client’s transaction may marked for rollback, depending on the vendor.

The bean is not part of a transaction.

The EJB was invoked but doesn’t propagate the client’s transaction and doesn’t start its own transaction.

transaction-type =Container

transaction-attribute = Never | NotSupported | Supports |

Application exception

Rethrow the application exception.

Receives the application exception.

The client’s transaction is not affected.

System exception

Log the error.

Discard the instance.

Rethrow the RemoteException to remote clients or the EJBException to EJB local clients.

Remote clients receive the RemoteException; local EJB clients receive the EJBException.

The client’s transaction may or may not be marked for rollback, depending on the vendor.

Bean-managed transaction.

The stateful or stateless session EJB uses the EJBContext to explicitly manage its own transaction.

transaction-type = Bean

transaction-attribute = Bean-managed transaction EJBs do not use transaction attributes.

Application exception

Rethrow the application exception.

Receives the application exception.

The client’s transaction is not affected.

System exception

Roll back the transaction.

Log the error.

Discard the instance.

Rethrow the RemoteException to remote clients or the EJBException to EJB local clients.

Remote clients receive the RemoteException; local EJB clients receive the EJBException.

The client’s transaction is not affected.

Table 16-2 summarizes the interactions between different types of exceptions and transactions in message-driven beans.

Table 16-2. Exception summary for message-driven beans

Transaction scope

Transaction type attributes

Exception thrown

Container’s action

Container-initiated transaction.

The transaction started before the onMessage( ) method was invoked and will end when the method completes.

transaction-type =Container

transaction-attribute = Required

System exception

Roll back the transaction.

Log the error.

Discard the instance.

Container-initiated transaction.

No transaction was started.

transaction-type =Container

transaction-attribute = NotSupported

System exception

Log the error.

Discard the instance.

Bean-managed transaction.

The message-driven bean uses the EJBContext to explicitly manage its own transaction.

transaction-type = Bean

transaction-attribute = Bean-managed transaction EJBs do not use transaction attributes.

System exception

Roll back the transaction.

Log the error.

Discard the instance.



[51] Although the instance is always discarded with a RuntimeException, the impact on the remote reference may vary depending on the vendor.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.189.199