Closed chas678 closed 9 months ago
At the time of writing, https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html lists 23.2, 21.x, and 19.x. In Spring Boot, we've used 21.x since 2.5 before upgrading to 23.3 in 3.2. 21.x is described as an "innovation release" but there's no statement about limited production support. 19.x is described as a "long term release". If we do anything here, I think we should drop back to 21.x.
At the same time - if falling back, the issue will be that Oracle 23C is not supported with the 21.x line of drivers (or at least nothing official on the Oracle site - driver 23.x is the only one mentioning Oracle 23C in any shape or form).
We already did preliminary testing of the latest SpringBoot 3.2.1 against Oracle 23C Free (this is officially stated compatibility on Oracle site) - Oracle still has not released the official production version of 23C, so maybe that is why they do not mention driver compatibility for it either.
Interestingly, we noticed the new 23.3 driver required minor refactoring in our code (related to an edge case dealing with legacy timestamp datatypes - the nature of the change indicated this was an issue that simply did not show up earlier, rather than a new driver bug... and once the change was implemented, our code remained compatible also with the older Oracle driver versions/database combinations without further changes.
Well, legacy time handling in java, a gift that keeps on giving...
Whichever way you decide to go, it seems that later, once Oracle releases 23C production, 23.x driver will be the one to use again, as their driver versioning usually follows the highest officially supported database version (+works also with all the older officially supported Oracle versions)...
We shall see.
Thanks for sharing your experience, @the-vj. We've decided to downgrade as we don't want the default to be something that Oracle does not recommend for production use. I think it's worth pointing out that the version in Boot's dependency management is only an opinion and can be overridden to meet individual needs. That's particularly true of JDBC drivers where we have very little dependency on the driver's code.
Downgrading is not that easy, several tests in OracleUcpDataSourcePoolMetadataTests
fail with 21.11.0.0
and 21.10.0.0
with:
org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection
at app//org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:84)
at app//org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:342)
at app//org.springframework.boot.jdbc.metadata.AbstractDataSourcePoolMetadataTests.getIdle(AbstractDataSourcePoolMetadataTests.java:75)
at java.base@17.0.9/java.lang.reflect.Method.invoke(Method.java:568)
at java.base@17.0.9/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base@17.0.9/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.sql.SQLException: Exception occurred while getting connection: oracle.ucp.UniversalConnectionPoolException: Universal Connection Pool internal error: java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null
at oracle.ucp.util.UCPErrorHandler.newSQLException(UCPErrorHandler.java:499)
at oracle.ucp.util.UCPErrorHandler.throwSQLException(UCPErrorHandler.java:176)
at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:1902)
at oracle.ucp.jdbc.PoolDataSourceImpl$3.build(PoolDataSourceImpl.java:4055)
at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:1825)
at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:1781)
at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:1767)
at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:160)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:118)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:81)
... 5 more
Caused by: oracle.ucp.UniversalConnectionPoolException: Universal Connection Pool internal error: java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null
at app//oracle.ucp.util.UCPErrorHandler.newUniversalConnectionPoolException(UCPErrorHandler.java:379)
at app//oracle.ucp.util.UCPErrorHandler.throwUniversalConnectionPoolException(UCPErrorHandler.java:69)
at app//oracle.ucp.util.UCPErrorHandler.throwUniversalConnectionPoolException(UCPErrorHandler.java:92)
at app//oracle.ucp.util.UCPErrorHandler.throwUniversalConnectionPoolException(UCPErrorHandler.java:165)
at app//oracle.ucp.common.Core.growBorrowed(Core.java:1316)
at app//oracle.ucp.common.UniversalConnectionPoolImpl.helpGrowBorrowed(UniversalConnectionPoolImpl.java:407)
at app//oracle.ucp.common.UniversalConnectionPoolImpl.borrowConnectionWithoutCountingRequests(UniversalConnectionPoolImpl.java:350)
at app//oracle.ucp.common.UniversalConnectionPoolImpl.borrowConnectionAndValidateHelper(UniversalConnectionPoolImpl.java:206)
at app//oracle.ucp.common.UniversalConnectionPoolImpl.borrowConnectionAndValidate(UniversalConnectionPoolImpl.java:166)
at app//oracle.ucp.common.UniversalConnectionPoolImpl.borrowConnection(UniversalConnectionPoolImpl.java:139)
at app//oracle.ucp.jdbc.JDBCConnectionPool.borrowConnection(JDBCConnectionPool.java:185)
at app//oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:1882)
... 12 more
Caused by: java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null
at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
at oracle.ucp.common.Topology.service(Topology.java:587)
at oracle.ucp.common.Topology.isServiceRegistered(Topology.java:627)
at oracle.ucp.common.Core.growBorrowed(Core.java:1288)
... 19 more
At this stage I'm not sure if our tests are not properly written or if we're running into a driver bug.
21.9.0.0
which is being used on our 3.1.x branch does not fail with the same tests.
could this be because you also upgraded your test setup use Oracle 23.3 FREE - i noticed a commit related to that somewhere...
That's not it, unfortunately, as those tests don't rely on a running Oracle instance.
I think it's the problem described in https://github.com/spring-projects/spring-boot/issues/35006 again. There's a bug in UCP which means that it fails when it's used on a JVM with assertions enabled. Unfortunately, that's often the case when running unit tests and I don't think we'd want our default version to require people to disable assertions when running tests that use UCP.
Looks like we need to drop back to 21.9.0.0 and then upgrade once there's a production-ready 23c release available.
/cc @Kuassim
Latest Spring Boot 3.2.1 declares a managed dependency of Oracle OJDBC BOM version here: https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-dependencies/build.gradle#L1101 and documents it here: https://docs.spring.io/spring-boot/docs/current/reference/html/dependency-versions.html
however - the Oracle docs say this is not for production use: https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html
"Note: The Oracle JDBC 23.3 drivers are supported for production use with BaseDB only. The 23.3 release drivers are not supported for production for any other database configuration."
Should pin the BOM version to one that is for production use.