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!

About Abhishek

Loves Go, NoSQL DBs and messaging systems
This entry was posted in Java, Java EE and tagged , , , . Bookmark the permalink.

8 Responses to Pre Java EE 7 alternative to JPA 2.1 unsynchronized persistence context

  1. Pingback: Pre Java EE 7 alternative to JPA 2.1 unsynchronized persistence context | Dinesh Ram Kali.

  2. Basically a good idea. Nevertheless a weak approach, if you ask me. I would always prefer an request scoped CDI managed persistence context (EntityManager) and use an interceptor to ensure that the entity manager joins a newly created transaction even if the EM was queried prior toTX start.

    Overall a few lines of code with @Produces / @Disposes and an Interceptor. For German-only version see here: https://blog.openknowledge.de/2014/08/eager-synchronized-entitymanager-mit-transactional/ (We have to publish the english version too).

    Like

  3. It does;). We even use it in non EE environments a lot (pure tomcat, for instance, or standalone apps). Just use Apache OWB or similar and deltaspike for TX management (or your own transactional interceptor). Of course this will be more initial work than in your example. However it does not introduce a conceptional bad battern. Your idea will pretty much ensure that your TX management will be broken at some point – and its hard to catch with tests. We invented Requires_New pretty much without JPA in our mind.

    Your idea works, technically. But it is really dangerous.

    Like

    • Abhishek says:

      Exactly ! I said it will not work in a pure Java EE environment. The presented solution (with all its flaws) is portable. I do not generally tend to discuss non-portable solutions/approaches in my blog posts. As far as customisation (usage of Apache OWB, delatspike etc.) is concerned, one can go to any length and even achieve this with this in a Java SE environment (with equivalent implementations of CDI, JPA, JTA, Embedded EJB etc.) – but that was not the point of this post 🙂

      Anyway, there are often multiple ways to solve a problem and this is definitely one of them. Appreciate your inputs !

      Like

      • Abhishek – don’t get me wrong. I always prefer portable solutions.

        But:
        – EE 5 is now 10 years old. Let’s kill the beast. We gained a lot with EE 5. Nevertheless it introduced several major flaws too. JTA-bound EntityManagers as default is one of them. The overuse of the java.ejb namespace is another. Let’s move on to EE 6 at least. An almost 7 year old technology stack. (Do you hear the spring folks laughing? 😉
        – Your solutions is pretty much the J2EE answer to something that is just wrong. In 2015 we should avoid pattern that require a change in the programming model (an empty save method) to overcome a technical flaw. If you need to work around a technical flaw / conceptual problem it is just not the right technology / framework.
        – There is almost no reason to not to develop EE 7 style today, even in a EE 5 environment (avoid infrastructure pattern at all, use @Inject EntityManager and @Transactional, avoid EJBs unless you make use of their nowadays pretty much limited benefits). As of today I can write code that does not require fundamental changes once I move on to an EE 6 or EE 7 environment, no matter where I start (SE, Web context (Tomcat etc.) or an old J2EE / EE server). This of course does not apply to people who have to use an ancient IBM Websphere version. Sorry guys;(.
        – Your solution is not as portable as you might think. Just to name one: EntityManager serialization is a complex topic that is not portable at all (you inherit that issue with SFSBs).

        Sorry if I am sounding rude. Your post gained some attention, and because of it’s consequences I had to write an answer. We still have a long way to go to overcome the J2EE programming model, which focused on infrastructure and technology instead of business. I am part of the problem, because I have sold that stuff for almost 10 years . But we are in 2015 now. Could we just start and ban the word “facade” ;).

        Like

  4. Abhishek says:

    Jens, there is no reason to ‘get you wrong’ 🙂 Don’t worry about it. After all, this is just a technical discussion (one from which I am learning something!)

    Just to answer your specific points

    • “EE 5 is now 10 years old. Let’s kill the beast” & “There is almost no reason to not to develop EE 7 style today”

    I could not agree more! I am guessing that you might have misunderstood the reason behind this post. It is not meant to encourage Java EE 5 programming in the age of Java EE 7 – it was meant to be a (possible) workaround for folks who have no choice but to stick to a Java EE 5 env like Weblogic 11g or Websphere 6.x stack (while still maintaining portability)

    • “There is almost no reason to not to develop EE 7 style today”

    Again. I am with you on this. This blog is a testimony to my love for and belief in Java EE 7 🙂

    • “avoid EJBs ”

    I am not ‘completely’ with you on this one 🙂 I personally feel that Java EE platform is still undergoing lot of changes w.r.t EJB-CDI alignment and EJBs are still relevant today (even in Java EE 7)

    “Your solution is not as portable as you might think”

    To be honest, I have not encountered EntityManager serialization related issues yet, but that definitely does not mean they do not exist. When I state ‘portability’, I look at it from a specification perspective (in this case the EJB specification)

    • “Sorry if I am sounding rude.”

    No worries at all 🙂 It is just a technical discussion. After all, interacting with someone who is much more accomplished and technically experienced is a way to improve. That’s precisely why I appreciate the time you have taken out to respond and comment

    Cheers!

    Like

    • OK – fine with me.

      Just to be clear – I wrote “avoid EJBs unless you make use of their nowadays pretty much limited benefits” ;). There are some rare benefits, nevertheless EJB TX management is the major drawback. I always recommend to check the average EJB application regarding TX handling for read-only business code. How oft did you encounter disabled transactions for read-only methods? Especially in combination with JPA, which – as you know – just depends on JTA for DB synchronisation.

      Regarding EntityManager serialization: https://struberg.wordpress.com/2012/04/25/is-there-a-way-to-fix-the-jpa-entitymanager/. The blog post is 4 years old and still valid. We have code in production that uses serializable (CDI-)scopes and Hibernate. It does work with hibernate but fails silently if you do not meet the requirements. (Disclaimer: my Hibernate knowledge on that topic is 2 years old. At this point other JPA providers did not support EM serialization, as far I know).

      And btw: I asked for eager synchronized EntityManagers too (automatically join a TX once it’s started, even if the EM was created before). As of today I did not find people who support that. I believe eager synchronized EM are missing, especially because other EE resources (e.g. database connections) work that way.

      Like

Leave a comment