Reputation: 3590
I am processing three transaction inside a single method in stateless container managed bean .i want to persist three transaction while if one throws exception other two should complete their respective transaction ,error is that if first or any one is throwing exception other two are to executing please give some helpful suggestion
public void allocateSubjectToStudent(SubjectAllocatedToStudentDto dto)throws Exception {
logger.info("allocateSubjectToStudent method entry :");
List<Subject> coreList=dto.getCoreList();
Iterator<Subject> iterator=coreList.iterator();
while(iterator.hasNext()){
logger.info("inside while :");
SubjectAllocatedToStudentBo bo=new SubjectAllocatedToStudentBo();
bo.setBacthId(dto.getBacthId());
bo.setSemester(dto.getSemester());
bo.setStudentId(dto.getStudentId());
Subject subject=iterator.next();
bo.setSubjectName(subject.getSubjectName());
bo.setSubjectType(subject.getAbbreviation());
try{
manager.persist(bo);
}
catch(javax.persistence.PersistenceException e){
Throwable t = e.getCause();
while ((t != null) && !(t instanceof org.hibernate.exception.ConstraintViolationException)) {
t = t.getCause();
}//while
if (t instanceof org.hibernate.exception.ConstraintViolationException) {
throw new Exception("Core subject already allocated to student");
} //end of if
}//end of catch
}//end of while
List<Subject> departmentallist=dto.getDepartmentList();
Iterator<Subject> iterator1=departmentallist.iterator();
while(iterator1.hasNext()){
logger.info("inside while :");
SubjectAllocatedToStudentBo bo=new SubjectAllocatedToStudentBo();
bo.setBacthId(dto.getBacthId());
bo.setSemester(dto.getSemester());
bo.setStudentId(dto.getStudentId());
Subject subject=iterator1.next();
bo.setSubjectName(subject.getSubjectName());
bo.setSubjectType(subject.getAbbreviation());
try{
manager.persist(bo);
}
catch(javax.persistence.PersistenceException e){
Throwable t = e.getCause();
while ((t != null) && !(t instanceof org.hibernate.exception.ConstraintViolationException)) {
t = t.getCause();
}//while
if (t instanceof org.hibernate.exception.ConstraintViolationException) {
throw new Exception("InterDepartmental subject already allocated to student");
} //end of if
}//end of catch
}//end of while
List<Subject> electiveList=dto.getElectiveList();
Iterator<Subject> iterator2=electiveList.iterator();
while(iterator2.hasNext()){
logger.info("inside while :");
SubjectAllocatedToStudentBo bo=new SubjectAllocatedToStudentBo();
bo.setBacthId(dto.getBacthId());
bo.setSemester(dto.getSemester());
bo.setStudentId(dto.getStudentId());
Subject subject=iterator2.next();
bo.setSubjectName(subject.getSubjectName());
bo.setSubjectType(subject.getAbbreviation());
try{
manager.persist(bo);
}
catch(javax.persistence.PersistenceException e){
Throwable t = e.getCause();
while ((t != null) && !(t instanceof org.hibernate.exception.ConstraintViolationException)) {
t = t.getCause();
}//while
if (t instanceof org.hibernate.exception.ConstraintViolationException) {
throw new Exception("Elective subject already allocated to student");
} //end of if
}//end of catch
}//end of while
logger.info("allocateSubjectToStudent method exit :");
} //end of method
Upvotes: 0
Views: 137
Reputation: 3533
Within a single method invocation there is only a single transaction active. To achieve what you want, you must perform the three operations in different transactions. This would require one more level of abstracttion.
public class MyFreshTransaction {
@TransactionAttribute(REQUIRES_NEW)
public void updateO() {
//do something
}
@TransactionAttribute(REQUIRES_NEW)
public void update1() {
//do something
}
@TransactionAttribute(REQUIRES_NEW)
public void update2() {
//do something
}
}
@Stateless
public class MyTransactionProcessor {
@EJB
private MyFreshTransaction freshTransaction;
public void processTransaction() {
try {
//The current transaction context will be suspended, and a new one invoked
//if the new one fails and is rollback, the current one is not affected.
//you can then handle the exception, by rethrowing the exception,in which case
//the current transaction will also be rolled back, or continue based on your logic.
freshTransaction.update0();
} catch (Exception ex ) {//handle}
try {
//The current transaction context will be suspended, and a new one invoked
//if the new one fails and is rollback, the current one is not affected.
//you can then handle the exception, by rethrowing the exception,in which case
//the current transaction will also be rolled back, or continue based on your logic.
freshTransaction.update1();
} catch (Exception ex ) {//handle}
try {
//The current transaction context will be suspended, and a new one invoked
//if the new one fails and is rollback, the current one is not affected.
//you can then handle the exception, by rethrowing the exception,in which case
//the current transaction will also be rolled back, or continue based on your logic.
freshTransaction.update2();
} catch (Exception ex ) {//handle}
}
}
Note that if any of the update transaction was successful, and the the parent transaction is rolled back, it will not affect the status of the 'child' transactions, as they had already been committed and their effects (if DB effects) will be committed too.
Read on Java EE Transactions Java EE Transactions
Upvotes: 1
Reputation: 679
create three different method all with TranscationAttributeType REQUIRES_NEW Please find below code snippet for EJB3 Bean
public void doYourWork()
{
a();
b();
c();
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void a()
{
try
{
//Do the first transaction here
}catch(Exception e)
{
}
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void b()
{
try
{
//Do the second transaction here
}catch(Exception e)
{
}
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void c()
{
try
{
//Do the third transaction here
}catch(Exception e)
{
}
}
Upvotes: 1