У меня EJB сеанса без сохранения состояния согласно спецификации 3.0.
/*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;
}
}
В настоящее время, если 1-е обновление таблицы завершается успешно, а 2-е обновление таблицы дает исключение, откат не выполняется, т.е. обновляются записи в 1-й таблице.
Я хочу, чтобы транзакция откатывалась в случае возникновения исключения SQLException (или, если на то пошло, в случае возникновения какого-либо исключения во время выполнения).
Я попробовал два подхода:
- Использование
context.setRollbackOnly()
в блоке catch для SQLException
- Бросив SQLException
В обоих случаях транзакция не откатилась.
Как мне этого добиться:
- Без использования аннотации @ApplicationException (поскольку у меня нет исключений для приложений)
- Не перехватывая исключение SQLE, а затем вызывая
context.setRollbackOnly()
или какой стандартный способ?