I just spent some time investigating a customer testcase where they were wondering why the following sequence of steps was not working properly:
- Get an AppModule instance from the pool
- Create a new row in some view object
- Call appModule.getTransaction().postChanges()
- Release the AppModule to the Pool in "Managed State" mode (known as the Stateful mode)
- Reaquire an AppModule instance from the pool
- Try to find the newly added row
These steps will work fine if your configuration is not set to use database-level connection pooling. We generally recommend only using Application Module level pooling since there are performance benefits to be gained by allowing the instances of the application modules in the pool to hang onto their JDBC connection object (until, of course, that AM instance in the pool is cleaned up). JDBC prepared statements that we've created can be reused again by the framework if the JDBC connection against which they were initially created is still valid. If you ask us to "unplug" the JDBC connection from the application module each time we check an AM instance back into the pool -- which is what turning on database connection pooling is doing -- then we cannot assume that the next time around we will get the same database connection object from the database connection pool, so we rollback that connection when it's released to the pool so that no database pending state is left "hanging" there. Also, when a postChanges() operation is successful, pending changes are no longer considered pending anymore (since they've been communicated to the database) so the BC4J pending state management facility will no longer consider those entities as things that need tracking.
If you do turn on database connection pooling in your configuration, then...
- After step 3 above, the pending entities are removed from the list that the pending state management facility will bother storing pending information about.
- At step 4, upon releasing the AM to the pool, we turn around and release the database connection to the pool and issue a rollback on it just before doing that
- At step 5 you reacquire an AM instance, but since the newly added entities were successfully posted to the database prior to releasing in "Managed State" mode, they will not be in the state snapshot that we manage. Since we issued a rollback on the database connection, those pending inserts won't be there anymore in whatever database connection your new AM instance gets from the database connection pool
- At step 6, an attempt to find the newly added row (but never committed, just posted before releasing the AM) will not find it
The solution is to either not use database connection pooling (since our pooling of AppModules effectively accomplishes a nice pooling for you), or else don't try to combine that feature with postChanges().
One situation when database connection pooling may be worthwhile is when you have many application module pools, all using the same underlying database connection. In that case, the savings of database connections in use may be worth the tradeoff of losing the efficiency of reusing existing prepared statements.
6:18:04 PM
|
|