1

I'm developing a Java/Seam/Hibernate/Glassfish application with two threads:

  • Thread #1 sends various messages and writes summary information to a MySQL database.
  • Thread #2 polls the database periodically (invoked by a ScheduledExecutorService) and acts on the current "state" of each message.

Have come across an integration test problem: It doesn't seem to matter how long Thread #2 waits for a new row to be added by Thread #1, it just isn't added during the test so the expected call isn't made. Then sure enough, after the test has failed a new row pops up - but too late. Not sure if this might be a design problem - Thread #2 currently gets a Seam context using Lifecycle.beginCall()...Lifecycle.endCall(). So my understanding (which may be wrong) is possibly the problems are due to there being two separate Hibernate sessions for the two threads - so the one reading doesn't know about the latest information from the one writing?

There may be different ways of fixing this but my current thinking is couldn't I just force Hibernate to actually add a record to the table immediately when I call save() / flush() or even manually commit a transaction? No luck with any of these - makes me wonder if there is some kind of managed transaction being used behind the scenes. Grateful for any advice...

For info, here's the gist of the code that adds a record:

// Obtain Hibernate session
Session session = (Session) Component.getInstance("hibernateSession");

// Create request
Request newRequest = new Request();
// newRequest.set<blah>();

// Save the new request to the database
session.save(newRequest);

// Have tried session.flush(), transaction.commit() etc. here.
// Nothing seems to put the record into the database straight away.

Not sure if this is relevant but here is the Hibernate configuration:

<property name="transaction.flush_before_completion">true</property>
<property name="connection.release_mode">after_statement</property>
<property name="transaction.manager_lookup_class">org.hibernate.transaction.SunONETransactionManagerLookup</property>
<property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="current_session_context_class">jta</property>

(As this is an existing application owned by the customer I don't have the right to change the Hibernate config.)

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208

2 Answers2

1

Your guess is good.

You are using a JTATransactionFactory, so the transaction is demarcated by JTA (i.e by the container).

The method you are using to save the Request (here I presume it is defined in an EJB ) needs to be annotated with a transactional annotation: @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW), so when the method ends, the transaction gets committed.

Carlo Pellegrini
  • 5,656
  • 40
  • 45
0

Many thanks to @Carlo Pellegrini, whose answer pointed me in the right direction. I've since come across this answer and tried the following code after the save() operation:

// Commit Seam-managed transaction (if there is one)
UserTransaction userTransaction = (UserTransaction) Component.getInstance("org.jboss.seam.transaction.transaction");
if (userTransaction.isActive()) {
    userTransaction.commit();
}

Well it does the job nicely but I don't like it - seems a bit hacky! Is there a better way?

Community
  • 1
  • 1
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208