I have the following predicate implementation:
public boolean evaluate(RowSet rowset )
{try{
int count=0;
CachedRowSet crs = (CachedRowSet)rowset;
{
if (!crs.isAfterLast())//CRUCIAL LINE
for (int i=0;i<index.length;i++)
{
if ((crs.getObject(index[i])).toString().compareTo(high[i].toString())<=0)
{
if ((crs.getObject(index[i])).toString().compareTo(low[i].toString())>=0)
{
count++;
}
}
}
}
Now, if I comment out the "crucial line" hence:
if (!crs.isAfterLast())
I will get a java.sql.SQLException: Invalid cursor position
.
Why does it happen so? Does not it get used the .next() method returning false if the next line is afterLast?
I can traverse any resultset without having to check if (!crs.isAfterLast())
. Just using rs.next() would be enough as it returns false if next is after the last.
Why in predicate this does not happen? Thanks in advance.
The issue you are encountering is a bug in Java 7 (even in 7.0_45), documented here: https://bugs.java.com/bugdatabase/view_bug?bug_id=7166598
A simple workaround to avoid the "Invalid cursor position" SQLException that worked for me is to add this logic to the start of your implementation of Predicate.evaluate(RowSet rs) to detect the end-of-rowset condition:
FilteredRowSet frs = (FilteredRowSet) rs;
int rowNum = frs.getRow();
if (rowNum == 0) { // Meaning "no current row" - should never happen...
return false; // Needed only to address a bug in Java 7
}
Your workaround of calling isAfterLast() also seems fine, and the ugly workaround of simply swallowing the SQLException also works, since the exception occurs after all processing is complete.
The problem is fixed under Java 8 RTE, and recompilation is not necessary.
I have specifically tested a Predicate implementation which is failing under Java 7 using Java 8, within Intellij Idea, and also from the command line. Under Java 8 it also works fine without needing the Java 7 workaround described above.