You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2003/12/13 18:50:40 UTC
cvs commit: db-ojb/src/test/org/apache/ojb/broker RsIteratorTest.java
arminw 2003/12/13 09:50:40
Modified: src/java/org/apache/ojb/broker/accesslayer RsIterator.java
ResultSetAndStatement.java
src/test/org/apache/ojb/broker RsIteratorTest.java
Log:
made RsIterator more strict in handling used StatementAndResultSet
resources. Now we close all resources when associate PB instance
closed/commit../abort... methods were called (add RsIterator as
PBStateListener)
change log level of finalze method calls of
RsIterator and StatementAndResultSet
Revision Changes Path
1.54 +261 -132 db-ojb/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java
Index: RsIterator.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- RsIterator.java 9 Dec 2003 17:19:59 -0000 1.53
+++ RsIterator.java 13 Dec 2003 17:50:40 -0000 1.54
@@ -51,11 +51,15 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Vector;
+import java.lang.ref.WeakReference;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.PBLifeCycleEvent;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.VirtualProxy;
+import org.apache.ojb.broker.PBStateListener;
+import org.apache.ojb.broker.PBStateEvent;
+import org.apache.ojb.broker.OJBRuntimeException;
import org.apache.ojb.broker.cache.ObjectCache;
import org.apache.ojb.broker.core.PersistenceBrokerImpl;
import org.apache.ojb.broker.metadata.ClassDescriptor;
@@ -73,10 +77,23 @@
* PersistenceBroker::getCollectionByQuery(...) method uses a RsIterator
* internally to build up a Collection of objects
*
+ * <p>
+ * NOTE: OJB is very strict in handling <tt>RsIterator</tt> instances. <tt>RsIterator</tt> is
+ * bound very closely to the used {@link org.apache.ojb.broker.PersistenceBroker} instance.
+ * Thus if you do a
+ * <br/> - {@link org.apache.ojb.broker.PersistenceBroker#close}
+ * <br/> - {@link org.apache.ojb.broker.PersistenceBroker#commitTransaction}
+ * <br/> - {@link org.apache.ojb.broker.PersistenceBroker#abortTransaction}
+ * <br/>
+ * call, the current <tt>RsIterator</tt> instance resources will be cleaned up automatic
+ * and invalidate current instance.
+ * </p>
+ *
+ * <p>
* NOTE: this code uses features that only JDBC 2.0 compliant Drivers support.
* It will NOT work with JDBC 1.0 Drivers (e.g. SUN's JdbcOdbcDriver) If you
* are forced to use such a driver, you can use code from the 0.1.30 release.
- *
+ * </p>
* @author <a href="mailto:thma@apache.org">Thomas Mahler <a>
* @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird <a>- added the
* support for extents mapped to single table - added the .size
@@ -96,66 +113,66 @@
private ObjectCache m_cache;
/**
- * reference to the PersistenceBroker
- */
+ * reference to the PersistenceBroker
+ */
private PersistenceBrokerImpl m_broker;
/**
- * the underlying resultset
- */
+ * the underlying resultset
+ */
private ResultSetAndStatement m_rsAndStmt;
/**
- * the underlying query object
- */
+ * the underlying query object
+ */
private RsQueryObject m_queryObject;
/**
- * the proxy class to be used or null
- */
+ * the proxy class to be used or null
+ */
private Class m_itemProxyClass;
/**
- * the top-level class of the item objects
- */
+ * the top-level class of the item objects
+ */
private Class m_itemTopLevelClass = null;
/**
- * this container holds the values of the current ro during materialisation
- */
+ * this container holds the values of the current ro during materialisation
+ */
private Map m_row = null;
/**
- * flag that indicates wether hasNext on m_rs has allready been called
- */
+ * flag that indicates wether hasNext on m_rs has allready been called
+ */
private boolean m_hasCalledCheck = false;
/**
- * prefetch relationship: inBatchedMode true prevents releasing of
- * DbResources IN_LIMIT defines the max number of values of sql (IN) , -1
- * for no limits
- */
+ * prefetch relationship: inBatchedMode true prevents releasing of
+ * DbResources IN_LIMIT defines the max number of values of sql (IN) , -1
+ * for no limits
+ */
private boolean m_inBatchedMode = false;
/**
- * return value of the previously called hasNext from m_rs
- */
+ * return value of the previously called hasNext from m_rs
+ */
private boolean hasNext = false;
private boolean advancedJDBCSupport = false;
private boolean JDBCSupportAssessed = false;
private int m_current_row = 0;
/**
- * Tracks whether or not the resources that are used by this class have been released.
- */
+ * Tracks whether or not the resources that are used by this class have been released.
+ */
private boolean resourcesAreReleased = false;
/**
- * RsIterator constructor.
- *
- * @param queryObject query object
- * @param broker the broker we should use.
- */
+ * RsIterator constructor.
+ *
+ * @param queryObject query object
+ * @param broker the broker we should use.
+ */
public RsIterator(RsQueryObject queryObject, final PersistenceBrokerImpl broker)
{
setCache(broker.serviceObjectCache());
@@ -198,6 +215,13 @@
releaseDbResources();
throw e;
}
+
+ /*
+ now RsIterator instance is created, we wrap this instance with a
+ PBStateListener to make sure that resources of this instance will be
+ released. Add this as temporary PBStateListener.
+ */
+ m_broker.addListener(new ResourceWrapper(this));
}
protected Class getTopLevelClass()
@@ -210,9 +234,9 @@
}
/**
- * returns true if there are still more rows in the underlying ResultSet.
- * Returns false if ResultSet is exhausted.
- */
+ * returns true if there are still more rows in the underlying ResultSet.
+ * Returns false if ResultSet is exhausted.
+ */
public synchronized boolean hasNext()
{
try
@@ -231,6 +255,10 @@
{
setHasNext(false);
releaseDbResources();
+ if(ex instanceof ResourceClosedException)
+ {
+ throw (ResourceClosedException)ex;
+ }
}
if (logger.isDebugEnabled())
logger.debug("hasNext() -> " + getHasNext());
@@ -239,9 +267,9 @@
}
/**
- * moves to the next row of the underlying ResultSet and returns the
- * corresponding Object materialized from this row.
- */
+ * moves to the next row of the underlying ResultSet and returns the
+ * corresponding Object materialized from this row.
+ */
public synchronized Object next() throws NoSuchElementException
{
try
@@ -271,23 +299,30 @@
catch (Exception ex)
{
releaseDbResources();
- ex.printStackTrace();
- logger.error(ex);
- throw new NoSuchElementException("Could not obtain next object: " + ex.getMessage());
+ // ex.printStackTrace();
+ if(ex instanceof ResourceClosedException)
+ {
+ throw (ResourceClosedException) ex;
+ }
+ else
+ {
+ logger.error("Error while iterate ResultSet for query " + m_queryObject, ex);
+ throw new NoSuchElementException("Could not obtain next object: " + ex.getMessage());
+ }
}
}
/**
- * removing is not supported
- */
+ * removing is not supported
+ */
public void remove()
{
throw new UnsupportedOperationException("removing not supported by RsIterator");
}
/**
- * read all objects of this iterator. objects will be placed in cache
- */
+ * read all objects of this iterator. objects will be placed in cache
+ */
private Collection getOwnerObjects()
{
Collection owners = new Vector();
@@ -299,9 +334,9 @@
}
/**
- * prefetch defined relationships requires JDBC level 2.0, does not work
- * with Arrays
- */
+ * prefetch defined relationships requires JDBC level 2.0, does not work
+ * with Arrays
+ */
private void prefetchRelationships(Query query)
{
List prefetchedRel;
@@ -331,7 +366,7 @@
{
relName = (String) prefetchedRel.get(i);
prefetchers[i] =
- RelationshipPrefetcherFactory.createRelationshipPrefetcher(getBroker(), getQueryObject().getClassDescriptor(), relName);
+ RelationshipPrefetcherFactory.createRelationshipPrefetcher(getBroker(), getQueryObject().getClassDescriptor(), relName);
prefetchers[i].prepareRelationshipSettings();
}
@@ -364,8 +399,8 @@
}
/**
- * returns an Identity object representing the current resultset row
- */
+ * returns an Identity object representing the current resultset row
+ */
protected Identity getIdentityFromResultSet() throws PersistenceBrokerException
{
// fill primary key values from Resultset
@@ -384,22 +419,22 @@
}
/**
- * returns a fully materialized Object from the current row of the
- * underlying resultset. Works as follows: - read Identity from the primary
- * key values of current row - check if Object is in cache - return cached
- * object or read it from current row and put it in cache
- */
+ * returns a fully materialized Object from the current row of the
+ * underlying resultset. Works as follows: - read Identity from the primary
+ * key values of current row - check if Object is in cache - return cached
+ * object or read it from current row and put it in cache
+ */
protected Object getObjectFromResultSet() throws PersistenceBrokerException
{
/**
- * MBAIRD if a proxy is to be used, return a proxy instance and dont
- * perfom a full materialization. NOTE: Potential problem here with
- * multi-mapped table. The itemProxyClass is for the m_cld
- * classdescriptor. The object you are materializing might not be of
- * that type, it could be a subclass. We should get the concrete class
- * type out of the resultset then check the proxy from that.
- * itemProxyClass should NOT be a member variable.
- */
+ * MBAIRD if a proxy is to be used, return a proxy instance and dont
+ * perfom a full materialization. NOTE: Potential problem here with
+ * multi-mapped table. The itemProxyClass is for the m_cld
+ * classdescriptor. The object you are materializing might not be of
+ * that type, it could be a subclass. We should get the concrete class
+ * type out of the resultset then check the proxy from that.
+ * itemProxyClass should NOT be a member variable.
+ */
if (getItemProxyClass() != null)
{
@@ -424,7 +459,7 @@
{
// 3. If Object is not in cache
// materialize Object with primitive attributes filled from
- // current row
+ // current row
result = getQueryObject().getClassDescriptor().getRowReader().readObjectFrom(getRow());
// result may still be null!
if (result != null)
@@ -442,12 +477,12 @@
*/
// LoadedObjectsRegistry.register(result);
/**
- * MBAIRD if you have multiple classes mapped to a
- * table, and you query on the base class you could get
- * back NON base class objects, so we shouldn't pass
- * m_cld, but rather the class descriptor for the
- * actual class.
- */
+ * MBAIRD if you have multiple classes mapped to a
+ * table, and you query on the base class you could get
+ * back NON base class objects, so we shouldn't pass
+ * m_cld, but rather the class descriptor for the
+ * actual class.
+ */
// fill reference and collection attributes
ClassDescriptor cld = getQueryObject().getClassDescriptor().getRepository().getDescriptorFor(result.getClass());
// don't force loading of reference
@@ -459,10 +494,10 @@
}
}
else // Object is in cache
- {
+ {
ClassDescriptor cld = getQueryObject().getClassDescriptor().getRepository().getDescriptorFor(result.getClass());
// if refresh is required, update the cache instance from the
- // db
+ // db
if (cld.isAlwaysRefresh())
{
getQueryObject().getClassDescriptor().getRowReader().refreshObject(result, getRow());
@@ -475,13 +510,13 @@
}
/**
- * Reads primary key information from current RS row and generates a
- *
- * corresponding Identity, and returns a proxy from the Identity.
- *
- * @throws PersistenceBrokerException
- * if there was an error creating the proxy class
- */
+ * Reads primary key information from current RS row and generates a
+ *
+ * corresponding Identity, and returns a proxy from the Identity.
+ *
+ * @throws PersistenceBrokerException
+ * if there was an error creating the proxy class
+ */
protected Object getProxyFromResultSet() throws PersistenceBrokerException
{
// 1. get Identity of current row:
@@ -492,12 +527,12 @@
}
/**
- * with a new batch of JDBC 3.0 drivers coming out we can't just check for
- * begins with 2, we need to check the actual version and see if it's
- * greater than or equal to 2
- *
- * @return
- */
+ * with a new batch of JDBC 3.0 drivers coming out we can't just check for
+ * begins with 2, we need to check the actual version and see if it's
+ * greater than or equal to 2
+ *
+ * @return
+ */
private boolean supportsAdvancedJDBCCursorControl()
{
if (!JDBCSupportAssessed)
@@ -510,10 +545,10 @@
}
/**
- * Answer the counted size
- *
- * @return int
- */
+ * Answer the counted size
+ *
+ * @return int
+ */
protected int countedSize() throws PersistenceBrokerException
{
Query countQuery = getBroker().serviceBrokerHelper().getCountQuery(getQueryObject().getQuery());
@@ -553,9 +588,9 @@
}
/**
- * @return the size of the iterator, aka the number of rows in this
- * iterator.
- */
+ * @return the size of the iterator, aka the number of rows in this
+ * iterator.
+ */
public int size() throws PersistenceBrokerException
{
int retval = 0; // default size is 0;
@@ -568,14 +603,14 @@
{
}
if (!supportsAdvancedJDBCCursorControl()
- || getBroker().serviceConnectionManager().getSupportedPlatform().useCountForResultsetSize()
- || forwardOnly)
+ || getBroker().serviceConnectionManager().getSupportedPlatform().useCountForResultsetSize()
+ || forwardOnly)
{
/**
- * MBAIRD: doesn't support the .last .getRow method, use the
- * .getCount on the persistenceBroker which executes a count(*)
- * query.
- */
+ * MBAIRD: doesn't support the .last .getRow method, use the
+ * .getCount on the persistenceBroker which executes a count(*)
+ * query.
+ */
if (logger.isDebugEnabled())
logger.debug("Executing count(*) to get size()");
retval = countedSize();
@@ -583,11 +618,11 @@
else
{
/**
- * Use the .last .getRow method of finding size. The reason for
- * supplying an alternative method is effeciency, some driver/db
- * combos are a lot more efficient at just moving the cursor and
- * returning the row in a real (not -1) number.
- */
+ * Use the .last .getRow method of finding size. The reason for
+ * supplying an alternative method is effeciency, some driver/db
+ * combos are a lot more efficient at just moving the cursor and
+ * returning the row in a real (not -1) number.
+ */
int whereIAm = 1; // first
try
{
@@ -630,14 +665,14 @@
}
/**
- * Moves the cursor to the given row number in the iterator. If the row
- * number is positive, the cursor moves to the given row number with
- * respect to the beginning of the iterator. The first row is row 1, the
- * second is row 2, and so on.
- *
- * @param row
- * the row to move to in this iterator, by absolute number
- */
+ * Moves the cursor to the given row number in the iterator. If the row
+ * number is positive, the cursor moves to the given row number with
+ * respect to the beginning of the iterator. The first row is row 1, the
+ * second is row 2, and so on.
+ *
+ * @param row
+ * the row to move to in this iterator, by absolute number
+ */
public boolean absolute(int row) throws PersistenceBrokerException
{
boolean retval = false;
@@ -689,21 +724,21 @@
else
{
logger.info(
- "Your driver does not support advanced JDBC Functionality, you cannot call absolute() with a position < current");
+ "Your driver does not support advanced JDBC Functionality, you cannot call absolute() with a position < current");
}
}
return retval;
}
/**
- * Moves the cursor a relative number of rows, either positive or negative.
- * Attempting to move beyond the first/last row in the iterator positions
- * the cursor before/after the the first/last row. Calling relative(0) is
- * valid, but does not change the cursor position.
- *
- * @param row
- * the row to move to in this iterator, by relative number
- */
+ * Moves the cursor a relative number of rows, either positive or negative.
+ * Attempting to move beyond the first/last row in the iterator positions
+ * the cursor before/after the the first/last row. Calling relative(0) is
+ * valid, but does not change the cursor position.
+ *
+ * @param row
+ * the row to move to in this iterator, by relative number
+ */
public boolean relative(int row) throws SQLException
{
boolean retval = false;
@@ -737,11 +772,11 @@
}
/**
- * Release all internally used Database resources of the iterator. Clients
- * must call this methods explicitely if the iterator is not exhausted by
- * the client application. If the Iterator is exhauseted this method will
- * be called implicitely.
- */
+ * Release all internally used Database resources of the iterator. Clients
+ * must call this methods explicitely if the iterator is not exhausted by
+ * the client application. If the Iterator is exhauseted this method will
+ * be called implicitely.
+ */
public void releaseDbResources()
{
if (!isInBatchedMode()) // resources are reused in batched mode
@@ -750,7 +785,7 @@
if (!this.resourcesAreReleased)
{
this.resourcesAreReleased = true;
- if(m_rsAndStmt != null)
+ if (m_rsAndStmt != null)
{
m_rsAndStmt.close();
m_rsAndStmt = null;
@@ -760,8 +795,8 @@
}
/**
- * Return the DescriptorRepository
- */
+ * Return the DescriptorRepository
+ */
protected DescriptorRepository getDescriptorRepository()
{
return getBroker().getDescriptorRepository();
@@ -773,13 +808,14 @@
}
/**
- * safety just in case someone leaks.
- */
+ * safety just in case someone leaks.
+ */
protected void finalize()
{
- if(m_rsAndStmt != null)
+ if (m_rsAndStmt != null)
{
- logger.warn("Found unclosed resources while finalize (causer class: "+this.getClass().getName()+")");
+ logger.info("Found unclosed resources while finalize (causer class: " + this.getClass().getName() + ")" +
+ " Do automatic cleanup");
releaseDbResources();
}
}
@@ -790,8 +826,8 @@
}
/**
- * @return Returns the cld.
- */
+ * @return Returns the cld.
+ */
public ClassDescriptor getClassDescriptor()
{
return getQueryObject().getClassDescriptor();
@@ -815,6 +851,11 @@
protected ResultSetAndStatement getRsAndStmt()
{
+ if(resourcesAreReleased)
+ {
+ throw new ResourceClosedException("Resources no longer reachable, RsIterator will be automatic" +
+ " cleaned up on PB.close/.commitTransaction/.abortTransaction");
+ }
return m_rsAndStmt;
}
@@ -896,5 +937,93 @@
protected boolean isInBatchedMode()
{
return m_inBatchedMode;
+ }
+
+ //***********************************************************
+ // inner classes
+ //***********************************************************
+ /**
+ * Wraps a {@link RsIterator} instance as {@link WeakReference}.
+ */
+ public static class ResourceWrapper implements PBStateListener
+ {
+ /*
+ we do register a PBStateListener to PB instance
+ to make sure that this instance will be cleaned up at PB.close() call.
+ If PB was in tx, we cleanup on PB.commit/abort because we create
+ RsIterator instance within a tx.
+ TODO: Check beforeRollback, beforeCommit method calls - is this too strict?
+ */
+ WeakReference ref;
+
+ public ResourceWrapper(RsIterator rs)
+ {
+ ref = new WeakReference(rs);
+ }
+
+ public void beforeClose(PBStateEvent event)
+ {
+ if(ref != null && ref.get() != null)
+ {
+ ((RsIterator)ref.get()).releaseDbResources();
+ ref = null;
+ }
+ }
+
+ public void beforeRollback(PBStateEvent event)
+ {
+ if(ref != null && ref.get() != null)
+ {
+ ((RsIterator)ref.get()).releaseDbResources();
+ ref = null;
+ }
+ }
+
+ public void beforeCommit(PBStateEvent event)
+ {
+ if(ref != null && ref.get() != null)
+ {
+ ((RsIterator)ref.get()).releaseDbResources();
+ ref = null;
+ }
+ }
+
+ public void afterCommit(PBStateEvent event)
+ {
+ }
+ public void afterRollback(PBStateEvent event)
+ {
+ }
+ public void afterBegin(PBStateEvent event)
+ {
+ }
+ public void beforeBegin(PBStateEvent event)
+ {
+ }
+ public void afterOpen(PBStateEvent event)
+ {
+ }
+ }
+
+ public static class ResourceClosedException extends OJBRuntimeException
+ {
+ public ResourceClosedException()
+ {
+ }
+
+ public ResourceClosedException(String msg)
+ {
+ super(msg);
+ }
+
+ public ResourceClosedException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ public ResourceClosedException(String msg, Throwable cause)
+ {
+ super(msg, cause);
+ }
}
}
1.10 +10 -3 db-ojb/src/java/org/apache/ojb/broker/accesslayer/ResultSetAndStatement.java
Index: ResultSetAndStatement.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/ResultSetAndStatement.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ResultSetAndStatement.java 27 Nov 2003 14:50:23 -0000 1.9
+++ ResultSetAndStatement.java 13 Dec 2003 17:50:40 -0000 1.10
@@ -137,8 +137,15 @@
super.finalize();
if(!isClosed && (m_stmt != null || m_rs != null))
{
- log.error("** Associated resources (Statement/ResultSet) not closed!" +
- " This could lead in leaking resources **");
+ log.warn("** Associated resources (Statement/ResultSet) not closed!" +
+ " Try automatic cleanup **");
+ try
+ {
+ close();
+ }
+ catch (Exception ignore)
+ {
+ }
}
}
}
1.4 +191 -43 db-ojb/src/test/org/apache/ojb/broker/RsIteratorTest.java
Index: RsIteratorTest.java
===================================================================
RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/broker/RsIteratorTest.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- RsIteratorTest.java 7 Jun 2003 10:18:33 -0000 1.3
+++ RsIteratorTest.java 13 Dec 2003 17:50:40 -0000 1.4
@@ -1,7 +1,10 @@
package org.apache.ojb.broker;
+import java.util.Iterator;
+
import junit.framework.TestCase;
import org.apache.ojb.broker.query.*;
+import org.apache.ojb.broker.accesslayer.RsIterator;
/**
* Test case for the RsIterator
@@ -9,67 +12,212 @@
* @author <a href="mailto:rongallagher@bellsouth.net">Ron Gallagher<a>
* @version $Id$
*/
-public class RsIteratorTest extends TestCase {
- private static Class CLASS = RsIteratorTest.class;
- private int COUNT = 10;
-
- public static void main(String[] args){
- String[] arr = {CLASS.getName()};
+public class RsIteratorTest extends TestCase
+{
+ private PersistenceBroker broker;
+
+ public static void main(String[] args)
+ {
+ String[] arr = {RsIteratorTest.class.getName()};
junit.textui.TestRunner.main(arr);
}
- /**
- * Insert the method's description here.
- * Creation date: (24.12.2000 00:33:40)
- */
- public RsIteratorTest(String name){
+ public RsIteratorTest(String name)
+ {
super(name);
}
+ public void setUp()
+ {
+ broker = PersistenceBrokerFactory.defaultPersistenceBroker();
+ }
+
+ public void tearDown()
+ {
+ if(broker != null)
+ {
+ broker.close();
+ }
+ }
+
+ public void testRsIterator() throws Exception
+ {
+ String name = "testRsIterator_" + System.currentTimeMillis();
+ prepareTest(name);
+
+ Criteria criteria = new Criteria();
+ criteria.addLike("name", name+"*");
+ Query query = new QueryByCriteria(ObjectRepository.Component.class, criteria);
+
+ Iterator it = broker.getIteratorByQuery(query);
+ int k = 0;
+ while(it.hasNext())
+ {
+ it.next();
+ k++;
+ }
+ assertEquals("Wrong number of items found", 2, k);
+ }
+
/**
- * Insert the method's description here.
- * Creation date: (06.12.2000 21:58:53)
+ * Test RsIterator cleanup on PB.commitTransaction()
*/
- public void setUp(){
+ public void testRsIteratorAutomaticCleanupCheck_1() throws Exception
+ {
+ String name = "testRsIteratorAutomaticCleanupCheck_1_" + System.currentTimeMillis();
+ prepareTest(name);
+
+ Criteria criteria = new Criteria();
+ criteria.addLike("name", name+"*");
+ Query query = new QueryByCriteria(ObjectRepository.Component.class, criteria);
+
+ Iterator it = broker.getIteratorByQuery(query);
+ it.hasNext();
+ broker.beginTransaction();
+ broker.commitTransaction();
+ /*
+ if tx was commited we invalidate RsIterator instance
+ */
+ try
+ {
+ it.next();
+ fail("We expect RsIterator has released resources on pb.commit..");
+ }
+ catch (RsIterator.ResourceClosedException e)
+ {
+ assertTrue(true);
+ }
+
+
+ it = broker.getIteratorByQuery(query);
+ it.hasNext();
+ it.next();
+ broker.beginTransaction();
+ broker.commitTransaction();
+ /*
+ if tx was commited we invalidate RsIterator instance
+ */
+ try
+ {
+ it.hasNext();
+ it.next();
+ fail("We expect RsIterator has released resources on pb.commit..");
+ }
+ catch (RsIterator.ResourceClosedException e)
+ {
+ assertTrue(true);
+ }
}
/**
- * Test retrieving data via the rsIterator
+ * Test RsIterator cleanup on PB.abortTransaction()
*/
- public void testIterator()
- throws Exception{
+ public void testRsIteratorAutomaticCleanupCheck_2() throws Exception
+ {
+ String name = "testRsIteratorAutomaticCleanupCheck_" + System.currentTimeMillis();
+ prepareTest(name);
+
+ Criteria criteria = new Criteria();
+ criteria.addLike("name", name+"*");
+ Query query = new QueryByCriteria(ObjectRepository.Component.class, criteria);
+
+ Iterator it = broker.getIteratorByQuery(query);
+ it.hasNext();
+ broker.beginTransaction();
+ broker.abortTransaction();
+ /*
+ if tx was aborted we invalidate RsIterator instance
+ */
+ try
+ {
+ it.next();
+ fail("We expect RsIterator has released resources on pb.commit..");
+ }
+ catch (RsIterator.ResourceClosedException e)
+ {
+ assertTrue(true);
+ }
- // Get the broker
- PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker();
- try {
- // Build the query
- Criteria criteria = new Criteria();
- criteria.addEqualTo("id",new Integer(1));
- Query query = new QueryByCriteria(Person.class,criteria);
- // Run the query.
- Person person = (Person)broker.getObjectByQuery(query);
- // The previous call may or may not return a 'real' Person
- // object. What it returns is not important. The test here
- // is whether or not this call raises an error or not. When
- // this code runs using hsqldb, it works fine. However, when
- // this code runs against Oracle, it fails with a null pointer
- // exception.
- } catch ( Exception e ) {
- fail(e.toString());
- e.printStackTrace();
- throw e;
- } finally {
- // Release resources
- broker.close();
+
+ it = broker.getIteratorByQuery(query);
+ it.hasNext();
+ it.next();
+ broker.beginTransaction();
+ broker.abortTransaction();
+ /*
+ if tx was aborted we invalidate RsIterator instance
+ */
+ try
+ {
+ it.hasNext();
+ it.next();
+ fail("We expect RsIterator has released resources on pb.commit..");
+ }
+ catch (RsIterator.ResourceClosedException e)
+ {
+ assertTrue(true);
}
}
/**
- * Insert the method's description here.
- * Creation date: (06.12.2000 21:59:14)
+ * Test RsIterator cleanup on PB.close()
*/
- public void tearDown(){
+ public void testRsIteratorAutomaticCleanupCheck_3() throws Exception
+ {
+ String name = "testRsIteratorAutomaticCleanupCheck_" + System.currentTimeMillis();
+ prepareTest(name);
+
+ Criteria criteria = new Criteria();
+ criteria.addLike("name", name+"*");
+ Query query = new QueryByCriteria(ObjectRepository.Component.class, criteria);
+
+ Iterator it = broker.getIteratorByQuery(query);
+ broker.close();
+ /*
+ if was closed we invalidate RsIterator instance
+ */
+ try
+ {
+ if(it.hasNext()) it.next();
+ fail("We expect RsIterator has released resources on pb.commit..");
+ }
+ catch (RsIterator.ResourceClosedException e)
+ {
+ assertTrue(true);
+ }
+ }
+
+ private void prepareTest(String objectName)
+ {
+ ObjectRepository.Component c1 = new ObjectRepository.Component();
+ c1.setName(objectName + "_1");
+ ObjectRepository.Component c2 = new ObjectRepository.Component();
+ c2.setName(objectName + "_2");
+
+ broker.beginTransaction();
+ broker.store(c1);
+ broker.store(c2);
+ broker.commitTransaction();
}
+ /**
+ * Test retrieving data via the rsIterator
+ * test by Ron Gallagher
+ */
+ public void testInternUsedRsIterator() throws Exception
+ {
+ // Build the query
+ Criteria criteria = new Criteria();
+ criteria.addEqualTo("id", new Integer(1));
+ Query query = new QueryByCriteria(Person.class, criteria);
+ // Run the query.
+ Person person = (Person) broker.getObjectByQuery(query);
+ // The previous call may or may not return a 'real' Person
+ // object. What it returns is not important. The test here
+ // is whether or not this call raises an error or not. When
+ // this code runs using hsqldb, it works fine. However, when
+ // this code runs against Oracle, it fails with a null pointer
+ // exception.
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org