title: Transaction rollback in stateless session EJB 3.0
body: <p>I have a stateless session EJB as per 3.0 spec.</p>
  
  <pre><code>/*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&lt;String&gt; 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&lt;String&gt; 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;
  }
  
  }
  </code></pre>
  
  <p>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.</p>
  
  <p>I want the transaction to be rolled back in case an SQLException occurs (or for that matter, if any runtime exception occurs).</p>
  
  <p>I tried two approaches :</p>
  
  <ol>
  <li>Use of <code>context.setRollbackOnly()</code> in catch block for SQLException</li>
  <li>Throwing the SQLException</li>
  </ol>
  
  <p>In both the cases, the transaction didn't roll back.</p>
  
  <p>How can I achieve this:</p>
  
  <ol>
  <li>Without the usage of @ApplicationException annotation (as I do not have any application exceptions)</li>
  <li>Without catching the SQLException and then calling <code>context.setRollbackOnly()</code></li>
  </ol>
  
  <p>Or what is the standard way?</p>