Home » Java » Enterprise Java » Pre Java EE 7 alternative to JPA 2.1 unsynchronized persistence context

About Abhishek Gupta

Pre Java EE 7 alternative to JPA 2.1 unsynchronized persistence context

Unsynchronized persistence context in Java EE 7

JPA 2.1 introduced the concept of unsynchronized persistence context which allows fine grained control over flushing of the JPA Entity Manager i.e. by explicitly calling EntityManager#joinTransaction. Previously, this was defaulted to end of JTA transaction e.g. in a typical Stateless EJB, the entity manager would flush its state to the DB at the end of a method (which starts and ends a transaction by default). You can read more about this, here and here.

Possible in the pre Java EE 7 era as well (both EE 5 and EE 6)

Java EE 5 and 6 have can be tweaked to achieve the same result as attained by the Unsynchronized Persistence Context in Java EE 7

Imagine a use case where customer details are being edited in a sequential manner (using a wizard like flow) e.g. address info in screen 1, contact info in screen 2 etc. You would want to save the state of the each category as and when the customer enters is but do not wish to push the entire state to the DB until the process is complete i.e. info for all the categories is entered by the user

package com.abhirockzz.conversationalee;

import com.abhirockzz.conversationalee.entity.Customer;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

@Stateful
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class CustomerEditorFacade{
 
  @PersistenceContext(type = PersistenceContextType.EXTENDED)
  EntityManager em;
  
  @Inject //this won't work in Java EE 5
  Principal authenticatedUser;
  
  private Customer customer;
  
  @PostConstruct
  public void init(){
      System.out.println("CustomerEditorFacade created at " + new Date().toString());   
  }
  
  @PreDestroy
  public void destroy(){
      System.out.println("CustomerEditorFacade destroyed at " + new Date().toString());   
  }
  
  //step 1
  public void updateCity(String custID, String city){
    String custID = authenticatedUser.getName(); //assume we have an authenticated principal which is the same as the customer ID in the Database
    Customer customerFromDB = em.find(Customer.class, Integer.valueOf(custID)); //obtain a 'managed' entity
    customerFromDB.setCity(city); //no need to call em.persist
    customer = customerFromDB; //just switch references
    
    //Customer state will NOT be pushed to DB
  }

  //step 2
  public void updateEmail(String email){
    customer.setEmail(email); //not pushed to DB yet
  }
  
  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  public void save(){
    //dummy method to trigger transaction and flush EM state to DB
  }
  
  @Remove
  public void finish(){
    //optional method to provide a way to evict this bean once used
    //not required if this is session scoped
  }

}

The code comments are self explanatory (hopefully)

Cheers!

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

 

and many more ....

 

Receive Java & Developer job alerts in your Area

I have read and agree to the terms & conditions

 

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments