FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
If you:
-> have a CachedRowSet on table with an auto-increment primary key in a mySQL database.
-> you are inserting a new row
-> you are calling acceptChanges
you will get an NPE.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1/ in your mySQL database creates a database "ilog_demos"
2/ in your mySQL "test" database creates a table "activities"
3/ modify the attached .java to use your login/passwd to mysql and change "server" by your mySQL server.
4/ run the sample
you'll get a NPE because the code is calling toString() on the value of the primary key. However the primary key column is in auto increment mode, and thus until the row has been commited to the database its value is NULL. => NULL.toString() = NPE.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
no NPE, the row is added.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NullPointerException
at com.sun.rowset.internal.CachedRowSetWriter.insertNewRow(CachedRowSetWriter.java:766)
at com.sun.rowset.internal.CachedRowSetWriter.writeData(CachedRowSetWriter.java:313)
at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:862)
at ilog.views.util.data.TestCachedRowSet.main(TestCachedRowSet.java:65)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
///// SOURCE CODE /////
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import javax.sql.rowset.CachedRowSet;
import com.sun.rowset.CachedRowSetImpl;
public class TestCachedRowSet {
final static String databaseURL = "jdbc:mysql://server/ilog_demos";
final static String user = "xxxx";
final static String passwd = "yyy";
final static String driverName = "com.mysql.jdbc.Driver";
final static String TABLE_NAME = "activities";
final static Timestamp newDateValue = new Timestamp(1000*(System.currentTimeMillis()/1000));
final static String newStringValue = "newStringValue";
// CJO 01/07
public static void main(String[] arg) throws SQLException, IOException, ClassNotFoundException {
// driver
Class.forName(driverName);
// first fresh up the database
Connection con = DriverManager.getConnection(databaseURL, user, passwd);
InputStream stream = TestCachedRowSet.class.getResourceAsStream("script.sql");
BufferedReader breader = new BufferedReader(new InputStreamReader(stream));
Statement statement = con.createStatement();
while (breader.ready()) {
statement.executeUpdate(breader.readLine());
}
stream.close();
con.close();
// prepare CachedRowSet
CachedRowSet rowSet = new CachedRowSetImpl();
rowSet.setPageSize(0);
con = DriverManager.getConnection(databaseURL, user, passwd);
rowSet.setCommand("select * from activities");
rowSet.setReadOnly(false);
rowSet.execute(con);
// the actual test
addRow(rowSet,
new Object[] {null, newStringValue, newDateValue, newDateValue, new Integer(200), null});
rowSet.acceptChanges();
}
private static void addRow(CachedRowSet rowSet, Object[] rowData) throws SQLException
{
rowSet.moveToInsertRow();
// this can happen we don't have any row data at all for the moment
if (rowData != null) {
for (int i = 0; i < rowData.length; i++) {
rowSet.updateObject(i+1, rowData[i]);
}
}
rowSet.insertRow();
rowSet.moveToCurrentRow();
}
}
// script.sql file to fill the table
DROP TABLE IF EXISTS activities;
CREATE TABLE activities (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), startTime TIMESTAMP NULL, endTime TIMESTAMP NULL, parentID INT, originalID VARCHAR(20)) ENGINE=InnoDB;
INSERT INTO activities VALUES(NULL, 'Project Summary', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '18-5-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), NULL, 'A-Root');
INSERT INTO activities SELECT NULL, 'Gather Requirements', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '21-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'Talk to customers', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '9-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.1' FROM activities as parent WHERE parent.originalID='A-1';
INSERT INTO activities SELECT NULL, 'Compile customer list', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '7-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.1.1' FROM activities as parent WHERE parent.originalID='A-1.1';
INSERT INTO activities SELECT NULL, 'Contact customers', STR_TO_DATE('7-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '9-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.1.2' FROM activities as parent WHERE parent.originalID='A-1.1';
INSERT INTO activities SELECT NULL, 'Write up requirements', STR_TO_DATE('7-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '21-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.2' FROM activities as parent WHERE parent.originalID='A-1';
INSERT INTO activities SELECT NULL, 'Marketing Specification', STR_TO_DATE('20-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '25-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-2' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'First Draft Specification', STR_TO_DATE('20-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '23-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-2.1' FROM activities as parent WHERE parent.originalID='A-2';
INSERT INTO activities SELECT NULL, 'Second Draft Specification', STR_TO_DATE('20-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '25-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-2.2' FROM activities as parent WHERE parent.originalID='A-2';
INSERT INTO activities SELECT NULL, 'Proof of Concept', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'Rough Design', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '30-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.1' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'CAD Layout', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '28-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.1.1' FROM activities as parent WHERE parent.originalID='A-3.1';
INSERT INTO activities SELECT NULL, 'Detailing', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '30-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.1.2' FROM activities as parent WHERE parent.originalID='A-3.1';
INSERT INTO activities SELECT NULL, 'Fabricate Prototype', STR_TO_DATE('3-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '10-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.2' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'Order Materials', STR_TO_DATE('3-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '4-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.2.1' FROM activities as parent WHERE parent.originalID='A-3.2';
INSERT INTO activities SELECT NULL, 'Machining', STR_TO_DATE('3-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '10-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.2.2' FROM activities as parent WHERE parent.originalID='A-3.2';
INSERT INTO activities SELECT NULL, 'Burn-in Testing', STR_TO_DATE('17-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '24-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.3' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'Prepare Demo', STR_TO_DATE('24-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.4' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'Design and Development', STR_TO_DATE('1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '18-5-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'Phase I Development', STR_TO_DATE('1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '19-1-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4.1' FROM activities as parent WHERE parent.originalID='A-4';
INSERT INTO activities SELECT NULL, 'Phase II Development', STR_TO_DATE('19-1-2001 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '23-2-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4.2' FROM activities as parent WHERE parent.originalID='A-4';
INSERT INTO activities SELECT NULL, 'Phase III Development', STR_TO_DATE('23-2-2001 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '18-5-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4.3' FROM activities as parent WHERE parent.originalID='A-4';
---------- END SOURCE ----------
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
If you:
-> have a CachedRowSet on table with an auto-increment primary key in a mySQL database.
-> you are inserting a new row
-> you are calling acceptChanges
you will get an NPE.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1/ in your mySQL database creates a database "ilog_demos"
2/ in your mySQL "test" database creates a table "activities"
3/ modify the attached .java to use your login/passwd to mysql and change "server" by your mySQL server.
4/ run the sample
you'll get a NPE because the code is calling toString() on the value of the primary key. However the primary key column is in auto increment mode, and thus until the row has been commited to the database its value is NULL. => NULL.toString() = NPE.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
no NPE, the row is added.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NullPointerException
at com.sun.rowset.internal.CachedRowSetWriter.insertNewRow(CachedRowSetWriter.java:766)
at com.sun.rowset.internal.CachedRowSetWriter.writeData(CachedRowSetWriter.java:313)
at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:862)
at ilog.views.util.data.TestCachedRowSet.main(TestCachedRowSet.java:65)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
///// SOURCE CODE /////
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import javax.sql.rowset.CachedRowSet;
import com.sun.rowset.CachedRowSetImpl;
public class TestCachedRowSet {
final static String databaseURL = "jdbc:mysql://server/ilog_demos";
final static String user = "xxxx";
final static String passwd = "yyy";
final static String driverName = "com.mysql.jdbc.Driver";
final static String TABLE_NAME = "activities";
final static Timestamp newDateValue = new Timestamp(1000*(System.currentTimeMillis()/1000));
final static String newStringValue = "newStringValue";
// CJO 01/07
public static void main(String[] arg) throws SQLException, IOException, ClassNotFoundException {
// driver
Class.forName(driverName);
// first fresh up the database
Connection con = DriverManager.getConnection(databaseURL, user, passwd);
InputStream stream = TestCachedRowSet.class.getResourceAsStream("script.sql");
BufferedReader breader = new BufferedReader(new InputStreamReader(stream));
Statement statement = con.createStatement();
while (breader.ready()) {
statement.executeUpdate(breader.readLine());
}
stream.close();
con.close();
// prepare CachedRowSet
CachedRowSet rowSet = new CachedRowSetImpl();
rowSet.setPageSize(0);
con = DriverManager.getConnection(databaseURL, user, passwd);
rowSet.setCommand("select * from activities");
rowSet.setReadOnly(false);
rowSet.execute(con);
// the actual test
addRow(rowSet,
new Object[] {null, newStringValue, newDateValue, newDateValue, new Integer(200), null});
rowSet.acceptChanges();
}
private static void addRow(CachedRowSet rowSet, Object[] rowData) throws SQLException
{
rowSet.moveToInsertRow();
// this can happen we don't have any row data at all for the moment
if (rowData != null) {
for (int i = 0; i < rowData.length; i++) {
rowSet.updateObject(i+1, rowData[i]);
}
}
rowSet.insertRow();
rowSet.moveToCurrentRow();
}
}
// script.sql file to fill the table
DROP TABLE IF EXISTS activities;
CREATE TABLE activities (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), startTime TIMESTAMP NULL, endTime TIMESTAMP NULL, parentID INT, originalID VARCHAR(20)) ENGINE=InnoDB;
INSERT INTO activities VALUES(NULL, 'Project Summary', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '18-5-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), NULL, 'A-Root');
INSERT INTO activities SELECT NULL, 'Gather Requirements', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '21-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'Talk to customers', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '9-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.1' FROM activities as parent WHERE parent.originalID='A-1';
INSERT INTO activities SELECT NULL, 'Compile customer list', STR_TO_DATE('6-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '7-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.1.1' FROM activities as parent WHERE parent.originalID='A-1.1';
INSERT INTO activities SELECT NULL, 'Contact customers', STR_TO_DATE('7-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '9-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.1.2' FROM activities as parent WHERE parent.originalID='A-1.1';
INSERT INTO activities SELECT NULL, 'Write up requirements', STR_TO_DATE('7-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '21-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-1.2' FROM activities as parent WHERE parent.originalID='A-1';
INSERT INTO activities SELECT NULL, 'Marketing Specification', STR_TO_DATE('20-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '25-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-2' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'First Draft Specification', STR_TO_DATE('20-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '23-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-2.1' FROM activities as parent WHERE parent.originalID='A-2';
INSERT INTO activities SELECT NULL, 'Second Draft Specification', STR_TO_DATE('20-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '25-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-2.2' FROM activities as parent WHERE parent.originalID='A-2';
INSERT INTO activities SELECT NULL, 'Proof of Concept', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'Rough Design', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '30-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.1' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'CAD Layout', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '28-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.1.1' FROM activities as parent WHERE parent.originalID='A-3.1';
INSERT INTO activities SELECT NULL, 'Detailing', STR_TO_DATE('27-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '30-10-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.1.2' FROM activities as parent WHERE parent.originalID='A-3.1';
INSERT INTO activities SELECT NULL, 'Fabricate Prototype', STR_TO_DATE('3-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '10-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.2' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'Order Materials', STR_TO_DATE('3-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '4-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.2.1' FROM activities as parent WHERE parent.originalID='A-3.2';
INSERT INTO activities SELECT NULL, 'Machining', STR_TO_DATE('3-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '10-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.2.2' FROM activities as parent WHERE parent.originalID='A-3.2';
INSERT INTO activities SELECT NULL, 'Burn-in Testing', STR_TO_DATE('17-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '24-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.3' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'Prepare Demo', STR_TO_DATE('24-11-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-3.4' FROM activities as parent WHERE parent.originalID='A-3';
INSERT INTO activities SELECT NULL, 'Design and Development', STR_TO_DATE('1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '18-5-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4' FROM activities as parent WHERE parent.originalID='A-Root';
INSERT INTO activities SELECT NULL, 'Phase I Development', STR_TO_DATE('1-12-2000 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '19-1-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4.1' FROM activities as parent WHERE parent.originalID='A-4';
INSERT INTO activities SELECT NULL, 'Phase II Development', STR_TO_DATE('19-1-2001 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '23-2-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4.2' FROM activities as parent WHERE parent.originalID='A-4';
INSERT INTO activities SELECT NULL, 'Phase III Development', STR_TO_DATE('23-2-2001 0:00:00', '%e-%c-%Y %H:%i:%S'),STR_TO_DATE( '18-5-2001 0:00:00', '%e-%c-%Y %H:%i:%S'), parent.id, 'A-4.3' FROM activities as parent WHERE parent.originalID='A-4';
---------- END SOURCE ----------