Java – Transaction rollback in stateless session EJB 3.0

ejb-3.0javarollbacktransactions

I have a stateless session EJB as per 3.0 spec.

/*Remote Interface*/

package com.nseit.ncfm2.data.ejb;
import java.sql.SQLException;
import java.util.Collection;

import javax.ejb.Remote;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.naming.NamingException;

import com.nseit.ncfm2.security.Audit;

@Remote
public interface ProductionDataChangesRequestsRemote {

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public boolean shiftCandidateDetails(String sourceNcfmId,
            String destinationNcfmId, Collection<String> specialCasesList, String shiftingRemarks, String user, Audit updtAudit) throws NamingException, SQLException;
}


/*Bean Class*/

package com.nseit.ncfm2.data.ejb;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.naming.NamingException;

import com.nseit.ncfm2.security.Audit;
import com.nseit.ncfm2.util.server.lookup.LookUpServerResources;
import java.sql.*;
import java.util.*;

/**
 * Session Bean implementation class ProductionDataChangesRequestsBean
 */
@Stateless(name = "ProductionDataChangesRequestsBean", mappedName = "ProductionDataChangesRequestsEJB")
@Remote(ProductionDataChangesRequestsRemote.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ProductionDataChangesRequestsBean implements
        ProductionDataChangesRequestsRemote {

/**
 * Default constructor.
 */
public ProductionDataChangesRequestsBean() {
    // TODO Auto-generated constructor stub
}

@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public boolean shiftCandidateDetails(String sourceNcfmId,
        String destinationNcfmId, Collection<String> specialCasesList,
        String shiftingRemarks, String user, Audit updtAudit)
        throws NamingException, SQLException {
    // TODO Auto-generated method stub
    Connection conn = null;
    PreparedStatement pstmt = null;

    int updtCnt = 0;

    boolean areDetailsShifted = false;

    try {
        ..............
        ..............
        ..............

        /* Start: update table-1 */
        ..............
        ..............
        ..............

        updtCnt = pstmt.executeUpdate();
        ..............
        ..............
        ..............

        /* End: update table-1 */


        /* Start: update table-2 */
        ..............
        ..............
        ..............

        updtCnt = pstmt.executeUpdate();
        ..............
        ..............
        ..............

        /* End: update table-2 */

        areDetailsShifted = true;

    } /*catch (SQLException e) {
        // TODO Auto-generated catch block
        System.out
                .println("SQLException in ProductionDataChangesRequestsBean.shiftCandidateDetails(...) "
                        + e.getMessage());
        // e.printStackTrace();

        context.setRollbackOnly();

    } */finally {
        LookUpServerResources.closeStatement(pstmt);
        LookUpServerResources.closeConnection(conn);
    }

    return areDetailsShifted;
}

}

Currently, if the 1st table update succeeds and the 2nd table update gives an exception, a rollback is not taking place, i.e records in 1st table are updated.

I want the transaction to be rolled back in case an SQLException occurs (or for that matter, if any runtime exception occurs).

I tried two approaches :

  1. Use of context.setRollbackOnly() in catch block for SQLException
  2. Throwing the SQLException

In both the cases, the transaction didn't roll back.

How can I achieve this:

  1. Without the usage of @ApplicationException annotation (as I do not have any application exceptions)
  2. Without catching the SQLException and then calling context.setRollbackOnly()

Or what is the standard way?

Best Answer

You will have to throw RuntimeException

Related Topic