I can reproduce your problem. It's a really nasty concurrency
materialization problem when using global/shared caches and an object was materialized first time:
Say we have a class Account with reference to Buyer, Buyer has a reference to Address and Address has a reference to AddressType
(similar to your test case)
Account -1:1- Buyer -1:1- Address -1:1- AddressType
We set autoretrieve true.
Thread_1: PB lookup Account object. Object was not found in cache, PB start to materialize Account and push this to cache, then first reference was materialized and pushed to cache,...
Thread_2: PB lookup Account object. Object was found in cache and returned. But the found object is the same pushed by thread_1, thus PB returns a not full materialized Account object.
If a local cache was used, e.g. ObjectCachePerBrokerImpl this situation will not arise.
Solution is to set attribute 'refresh="true"' in all reference-descriptor. This force OJB to lookup each reference for an object whether or not it was found in cache.
regards, Armin
Sven Efftinge wrote:
I just changed ObjectCacheClass from DefaultImpl to EmptyImpl.
Without caching the test doesn't fail.
I think this happens because the threads don't have to share the objects in this case.
Sven
Sven Efftinge wrote:
Hi Armin,
I wrote a test for this, now.
Unfortunately I wrote it against my application, because I haven't installed the OJB test suite yet ;(
The test starts n threads. Each thread creates a PersistentBroker, retrieves 4 instances of an entity and then checks some references for each entity.
When I run the test for 1 thread the test passes.
When I run it for e.g. 30 threads the test fails(most of the time) because some references were null.
Mmh... the test fails to RC4, also.
I'm not sure if this is really the same problem because I don't get any errors from OJB directly. Only the null references.
Here is the test (I used GroboUtils from SF):
public void testConcurrentRead() throws Throwable { int numthreads = 30; TestRunnable[] tests = new TestRunnable[numthreads];
for (int i = 0; i < tests.length; i++) { tests[i] = new FetchPersistentObjects(); } MultiThreadedTestRunner testRunner = new MultiThreadedTestRunner(tests);
testRunner.runTestRunnables();
}
class FetchPersistentObjects extends TestRunnable {
/* (non-Javadoc)
* @see net.sourceforge.groboutils.junit.v1.TestRunnable#runTest()
*/
public void runTest() throws Throwable {
PersistenceBroker broker = null;
KontoIF konto = null;
try {
broker = PersistenceBrokerFactory.createPersistenceBroker(pbKey);
Criteria crit = new Criteria();
crit.addEqualTo(KONTO.NAME, "test");
QueryByCriteria query = new QueryByCriteria(Konto.class, crit);
// we have 4 kontos with name="test" in the database
List kontos = (List) broker.getCollectionByQuery(query);
for (Iterator iter = kontos.iterator(); iter.hasNext();) {
konto = (KontoIF) iter.next();
assertEquals("test", konto.getName());
assertNotNull("All kontos have a reference to an interessent", konto.getInteressent());
assertNotNull("All interessents have a reference to an adresse", konto.getInteressent().getAdresse());
assertNotNull("All adresses have a reference to an adresseart", konto.getInteressent().getAdresse().getAdresseart());
assertNotNull("All adressearts have a varname", konto.getInteressent().getAdresse().getAdresseart().getVarname());
}
} finally {
broker.close();
}
}
}
Armin Waibel wrote:
Hi Sven,
I don't know if your problem rely on a concurrency problem. Between rc4 and rc5 I changed handling of DB resources in RsIterator class.
Now OJB is very strict in closing used resources. All resources will be released when
- PB instance was closed
- PB commit call is done
- PB abort call is done
This helps to avoid abandoned Statement/ResultSet instances.
> org.apache.ojb.broker.PersistenceBrokerException: > org.apache.ojb.broker.accesslayer.RsIterator$ResourceClosedException: > Resources no longer reachable, RsIterator will be automatic cleaned up > on PB.close/.commitTransaction/.abortTransaction
The exception says that OJB has already closed the DB resources used by the Iterator, e.g. one of the three events described above occur.
Can you post the source code or some pseudo code where the exception arise?
regards, Armin
Sven Efftinge wrote:
Hi,
I just got some errors when using/retrieving the same persistentobjects in multiple threads (request cause it's a webapp).
I tried many different configurations for class-descriptor, reference-descriptor, ... but the problem was still there.
At the moment I only have proxy="dynamic" specified all other attributes are set to default.
I only have the problem with OJB RC5. RC4 works fine.
This is a sequence from the stacktraces:
Caused by: org.apache.ojb.broker.PersistenceBrokerException: org.apache.ojb.broker.PersistenceBrokerException: org.apache.ojb.broker.accesslayer.RsIterator$ResourceClosedException: Resources no longer reachable, RsIterator will be automatic cleaned up on PB.close/.commitTransaction/.abortTransaction
at org.apache.ojb.broker.accesslayer.IndirectionHandler.materializeSubject(Unknown Source)
at org.apache.ojb.broker.accesslayer.IndirectionHandler.getRealSubject(Unknown Source)
... 33 more
Caused by: org.apache.ojb.broker.PersistenceBrokerException: org.apache.ojb.broker.accesslayer.RsIterator$ResourceClosedException: Resources no longer reachable, RsIterator will be automatic cleaned up on PB.close/.commitTransaction/.abortTransaction
at org.apache.ojb.broker.core.QueryReferenceBroker.getCollectionByQuery(Unknown Source)
at org.apache.ojb.broker.core.QueryReferenceBroker.getCollectionByQuery(Unknown Source)
at org.apache.ojb.broker.core.PersistenceBrokerImpl.getCollectionByQuery(Unknown Source)
at org.apache.ojb.broker.accesslayer.BasePrefetcher.prefetchRelationship(Unknown Source)
at org.apache.ojb.broker.core.QueryReferenceBroker$PBPrefetchingListener.prefetch(Unknown Source)
at org.apache.ojb.broker.core.QueryReferenceBroker$PBMaterializationListener.beforeMaterialization(Unknown Source)
at org.apache.ojb.broker.accesslayer.IndirectionHandler.beforeMaterialization(Unknown Source)
... 35 more
Caused by: org.apache.ojb.broker.accesslayer.RsIterator$ResourceClosedException: Resources no longer reachable, RsIterator will be automatic cleaned up on PB.close/.commitTransaction/.abortTransaction
at org.apache.ojb.broker.accesslayer.RsIterator.getRsAndStmt(Unknown Source)
at org.apache.ojb.broker.accesslayer.RsIterator.hasNext(Unknown Source)
at org.apache.ojb.broker.core.QueryReferenceBroker.getCollectionByQuery(Unknown Source)
... 42 more
Does this has to do with the "prefetch and autoRetreive"-problem discussed on this list in november?
regards, Sven
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
