You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It seems that the intent of the wrapping code is to preserve the main attributes of the cause - at least SQLState does get copied... however, the error code is not copied and therefore it will be set to 0 in the new SQLTransientConnectionException.
This creates a peculiar situation when dealing with specific error handling routines: let's have an example of business logic for "detect invalid password used by a connection and recover from it by fetching new credentials". The focus here is on "detection", not the details of "recovery".
PostgreSQL: The situation can be determined from SQLState - which is present in the wrapped exception.
Oracle: The situation can be determined from ErrorCode - which is not present in the wrapped exception.
See example of a stack trace:
Caused by: java.sql.SQLTransientConnectionException: Connection is not available, request timed out after 10000ms (total=0, active=0, idle=0, waiting=0)
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:686)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:179)
....
Caused by: java.sql.SQLException: ORA-01017: invalid credential or not authorized; logon denied
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:709)
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:604)
Business logic can react to ErrorCode (1017 is Oracle's indication of connection having invalid credentials). But our code cannot be simply testing for SQLException::getErrorCode() - SQLTransientConnectionException is also SQLException.
And now we can see that the correct error code is only in the cause (while the correct SQLState is in both) => depending on whether or not the original SQLException got wrapped by Hikari (this depends on various scenarios), client needs to perform analysis of the entire exception chain to consistently figure out this is an invalid password situation...
While the above is of course possible, now every client needs to deal with additional dimensions of the problem:
understand behavior of different DB vendors (sure, we cannot do much about that)
process different depth of the exception chain (all exceptions are instances of SQLException) and find the original information
follow Hikari's implementation details (which may change in different releases) to stay on top of things
It is possible that this could solve also several other open issues...
What do you think?
The text was updated successfully, but these errors were encountered:
the-vj
changed the title
HikariPool::createTimeoutException - SQLTransientConnectionException does not copy ErrorCode of cause
HikariPool::createTimeoutException - SQLTransientConnectionException copies SQLState from cause, but not ErrorCode
Jul 29, 2024
The createTimeoutException() method of HikariPool class wraps SQLException like so:
HikariCP/src/main/java/com/zaxxer/hikari/pool/HikariPool.java
Lines 681 to 687 in 0a6ccdb
It seems that the intent of the wrapping code is to preserve the main attributes of the cause - at least SQLState does get copied... however, the error code is not copied and therefore it will be set to 0 in the new SQLTransientConnectionException.
This creates a peculiar situation when dealing with specific error handling routines: let's have an example of business logic for "detect invalid password used by a connection and recover from it by fetching new credentials". The focus here is on "detection", not the details of "recovery".
PostgreSQL: The situation can be determined from SQLState - which is present in the wrapped exception.
Oracle: The situation can be determined from ErrorCode - which is not present in the wrapped exception.
See example of a stack trace:
Business logic can react to ErrorCode (1017 is Oracle's indication of connection having invalid credentials). But our code cannot be simply testing for SQLException::getErrorCode() - SQLTransientConnectionException is also SQLException.
And now we can see that the correct error code is only in the cause (while the correct SQLState is in both) => depending on whether or not the original SQLException got wrapped by Hikari (this depends on various scenarios), client needs to perform analysis of the entire exception chain to consistently figure out this is an invalid password situation...
While the above is of course possible, now every client needs to deal with additional dimensions of the problem:
A solution to this would be elementary:
add one line to extract also the error code here:
HikariCP/src/main/java/com/zaxxer/hikari/pool/HikariPool.java
Line 682 in 0a6ccdb
and use a constructor where also the error code is passed here:
HikariCP/src/main/java/com/zaxxer/hikari/pool/HikariPool.java
Line 687 in 0a6ccdb
It is possible that this could solve also several other open issues...
What do you think?
The text was updated successfully, but these errors were encountered: