Bug #9562 Operation not allowed after ResultSet closed
Submitted: 1 Apr 2005 16:10 Modified: 31 Mar 2014 9:09
Reporter: Michael Small Email Updates:
Status: Not a Bug Impact on me:
None 
Category:Connector / J Severity:S2 (Serious)
Version:nightly-20050331 OS:Windows (Windows 2000)
Assigned to: Alexander Soklakov CPU Architecture:Any

[1 Apr 2005 16:10] Michael Small
Description:
I continually receive the following exception when using the Connector/J 3.1 (nightly build 20050331 ... I need this build because 3.1.7 had a bug that was solved that was critical for my application):

Caused by: java.sql.SQLException: Operation not allowed after ResultSet closed
	at com.mysql.jdbc.ResultSet.checkClosed(ResultSet.java:4374)
	at com.mysql.jdbc.ResultSet.checkRowPos(ResultSet.java:4388)
	at com.mysql.jdbc.ResultSet.getNativeString(ResultSet.java:6432)
	at com.mysql.jdbc.ResultSet.getStringInternal(ResultSet.java:2280)
	at com.mysql.jdbc.ResultSet.getString(ResultSet.java:2176)
	at com.tasc.dao.mysql.TascClientMySqlDao.loadTascClient(TascClientMySqlDao.java:294)
	at com.tasc.dao.mysql.TascClientMySqlDao.findAll(TascClientMySqlDao.java:250)

What's even more disturbing is that the stack trace reports the problem at different lines for the loadTascClient method each time I run the application ... in some instances, it is line 274, some 281, some 294, etc.  I read an earlier bug posting about "Operation not allowed ...", but I have confirmed that only one thread is calling this method at a time and the statement and result objects are not closed until well after the findAll method has returned.  In fact, I recently upgraded to 3.1 (because we went to 4.1.10a Server).  Previously (running 3.0), I never had a problem.

Below is the code for com.tasc.dao.mysql.TascClientMySqlDao:

package com.tasc.dao.mysql;

import com.tasc.dao.DaoError;
import com.tasc.dao.mysql.MySqlDao;

import com.tasc.*;
import com.tasc.dao.*;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Date;

import org.apache.log4j.Logger;

/**
 * MySQL implementation of <code>TascClientDao</code>.
 */
public class TascClientMySqlDao extends MySqlDao implements TascClientDao {

    private static Logger logger = Logger.getLogger(TascClientMySqlDao.class);

    private static final String TABLE_NAME = "Tasc_Client";
    private static final String FIELD_LIST = 
	"internalKey, clientId, taxId, clientName, contactName, contactLastname, contactFirstname, " + 
	"address1, address2, city, state, zipcode, phoneNumber, faxNumber, mobilNumber, emailAddress, " + 
	"noEmailAddress, fk_Provider_internalKey, fk_Rsd_internalKey, fk_Tasc_Product_internalKey, " + 
	"dateOfInitialSale, startOfServiceDate, status, " + 
	"fk_Tasc_ClientCancelCode_internalKey, dateCanceled, vip, takeOver, pin";

 
    private static final String FIND_ALL_STMT = 
	"SELECT " + FIELD_LIST + " " + 
	"FROM " + TABLE_NAME;

    private PreparedStatement findAllStmt;

    public TascClientMySqlDao(Connection conn) {
	super(conn);
    }

        public Collection findAll() {

	try {

	    this.checkConnection();

	    if (this.findAllStmt == null) {
		this.findAllStmt = this.getConnection().prepareStatement(FIND_ALL_STMT);
	    }

	    LinkedList clients = new LinkedList();
	    ResultSet results = this.findAllStmt.executeQuery();

	    while (results.next()) {
		clients.add(this.loadTascClient(results));
	    }

	    results.close();
	    results = null;

	    if (clients.isEmpty()) return(null);
	    return(clients);

	} catch (SQLException sqle) {
	    throw new DaoError(sqle);
	}

    }

    protected TascClientVo loadTascClient(ResultSet result) throws SQLException {

	TascClientVo vo = new TascClientVo();

	vo.setInternalKey(this.getLong(1, result));
	vo.setClientId(result.getString(2));
	vo.setTaxId(result.getString(3));
	vo.setClientName(result.getString(4));
	vo.setContactName(result.getString(5));
	vo.setContactLastname(result.getString(6));
	vo.setContactFirstname(result.getString(7));
	vo.setAddress1(result.getString(8));
	vo.setAddress2(result.getString(9));
	vo.setCity(result.getString(10));
	vo.setState(result.getString(11));
	vo.setZipcode(result.getString(12));
	vo.setPhoneNumber(result.getString(13));
	vo.setFaxNumber(result.getString(14));
	vo.setMobilNumber(result.getString(15));
	vo.setEmailAddress(result.getString(16));
	vo.setNoEmailAddress(this.getBoolean(17, result));
	vo.setProviderInternalKey(this.getLong(18, result));
	vo.setRsdInternalKey(this.getLong(19, result));
	vo.setProductInternalKey(this.getLong(20, result));
	vo.setDateOfInitialSale(result.getDate(21));
	vo.setStartOfServiceDate(result.getDate(22));
	vo.setStatus(result.getString(23));
	vo.setCancelCodeInternalKey(this.getLong(24, result));
	vo.setDateCanceled(result.getDate(25));
	vo.setVip(this.getBoolean(26, result));
	vo.setTakeOver(this.getBoolean(27, result));
	vo.setPin(result.getString(28));

	return(vo);

    }

}

How to repeat:
Call the findAll method of the above class.
[1 Apr 2005 16:14] Michael Small
I forgot to mention (because I removed other finder methods) that the line numbers listed do not correlate with the code I put in the bug listing.  For clarification, I have received the problems at the following code lines in the loadTascClient():

vo.setTaxId(...)
vo.setZipcode(....)
vo.setStatus(...)
[1 Apr 2005 16:17] Michael Small
Another note, the ResultSet returned is large (roughly 130,000 records).  Could it possibly be that size of the ResultSet is causing the problem?
[1 Apr 2005 16:20] Mark Matthews
The only way this could happen is if _something_ is closing the result set.

Are you sure you're not experiencing the connection dying somewhere along the way (check your server's error log), because the JDBC specification requires that 1) A communications error closes the connection, and 2) That closing a connection implicitly closes all open statements, and that 3) closing a statement implicitly closes all open result sets.

Could you tell us what happens if you run your application with the following configuration parameter added to your JDBC URL?

'holdResultsOpenOverStatementClose=true'
[1 Apr 2005 16:36] Michael Small
It appears to running correctly now.  I ready the documentation on this property (as well as your comment about something closing the Connection/Statement/Result), but this code is running in a single threaded application.  No other objects are using the same DAO object.  The statements (and connection) are closed in the finalize() method of the object (as inherited by it's parent com.tasc.dao.mysql.MySqlDao class).
[1 Apr 2005 16:49] Michael Small
Is there a way I can turn on debugging of the ResultSet?  Is it possible that a error is occurring between the driver and the server that is closing the Connection/Statement/ResultSet without throwing an error (which then manifests later when I call a getter method of the ResultSet)?
[1 May 2005 23:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[31 Mar 2014 9:09] Alexander Soklakov
I close this report as "Not a Bug". Please, feel free to reopen it if the problem still exists in current driver.