Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullPointerException in private static class SetNetworkTimeoutCommand - class FBConnection file ./src/main/org/firebirdsql/jdbc/FBConnection.java when using HikariCP [JDBC631] #661

Closed
firebird-automations opened this issue Aug 11, 2020 · 9 comments

Comments

@firebird-automations
Copy link

Submitted by: Honza Hubeny (hubeny)

I use Hikari CP together with Jaybird 3. I try to upgrade Jaybird lib to 4. However it is not possible now becouse of following error:

Pool init with max 2 idle connections and 30 seconds timeout
.....
HikariConfig config = new HikariConfig();
config.setAutoCommit(false);
config.setMinimumIdle(2);
config.setMaximumPoolSize(100);
config.setIdleTimeout(30000);
connectionPool = new HikariDataSource(config);
......

When the hikari pool has more than 2 idle connections for more than 30 second then the class

com.zaxxer.hikari.pool.PoolBase

calls method

void quietlyCloseConnection(final Connection connection, final String closureReason)
{
if (connection != null) {
try {
LOGGER.debug("{} - Closing connection {}: {}", poolName, connection, closureReason);
try {
setNetworkTimeout(connection, SECONDS.toMillis(15));
}
finally {
connection.close(); // continue with the close even if setNetworkTimeout() throws
}
}
catch (Throwable e) {
LOGGER.debug("{} - Closing connection {} failed", poolName, connection, e);
}
}
}

here is first called asynchronous setNetworkTimeout(connection, SECONDS.toMillis(15));
the final product of this call is call of method setNetworkTImeout in Jaybird class FBConnection. After that the connection is immediately closed.
However, the jaybird SetNetworkTimeoutCommand is executed in another thread and in the run() method of the private static SetNetworkTimeoutCommand is call to
connection.getFbDatabase().setNetworkTimeout(timeoutMillis);

Unfortunatelly the call connection.getFbDatabase() returns null pointer (connection is already closed by the hikari CP).

The content of FBConnection with the source of error follows

@OverRide
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
SQLPermission sqlPermission = new SQLPermission(PERMISSION_SET_NETWORK_TIMEOUT);
securityManager.checkPermission(sqlPermission);
}
if (executor == null) {
throw FbExceptionBuilder
.forException(JaybirdErrorCodes.jb_invalidExecutor)
.toFlatSQLException();
}
if (milliseconds < 0) {
throw FbExceptionBuilder
.forException(JaybirdErrorCodes.jb_invalidTimeout)
.toFlatSQLException();
}
checkValidity();

    executor\.execute\(new SetNetworkTimeoutCommand\(this, milliseconds\)\);
\}

private static class SetNetworkTimeoutCommand implements Runnable \{

    private final WeakReference<FBConnection\> connectionReference;
    private final int timeoutMillis;

    SetNetworkTimeoutCommand\(FBConnection connection, int timeoutMillis\) \{
        connectionReference = new WeakReference<\>\(connection\);
        this\.timeoutMillis = timeoutMillis;
    \}

    @Override
    public void run\(\) \{
        FBConnection connection = connectionReference\.get\(\);
        if \(connection \!= null\) \{
            try \{
                connection\.getFbDatabase\(\)\.setNetworkTimeout\(timeoutMillis\);
            \} catch \(SQLException e\) \{
                log\.error\("Exception during asynchronous handling of setNetworkTimeout", e\);
            \}
        \}
    \}
\}

Commits: 2ba0167 c2a4695

@firebird-automations
Copy link
Author

Commented by: @mrotteveel

Thanks for reporting.
It looks like I misinterpreted the JDBC specification regarding the use of the executor (and I'm not the only on that did that, eg see http://bugs.mysql.com/bug.php?id=75615). Based on this discussion on jdbc-spec-discuss http://mail.openjdk.java.net/pipermail/jdbc-spec-discuss/2017-November/000236.html (which I read and forgot long before implementing this...), the executor should not be used in this case.

I will fix this in 4.0.1.

Be aware that the exception is caught and logged, so although it will produce annoying logging, the driver will function.

@firebird-automations
Copy link
Author

Modified by: @mrotteveel

environment: Linux Ubuntu 20.04 LTS. Bug finded when using Hikari CP 2.4.13 together with latest stable Jaybird 4.0. Both libraries compiled for Java 7. => Linux Ubuntu 20.04 LTS. Bug found when using Hikari CP 2.4.13 together with latest stable Jaybird 4.0. Both libraries compiled for Java 7.

@firebird-automations
Copy link
Author

Modified by: @mrotteveel

Fix Version: Jaybird 4.0.1 [ 10921 ]

@firebird-automations
Copy link
Author

Modified by: @mrotteveel

Fix Version: Jaybird 5 [ 10871 ]

@firebird-automations
Copy link
Author

Commented by: @mrotteveel

Implemented fix. I will see if I can release Jaybird 4.0.1 this week.

@firebird-automations
Copy link
Author

Modified by: @mrotteveel

status: Open [ 1 ] => Resolved [ 5 ]

resolution: Fixed [ 1 ]

@firebird-automations
Copy link
Author

Commented by: Honza Hubeny (hubeny)

Thank you for the quick fix. We will wait for the new version, the exception is showed to the user in our product, therefore I reported it.

@firebird-automations
Copy link
Author

Commented by: @mrotteveel

Jaybird 4.0.1 has been released, see https://firebirdsql.org/en/news/jaybird-4-0-1-released/

@firebird-automations
Copy link
Author

Modified by: @mrotteveel

status: Resolved [ 5 ] => Closed [ 6 ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment