Suggested Pages

Wednesday, June 6, 2012

Spring: Required vs Requires_new (propagation attribute)

In this post we'll see the difference between REQUIRED and REQUIRES_NEW Spring: Required vs Requires_new.

REQUIRES_NEW

Suppose you have the following classes.

ContactDAO.java

@Repository
public class ContactDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;

 @Transactional(propagation = Propagation.REQUIRES_NEW)
 public void saveRequiresNew(Contact contact, int count) {
  System.out.println("saveRequiresNew--start");
  entityManager.persist(contact);
  if (count == 1) {
   throw new RuntimeException("RuntimeException");
  }
  System.out.println("saveRequiresNew--end");
 }


}

ContactService.java
....
@Service
public class ContactService {

 @Autowired
 private ContactDAO contactDAO;

 @Transactional(propagation = Propagation.REQUIRED)
 public void saveRequiresNew(Contact contactOuterTransaction,
   List contacts) {
  
  contactDAO.save(contactOuterTransaction);
  int i = 1;
  for (Contact contact : contacts) {
  
   try {
    contactDAO.saveRequiresNew(contact, i);
   } catch (RuntimeException e) {
    System.out.println(e.getMessage());
   }
   i++;
  }
 }
}

As you can see the method saveRequiresNew of ContactDAO has Propagation.REQUIRES_NEW as propagation attribute.
The outer transaction will be suspended and a new transaction starts for each call to this method. When the count variable gets the value 1, an exception is thrown. Because the exception is a runtime exception the transaction will be marked for rollback. The method saveRequiresNew of ContactService catches the exception ad prints the exception message. The exception doesn't reach the outer transaction boundary so it has no effect on the outer transaction completion. Each trasaction that has been opened inside saveRequiresNew of ContactDAO will be committed except the transaction that is marked for rollback, and when the outer transaction will be resumed, it will go to commit.

REQUIRED


 
  ContactDAO.java
 .....

@Repository
public class ContactDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;

 @Transactional(propagation = Propagation.REQUIRED)
 public void saveRequired(Contact contact, int count) {
  System.out.println("saveRequired--start");
  
  entityManager.persist(contact);
  if (count == 1) {
   throw new RuntimeException("RuntimeException");
  }
  System.out.println("saveRequired--end");
 }

}

ContactService.java
....
@Service
public class ContactService {

 @Autowired
 private ContactDAO contactDAO;

 @Transactional(propagation = Propagation.REQUIRED)
 public void saveRequired(Contact contactOuterTransaction,
   List contacts) {

  System.out.println(contactOuterTransaction);
  contactDAO.save(contactOuterTransaction);
  int i = 1;
  for (Contact contact : contacts) {
   System.out.println("contact:" + i);
   try {
    contactDAO.saveRequired(contact, i);
   } catch (RuntimeException e) {
    System.out.println(e.getMessage());
   }
   i++;
  }
 }
As you can see the method saveRequired of ContactDAO has Propagation.REQUIRED as propagation attribute. So the outer transaction is used in this method to perform operations with the Entity Manager.  When the count variable gets  the value 1, an exception is thrown. Because the exception is a runtime exception the transaction will go to rollback. The transaction used in the this method is the same of the outer method, so no data will be persisted. Indipendently if the outer method catches the exception, the transaction is already marked for rollback.

No comments :

Post a Comment

Suggested Pages