Bug #88616 MySql connector crashes with NullPointerException when accessign a closed conn
Submitted: 23 Nov 2017 9:18 Modified: 27 Dec 2017 12:09
Reporter: magnus persson Email Updates:
Status: No Feedback Impact on me:
None 
Category:Connector / J Severity:S1 (Critical)
Version:8.0.8-dmr OS:Any
Assigned to: Assigned Account CPU Architecture:Any

[23 Nov 2017 9:18] magnus persson
Description:
When using the mysql connector I get a nullpointerexception if the connection was closed on the server side (using a timeout OR the kill-command).
The exception is propagated all the way to the user-code. If the exception would have been an IOException mysql would probably handle this correctly.
I used prepared statements and eclipselink. The problem is in the mysql-code.
This problem makes it difficult to use mysql with eclipselink in production as the server disconnects long-running connections (which makes my server stop working after 8 h).

Thu Nov 23 10:01:47 CET 2017 SELECT 1
Thu Nov 23 10:02:25 CET 2017  java.lang.NullPointerException
	at com.mysql.cj.mysqla.io.MysqlaProtocol.clearInputStream(MysqlaProtocol.java:804)
	at com.mysql.cj.mysqla.MysqlaSession.clearInputStream(MysqlaSession.java:509)
	at com.mysql.cj.jdbc.ServerPreparedStatement.serverPrepare(ServerPreparedStatement.java:1432)
	at com.mysql.cj.jdbc.ServerPreparedStatement.<init>(ServerPreparedStatement.java:344)
	at com.mysql.cj.jdbc.ServerPreparedStatement.getInstance(ServerPreparedStatement.java:308)
	at com.mysql.cj.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:1877)
	at com.mysql.cj.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:1821)
	at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.wasFailureCommunicationBased(DatabasePlatform.java:2948)
	at org.eclipse.persistence.platform.server.ServerPlatformBase.wasFailureCommunicationBased(ServerPlatformBase.java:548)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1641)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:680)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:564)
	at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2093)
	at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:600)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:270)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:256)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:327)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:722)
	at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2740)
	at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRows(ExpressionQueryMechanism.java:2693)
	at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:563)
	at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1221)
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:911)
	at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1180)
	at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:464)
	at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1268)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2979)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1892)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1874)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1839)
	at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
	at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:528)
	at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:402)
	at com.raybased.gwt.configtool.server.config.db.DBManager.lambda$getBlockType$9(DBManager.java:130)
	at com.raybased.gwt.configtool.server.config.db.SingleTenantDAO.doInSession(SingleTenantDAO.java:34)
	at com.raybased.gwt.configtool.server.config.db.DBManager.getBlockType(DBManager.java:130)
	at com.raybased.gwt.configtool.server.config.db.DBManager.main(DBManager.java:25)

Exception in thread "main" javax.persistence.PersistenceException: java.lang.NullPointerException
	at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:558)
	at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:402)
	at com.raybased.gwt.configtool.server.config.db.DBManager.lambda$getBlockType$9(DBManager.java:130)
	at com.raybased.gwt.configtool.server.config.db.SingleTenantDAO.doInSession(SingleTenantDAO.java:34)
	at com.raybased.gwt.configtool.server.config.db.DBManager.getBlockType(DBManager.java:130)
	at com.raybased.gwt.configtool.server.config.db.DBManager.main(DBManager.java:25)
Caused by: java.lang.NullPointerException

How to repeat:
Connect to the database, issue a query. On the server do show processlist; use kill <nr> to kill the connection. Do another query from the java-client. You will get the exception. show above.

Suggested fix:
Throw an IOException instead of nullpointerexception.
[23 Nov 2017 11:30] Chiranjeevi Battula
Hello magnus persson,

Thank you for the bug report.
I tried to reproduce the issue at my end using MySQL Connector / J 8.0.8 dmr and MySQL 5.7.20 but not seeing any issues.
Could you please provide repeatable test case (exact steps, database/create table statements, full stack trace, sample code etc. - please make it as private if you prefer) to confirm this issue at our end?

Thanks,
Chiranjeevi.
[23 Nov 2017 11:36] Chiranjeevi Battula
1) Frist run with connection kills
run:
Connecting to a database...
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Thu Nov 23 15:54:58 IST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Connected database successfully...
java.sql.SQLException: Can not read response from server. Expected to read 4,505 bytes, read 2,318 bytes before connection was unexpectedly lost.
Connection Closed!
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:121)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:116)
	at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1488)
	at mysqlbugs.Bug_88616.main(Bug_88616.java:42)
BUILD SUCCESSFUL (total time: 5 seconds)

2) Second run

run:
Connecting to a database...
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Thu Nov 23 15:55:45 IST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Connected database successfully...
select query via msyql connector return when max_execution_time is set
Connection Closed!
BUILD SUCCESSFUL (total time: 10 seconds)
[27 Nov 2017 6:19] magnus persson
Did you do this in your test:
for(i=0;i<10000000;i++) {
 do_a_query_wihout_a_connectionpool()
}

while the code above runs, login in the mysql:
show full processlist;  
kill <the connection used above>

The result for me is a nullpointerexcpetion in the code above.
[27 Nov 2017 12:09] Chiranjeevi Battula
Hello magnus persson,

Thank you for your feedback.
Could you please provide repeatable test case (exact steps, sample code etc. - please make it as private if you prefer) to confirm this issue at our end?

Thanks,
Chiranjeevi.
[28 Dec 2017 1: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".