modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BaseCriteria.java | 7
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java | 9
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftChangeSetCriteria.java | 30 +
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftCriteria.java | 29 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java | 190 +++++++++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java | 40 +-
6 files changed, 278 insertions(+), 27 deletions(-)
New commits:
commit 962b33d40299d5076e57e5e5949c4d664d62ab15
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Feb 20 13:53:51 2013 -0500
CriteriaQuery should always have a sort applied in the Criteria supplied to
it. Otherwise the implicit chunking will be unreliable, as queries will
have no guaranteed ordering, the DB is free to order results in any way it
likes.
To do this I've done two things:
1) I added the ability to sort by ID on all subclasses of Criteria
2) If no sort is specified in the CriteriaQuery Criteria, an ID sort is added
This default ASC sort on ID provides consistent chunking and the fastest
ordering given that it's an indexed (PK) field.
AND, DONE DURING MERGE:
Fix merge issue.
Also:
- fix issue when using CriteriaQuery with pageControlOverrides
- update tests to cover a few more scenarios
- remove the unnecessary pagecontrol overrides forwarding in CriteriaQuery.next
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BaseCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BaseCriteria.java
index c4993c1..5b931aa 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BaseCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BaseCriteria.java
@@ -18,7 +18,10 @@
*/
package org.rhq.core.domain.criteria;
+import java.util.List;
+
import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageOrdering;
/**
* All criteria, regardless of the backend storage that will be queried with this criteria, needs
@@ -28,6 +31,10 @@ import org.rhq.core.domain.util.PageControl;
*/
public interface BaseCriteria {
+ void addSortId(PageOrdering sortId);
+
+ List<String> getOrderingFieldNames();
+
PageControl getPageControlOverrides();
void setPageControl(PageControl pageControl);
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
index afcff6f..2ae6859 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
@@ -35,6 +35,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
/**
* @author Joseph Marques
@@ -96,6 +97,9 @@ public abstract class Criteria implements Serializable, BaseCriteria {
private String searchExpression;
+ // All Criteria support sorting on ID
+ private PageOrdering sortId;
+
/**
* This default constructor will set default paging to avoid unintended fetch of huge results. The default is:
* <pre>setPaging(0, 200);</pre>
@@ -139,6 +143,11 @@ public abstract class Criteria implements Serializable, BaseCriteria {
return pageControlOverrides;
}
+ public void addSortId(PageOrdering sortId) {
+ addSortField("id");
+ this.sortId = sortId;
+ }
+
protected void addSortField(String fieldName) {
orderingFieldNames.add("sort" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1));
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftChangeSetCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftChangeSetCriteria.java
index 0cb6bfa..c640bf0 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftChangeSetCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftChangeSetCriteria.java
@@ -18,15 +18,16 @@
*/
package org.rhq.core.domain.criteria;
-import org.rhq.core.domain.drift.DriftCategory;
-import org.rhq.core.domain.drift.DriftChangeSetCategory;
-import org.rhq.core.domain.util.PageControl;
-import org.rhq.core.domain.util.PageOrdering;
+import static org.rhq.core.domain.util.CriteriaUtils.getListIgnoringNulls;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.List;
-import static org.rhq.core.domain.util.CriteriaUtils.getListIgnoringNulls;
+import org.rhq.core.domain.drift.DriftCategory;
+import org.rhq.core.domain.drift.DriftChangeSetCategory;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageOrdering;
/**
* The generic implementation of DriftChangeSetCriteria makes no assumptions about the actual drift server
@@ -68,6 +69,8 @@ public class GenericDriftChangeSetCriteria implements Serializable, DriftChangeS
private boolean fetchDrifts;
+ private PageOrdering sortId;
+
private PageOrdering sortVersion;
private PageControl pageControl;
@@ -209,6 +212,11 @@ public class GenericDriftChangeSetCriteria implements Serializable, DriftChangeS
}
@Override
+ public void addSortId(PageOrdering sortId) {
+ this.sortId = sortId;
+ }
+
+ @Override
public void addSortVersion(PageOrdering sortVersion) {
this.sortVersion = sortVersion;
}
@@ -244,4 +252,16 @@ public class GenericDriftChangeSetCriteria implements Serializable, DriftChangeS
pageControl.setPageSize(pageSize);
}
+ @Override
+ public List<String> getOrderingFieldNames() {
+ List<String> result = new ArrayList<String>(2);
+ if (null != sortId) {
+ result.add("id");
+ }
+ if (null != sortVersion) {
+ result.add("version");
+ }
+ return result;
+ }
+
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftCriteria.java
index 3146b16..1c53353 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/GenericDriftCriteria.java
@@ -18,16 +18,16 @@
*/
package org.rhq.core.domain.criteria;
-import org.rhq.core.domain.drift.DriftCategory;
-import org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode;
-import org.rhq.core.domain.util.PageControl;
-import org.rhq.core.domain.util.PageOrdering;
+import static org.rhq.core.domain.util.CriteriaUtils.getListIgnoringNulls;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-import static org.rhq.core.domain.util.CriteriaUtils.getListIgnoringNulls;
+import org.rhq.core.domain.drift.DriftCategory;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageOrdering;
/**
* The generic implementation of DriftCriteria makes no assumptions about the actual drift server
@@ -71,6 +71,8 @@ public class GenericDriftCriteria implements Serializable, DriftCriteria {
private PageControl pageControl;
+ private PageOrdering sortId;
+
private PageOrdering sortCtime;
private boolean strict;
@@ -206,6 +208,11 @@ public class GenericDriftCriteria implements Serializable, DriftCriteria {
}
@Override
+ public void addSortId(PageOrdering sortId) {
+ this.sortId = sortId;
+ }
+
+ @Override
public void addSortCtime(PageOrdering sortCtime) {
this.sortCtime = sortCtime;
}
@@ -241,4 +248,16 @@ public class GenericDriftCriteria implements Serializable, DriftCriteria {
pageControl.setPageSize(pageSize);
}
+ @Override
+ public List<String> getOrderingFieldNames() {
+ List<String> result = new ArrayList<String>(2);
+ if (null != sortId) {
+ result.add("id");
+ }
+ if (null != sortCtime) {
+ result.add("ctime");
+ }
+ return result;
+ }
+
}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java
index e746deb..f48d360 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java
@@ -132,8 +132,8 @@ public class ResourceStorageTest extends AbstractEJB3Test {
ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager();
SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
PageControl pc = new PageControl(0, 5, new OrderingField("rg.name", PageOrdering.ASC));
- PageList<ResourceGroupComposite> groups = groupManager.findResourceGroupComposites(subjectManager
- .getOverlord(), GroupCategory.COMPATIBLE, null, null, null, null, null, null, pc);
+ PageList<ResourceGroupComposite> groups = groupManager.findResourceGroupComposites(
+ subjectManager.getOverlord(), GroupCategory.COMPATIBLE, null, null, null, null, null, null, pc);
System.out.println("Found compatible groups: " + groups.getTotalSize());
for (ResourceGroupComposite group : groups) {
System.out.println("\t" + group);
@@ -195,8 +195,8 @@ public class ResourceStorageTest extends AbstractEJB3Test {
Subject rhqadmin = subjectManager.loginUnauthenticated("rhqadmin");
rhqadmin = createSession(rhqadmin);
- Map<Resource, List<Resource>> queue = discoveryBoss.getQueuedPlatformsAndServers(rhqadmin, PageControl
- .getUnlimitedInstance());
+ Map<Resource, List<Resource>> queue = discoveryBoss.getQueuedPlatformsAndServers(rhqadmin,
+ PageControl.getUnlimitedInstance());
for (Resource root : queue.keySet()) {
System.out.println("Queue root resource: " + root);
}
@@ -228,7 +228,6 @@ public class ResourceStorageTest extends AbstractEJB3Test {
*
* @throws Exception
*/
- @SuppressWarnings("unused")
@Test(groups = "integration.ejb3")
public void testParsingCriteriaQueryResults() throws Exception {
getTransactionManager().begin();
@@ -251,8 +250,7 @@ public class ResourceStorageTest extends AbstractEJB3Test {
String tuid = "" + new Random().nextInt();
//create large number of resources
String prefix = "largeResultSet-" + tuid + "-";
- System.out.println("-------- Creating " + resourceCount
- + " resource(s). This may take a while ....");
+ System.out.println("-------- Creating " + resourceCount + " resource(s). This may take a while ....");
long start = System.currentTimeMillis();
for (int i = 0; i < resourceCount; i++) {
@@ -264,15 +262,14 @@ public class ResourceStorageTest extends AbstractEJB3Test {
entityMgr.flush();
System.out.println("----------- Created " + resourceCount + " resource(s) in "
- + (System.currentTimeMillis() - start)
- + " ms.");
+ + (System.currentTimeMillis() - start) + " ms.");
assert resourceNames.size() == resourceCount;//assert all resources loaded/created
//query the results and delete the resources
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterName(prefix);
- criteria.addSortName(PageOrdering.ASC);
+ criteria.addSortName(PageOrdering.DESC); // use DESC just to make sure sorting on name is different than insert order
criteria.setPaging(0, 47);
//iterate over the results with CriteriaQuery
@@ -288,10 +285,95 @@ public class ResourceStorageTest extends AbstractEJB3Test {
criteria, queryExecutor);
start = System.currentTimeMillis();
+ String prevName = null;
+ //iterate over the entire result set efficiently
+ ArrayList<String> alreadySeen = new ArrayList<String>();
+ int actualCount = 0;
+ for (Resource r : resources) {
+ assert null == prevName || r.getName().compareTo(prevName) < 0 : "Results should be sorted by name DESC, something is out of order";
+ prevName = r.getName();
+ actualCount++;
+ // System.out.println(actualCount + " @@@ " + r.getId() + ":"
+ // + ((resourceNames.containsKey(String.valueOf(r.getId()))) ? "NEW" : "DIRTY") + ":" + r.getName());
+ resourceNames.remove(String.valueOf(r.getId()));
+ }
+
+ System.out.println("----------- Parsed " + actualCount + " resource(s) in "
+ + (System.currentTimeMillis() - start) + " ms.");
+
+ //test that entire list parsed spanning multiple pages
+ assert resourceNames.size() == 0 : "Expected resourceNames to be empty. Still " + resourceNames.size()
+ + " name(s).";
+
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void testParsingCriteriaQueryResults_2() throws Exception {
+ // Same test as above but makes sure default id search works. use different numbers just for variety
+ getTransactionManager().begin();
+ EntityManager entityMgr = getEntityManager();
+ final ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+
+ //verify that all resource objects are actually parsed.
+ Map<String, Object> resourceNames = new HashMap<String, Object>();
+ int resourceCount = 344;
+
+ try {
+ final Subject subject = SessionTestHelper.createNewSubject(entityMgr, "testSubject");
+
+ Role roleWithSubject = SessionTestHelper.createNewRoleForSubject(entityMgr, subject, "role with subject");
+ roleWithSubject.addPermission(Permission.VIEW_RESOURCE);
+
+ ResourceGroup group = SessionTestHelper.createNewCompatibleGroupForRole(entityMgr, roleWithSubject,
+ "accessible group");
+
+ String tuid = "" + new Random().nextInt();
+ //create large number of resources
+ String prefix = "largeResultSet-" + tuid + "-";
+ System.out.println("-------- Creating " + resourceCount + " resource(s). This may take a while ....");
+
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < resourceCount; i++) {
+ String name = prefix + i;
+ Resource r = SessionTestHelper.createNewResourceForGroup(entityMgr, group, name);
+ //store away each resource name/key
+ resourceNames.put(String.valueOf(r.getId()), name);
+ }
+ entityMgr.flush();
+
+ System.out.println("----------- Created " + resourceCount + " resource(s) in "
+ + (System.currentTimeMillis() - start) + " ms.");
+
+ assert resourceNames.size() == resourceCount;//assert all resources loaded/created
+
+ //query the results and delete the resources, use default ID search
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterName(prefix);
+ criteria.setPaging(0, 25);
+
+ //iterate over the results with CriteriaQuery
+ CriteriaQueryExecutor<Resource, ResourceCriteria> queryExecutor = new CriteriaQueryExecutor<Resource, ResourceCriteria>() {
+ @Override
+ public PageList<Resource> execute(ResourceCriteria criteria) {
+ return resourceManager.findResourcesByCriteria(subject, criteria);
+ }
+ };
+
+ //initiate first/(total depending on page size) request.
+ CriteriaQuery<Resource, ResourceCriteria> resources = new CriteriaQuery<Resource, ResourceCriteria>(
+ criteria, queryExecutor);
+
+ start = System.currentTimeMillis();
+ int prevId = 0;
//iterate over the entire result set efficiently
ArrayList<String> alreadySeen = new ArrayList<String>();
int actualCount = 0;
for (Resource r : resources) {
+ assert r.getId() > prevId : "Results should be sorted by ID ASC, something is out of order";
+ prevId = r.getId();
actualCount++;
// System.out.println(actualCount + " @@@ " + r.getId() + ":"
// + ((resourceNames.containsKey(String.valueOf(r.getId()))) ? "NEW" : "DIRTY") + ":" + r.getName());
@@ -299,8 +381,7 @@ public class ResourceStorageTest extends AbstractEJB3Test {
}
System.out.println("----------- Parsed " + actualCount + " resource(s) in "
- + (System.currentTimeMillis() - start)
- + " ms.");
+ + (System.currentTimeMillis() - start) + " ms.");
//test that entire list parsed spanning multiple pages
assert resourceNames.size() == 0 : "Expected resourceNames to be empty. Still " + resourceNames.size()
@@ -310,4 +391,89 @@ public class ResourceStorageTest extends AbstractEJB3Test {
getTransactionManager().rollback();
}
}
+
+ @Test(groups = "integration.ejb3")
+ public void testParsingCriteriaQueryResults_3() throws Exception {
+ // Same test as above but makes sure pageoverrides default id search works. use different numbers just for variety
+ getTransactionManager().begin();
+ EntityManager entityMgr = getEntityManager();
+ final ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+
+ //verify that all resource objects are actually parsed.
+ Map<String, Object> resourceNames = new HashMap<String, Object>();
+ int resourceCount = 423;
+
+ try {
+ final Subject subject = SessionTestHelper.createNewSubject(entityMgr, "testSubject");
+
+ Role roleWithSubject = SessionTestHelper.createNewRoleForSubject(entityMgr, subject, "role with subject");
+ roleWithSubject.addPermission(Permission.VIEW_RESOURCE);
+
+ ResourceGroup group = SessionTestHelper.createNewCompatibleGroupForRole(entityMgr, roleWithSubject,
+ "accessible group");
+
+ String tuid = "" + new Random().nextInt();
+ //create large number of resources
+ String prefix = "largeResultSet-" + tuid + "-";
+ System.out.println("-------- Creating " + resourceCount + " resource(s). This may take a while ....");
+
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < resourceCount; i++) {
+ String name = prefix + i;
+ Resource r = SessionTestHelper.createNewResourceForGroup(entityMgr, group, name);
+ //store away each resource name/key
+ resourceNames.put(String.valueOf(r.getId()), name);
+ }
+ entityMgr.flush();
+
+ System.out.println("----------- Created " + resourceCount + " resource(s) in "
+ + (System.currentTimeMillis() - start) + " ms.");
+
+ assert resourceNames.size() == resourceCount;//assert all resources loaded/created
+
+ //query the results and delete the resources, use default ID search
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterName(prefix);
+ PageControl pc = new PageControl(0, 73);
+ criteria.setPageControl(pc);
+ assert pc.getOrderingFields().isEmpty() : "Should not have had any sorting defined";
+
+ //iterate over the results with CriteriaQuery
+ CriteriaQueryExecutor<Resource, ResourceCriteria> queryExecutor = new CriteriaQueryExecutor<Resource, ResourceCriteria>() {
+ @Override
+ public PageList<Resource> execute(ResourceCriteria criteria) {
+ return resourceManager.findResourcesByCriteria(subject, criteria);
+ }
+ };
+
+ //initiate first/(total depending on page size) request.
+ CriteriaQuery<Resource, ResourceCriteria> resources = new CriteriaQuery<Resource, ResourceCriteria>(
+ criteria, queryExecutor);
+
+ start = System.currentTimeMillis();
+ int prevId = 0;
+ //iterate over the entire result set efficiently
+ ArrayList<String> alreadySeen = new ArrayList<String>();
+ int actualCount = 0;
+ for (Resource r : resources) {
+ System.out.println(actualCount + " @@@ " + r.getId() + ":"
+ + ((resourceNames.containsKey(String.valueOf(r.getId()))) ? "NEW" : "DIRTY") + ":" + r.getName());
+ assert r.getId() > prevId : "Results should be sorted by ID ASC, something is out of order";
+ prevId = r.getId();
+ actualCount++;
+ resourceNames.remove(String.valueOf(r.getId()));
+ }
+
+ System.out.println("----------- Parsed " + actualCount + " resource(s) in "
+ + (System.currentTimeMillis() - start) + " ms.");
+
+ //test that entire list parsed spanning multiple pages
+ assert resourceNames.size() == 0 : "Expected resourceNames to be empty. Still " + resourceNames.size()
+ + " name(s).";
+
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
index 5e30b87..ab6a915 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
@@ -27,6 +27,7 @@ import java.util.NoSuchElementException;
import org.rhq.core.domain.criteria.BaseCriteria;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
/** This class provides a way to make PageList results easily iterable with 'for each','while',etc. loops
* and importantly automatically handles iteration through all PageControl results. This
@@ -50,9 +51,28 @@ public class CriteriaQuery<T, C extends BaseCriteria> implements Iterable<T> {
//Executor
private CriteriaQueryExecutor<T, C> queryExecutor;
+ /**
+ * It is important that the <code>criteria</code> includes sorting. If not then paging is nonsensical as the DB
+ * provides no guarantee of ordering. If no sort is specified, an implicit sort on ID is added.
+ *
+ * @param criteria The criteria applied to each execution of the fetch. If no sort is specified, an implicit sort on
+ * ID is added.
+ * @param queryExecutor
+ */
public CriteriaQuery(C criteria, CriteriaQueryExecutor<T, C> queryExecutor) {
this.criteria = criteria;
this.queryExecutor = queryExecutor;
+
+ // make sure we have at least a default sort, otherwise chunking doesn't work
+ PageControl pageControlOverrides = this.criteria.getPageControlOverrides();
+ if (null != pageControlOverrides) {
+ if (pageControlOverrides.getOrderingFields().isEmpty()) {
+ pageControlOverrides.addDefaultOrderingField("id");
+ }
+
+ } else if (this.criteria.getOrderingFieldNames().isEmpty()) {
+ this.criteria.addSortId(PageOrdering.ASC);
+ }
}
/** Returns iterator for a single page of results as defined by
@@ -104,21 +124,31 @@ public class CriteriaQuery<T, C extends BaseCriteria> implements Iterable<T> {
if (count == currentPage.getTotalSize()) {
throw new NoSuchElementException();
}
- deletable = null;//reset deletable.
+
+ deletable = null; // reset deletable.
+
//remove all flagged instances of T
if (!forDeletion.isEmpty()) {
currentPage.removeAll(forDeletion);
forDeletion.clear();
}
- PageControl pc = currentPage.getPageControl();
- criteria.setPaging(pc.getPageNumber() + 1, pc.getPageSize());
+ // advance the page. Although strange to be using a page control override in conjunction with
+ // CriteriaQuery, nonetheless make sure we advance it if it exists, because the normal setPaging is
+ // ignored when their is an overrides.
+ PageControl pcCurrent = currentPage.getPageControl();
+ PageControl pcOverrides = criteria.getPageControlOverrides();
+
+ if (null != pcOverrides) {
+ pcOverrides.setPageNumber(pcOverrides.getPageNumber() + 1);
+ } else {
+ criteria.setPaging(pcCurrent.getPageNumber() + 1, pcCurrent.getPageSize());
+ }
+
//help out the GC.
currentPage.clear();
- //move the current pagelist forward one
currentPage = queryExecutor.execute(criteria);
- currentPage.setPageControl(new PageControl(pc.getPageNumber() + 1, pc.getPageSize()));
iterator = currentPage.iterator();
}