Glassfish v2ur2: Potential Data Corruption in Mixed JPA / DAO Usage - and The Solution

During Glassfish v2ur2 EJB 3 tests together with JPA persistence I enountered the following problem: Direct changes to the database (SQL updates) performed using an injected DataSource in the same Bean-method, and so transaction, were not visible for the operations performed on the EntityManager (subsequent find). Only the old (cached)  entity was visible, without the changes performed in the DB.

Both EntityManager and DataSource were injected, whereas the EntityManager was configured in persistence.xml to use the same DataSource.

@Stateless
@Remote(VehicleManager.class)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class VehicleManagerBean implements VehicleManager {

    @PersistenceContext
    private EntityManager entityManager;
    @Resource(mappedName="jdbc/db")
    private DataSource dataSource;
 }

Both resources; the EntityManager and DataSource participate in a transaction, so direct changes to the database should be visible to the EntityManager as well.

Nevertheless in the method below, the last find-method didn't reflected the changes made in the DB:

public Vehicle findChangeDBClearFind(int id, String newColor) {
        Vehicle vehicle = this.find(id);
        try {
         //changes the color of the vehicle directly in the DB
            this.changeVehiclesColor(id, newColor);
        } catch (Exception e) {
            throw new EJBException("Problem executing statement" + e, e);
        }
        this.entityManager.clear();

                    return this.find(id);
    }

 private void changeVehiclesColor(int id, String color) throws Exception {
        Connection connection = this.dataSource.getConnection();
        Statement statement = connection.createStatement();
        String sqlStatement = "update vehicle set color=\'" + color + "\' where id=" + id;
        int updatedRecords = statement.executeUpdate(sqlStatement);
        if (updatedRecords != 1) {
            throw new IllegalStateException("Vehicle with id: " + id + " cannot be updated!");
        }
        connection.close();
        statement.close();
    }

I assumed first, that the problem was the DataSource configuration. It turned out, however, that in the default configuration, TopLink essentials will not join the existing transaction. This can be achieved with the following setting in the persistence.xml:

        <property name="toplink.transaction.join-existing" value="true"/>

The property above is only available for TopLink Essentials 2.1 and so only for Glassfish v2.1+,v3 and not for Glassfish v2ur2. However I replaced the installed toplink-essentials.jar and toplink-essentials-agent.jar in the [GLASSFISH_HOME]\lib (existing Glassfish v2ur2 installation), and it worked as well. It is actually an already known bug. Btw. I tested Glassfish v2ur2 during the last weeks intensively, and this was the one and only  major issue. Beyond that I enountered only problems merging entities with @Version fields with the "big" types like Long, Integer etc. which is uncommon in real life project. I filed this bug as well. Thanks to Gordon Yorke for providing the property and the hints.


Cloudy Jakarta EE and MicroProfile: Microservices, Clouds and Beyond Jakarta EE / MicroProfile airhacks workshops at MUC airport, Winter Edition

airhacks.fm the podcast:

Stay in touch: airhacks.news.

Comments:

Not really the only major bug. There is an other one regarding mail session handling.
If you try Liferay on Glassfish v2 you can not use some mail features due to this bug... Different calls to the same mail session are leading to different response from Glassfish.
This bug is also an known bug and should be solve in upcoming release and v3.

Posted by Stephane on July 28, 2008 at 01:39 PM CEST #

Thanks for this information. This is the only web page I have been able to find with information about how to mix JPA and JDBC. I am using glassfish v2ur2, and am experiencing something along the lines of this example: Data manipulated through JPA are not necessarily visible in the database using DataSource directly. I think I am going to try your tip, or maybe see if Hibernate works better.

Posted by Jacob Lorensen on February 03, 2009 at 06:05 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
Online Workshops
realworldpatterns.com
...the last 150 posts
...the last 10 comments
License