Mantis - Resin
Viewing Issue Advanced Details
904 minor always 01-01-06 08:26 03-27-06 14:18
ferg  
ferg  
normal  
closed 3.0.17  
fixed  
none    
none 3.0.19  
0000904: CMP updates not visible in selects
(rep by Steven Grimm)

We have a session bean that calls an entity bean to perform some
updates, then does a JDBC call that joins with the entity bean's table.
Something like

    fooBean.setName("Joe");
    stmt = connection.prepareStatement("select f.name from foo f, bar b
where f.id = b.foo_id");

What seems to be happening is that the "foo" table is not getting
updated by the call to setName(). Most likely the container is just
deferring the update until the end of the transaction for performance
reasons. At least, that's what WebLogic does. They provide a "defer
updates until end of transaction" option that can be set to false in
cases like the above.

What, if anything, is the equivalent in Resin? How do I get updates to
entity beans to show up in JDBC queries within the same transaction?

I thought maybe the "distributed" option to <ejb-server> would help, as
documented on http://www.caucho.com/resin-3.0/cmp/ejb-server.xtp [^] -- but
when I try to include <distributed> in my resin.conf's <ejb-server>, I
get an XML validation error that claims there's no such thing as a
<distributed> tag! What's the story with that?


Notes
(0000895)
ferg   
02-23-06 10:39   
Since the problem of CMP updates not showing up in JDBC queries in the
same transaction is our last real stumbling block to deploying Resin,
I've been digging a little deeper into it. The previously offered advice
of calling EntityManager.flush() didn't work, but it seemed like it
should have, so that's where I've been focusing.

The problem seems to be that when I call

  EntityManager mgr = (EntityManager)new
InitialContext().lookup("java:comp/EntityManager");
  mgr.flush();

the flush() call is getting a different AmberConnectionImpl than the CMP
code is. Specifically, EntityManagerImpl.getAmberConnection() calls
AmberManager.createAmberConnection(). That creates a new
AmberConnectionImpl(), which of course doesn't have any of the pending
changes from earlier in the transaction.

In other words, the flush() is flushing the wrong cache of updates to
the CMP entities.

I *think* that EntityManagerImpl.getAmberConnection() should first be
trying to get the AmberConnectionImpl associated with the currently open
transaction, if any.

Does that seem right? I will start trying to figure out how to do that.
(0000896)
koreth   
02-23-06 18:03   
Patch for this problem, more robust than what I sent to the mailing list (but still needs improvement for actual release since it hardwires a JNDI name):

--- modules/resin/src/com/caucho/amber/ejb3/EntityManagerImpl.java- 2006-02-
23 11:30:07.808570253 -0800
+++ modules/resin/src/com/caucho/amber/ejb3/EntityManagerImpl.java 2006-02-
23 17:52:12.444163560 -0800
@@ -41,10 +41,15 @@
 import com.caucho.amber.query.AbstractQuery;

 import com.caucho.ejb.EJBExceptionWrapper;
+import com.caucho.ejb.EjbServerManager;
+import com.caucho.ejb.xa.EjbTransactionManager;
+import com.caucho.ejb.xa.TransactionContext;

 import com.caucho.jca.UserTransactionProxy;
 import com.caucho.jca.CloseResource;

+import com.caucho.naming.*;
+
 import com.caucho.util.L10N;

 /**
@@ -57,6 +62,8 @@

   private AmberManager _amberManager;

+ private EjbTransactionManager _transactionManager;
+
   private boolean _isRegistered;
   private AmberConnectionImpl _aConn;

@@ -67,6 +74,15 @@
   {
     _amberManager = amberManager;
     _entityManagerProxy = proxy;
+
+ // Look up the transaction manager so we can get transactional Amber
+ // connections.
+ EjbServerManager serverManager = (EjbServerManager)
+ Jndi.lookup("java:comp/env/cmp/resin-ejb-server");
+ if (serverManager != null)
+ _transactionManager = serverManager.getTransactionManager();
+ else
+ _transactionManager = null;
   }

   /**
@@ -235,6 +251,12 @@
    */
   private AmberConnectionImpl getAmberConnection()
   {
+ if (_transactionManager != null) {
+ TransactionContext context = _transactionManager.getTransactionContext();
+ if (context != null)
+ return context.getAmberConnection();
+ }
+
     if (_aConn == null) {
       /*
       if (_depth == 0)
(0000923)
koreth   
03-08-06 16:44   
I should add that my patch is to fix the problem of the explicit EntityManager.flush() not working. My patch does *not* fix the underlying bug (CMP updates are invisible to subsequent JDBC queries in the same transaction).
(0000951)
ferg   
03-27-06 14:18   
ejb/0al5

With 3.0.19, the CMP context is associated with the Amber/persistence context/EntityManager at java:comp/env/persistence/PersistenceContext/resin-ejb.

You can use that EntityManager to flush the current dirty entities.