Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Pre-Java EE 7 Alternative to JPA 2.1 Unsynchronized Persistence Context

DZone's Guide to

Pre-Java EE 7 Alternative to JPA 2.1 Unsynchronized Persistence Context

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

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

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 defaulted to the end of a JTA transaction e.g. in a typical Stateless EJB, as 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 can be tweaked to achieve the same result 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 each category when the customer enters it but you do not want to push the entire state to the DB until the process is complete (info for all the categories is entered by the user).

The code comments are self explanatory (hopefully).

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
  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
  }

}


Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
java ee 7 ,jpa

Published at DZone with permission of Abhishek Gupta, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}