From cddc6f48f30b4e80ed19bc05561c71c4112f3fdf Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Wed, 10 Jan 2024 19:35:39 -0800 Subject: [PATCH 1/5] Upgrades Oracle database libraries to version 21.9.0.0. Adds test under datasource-ucp CDI integration. Signed-off-by: Laird Nelson --- dependencies/pom.xml | 3 +- integrations/cdi/datasource-ucp/pom.xml | 2 +- .../TestUcpConnectionStateResetBehavior.java | 129 ++++++++++++++++++ .../src/test/logging.properties | 10 +- 4 files changed, 138 insertions(+), 6 deletions(-) create mode 100644 integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpConnectionStateResetBehavior.java diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 5d6b97b2f12..bd449a25c43 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -127,7 +127,8 @@ 5.12.0 4.1.100.Final 3.34.0 - 21.4.0.0 + 21.9.0.0 + ${version.lib.ojdbc} 3.4.0 diff --git a/integrations/cdi/datasource-ucp/pom.xml b/integrations/cdi/datasource-ucp/pom.xml index ba26dc04af6..9fdcad6795d 100644 --- a/integrations/cdi/datasource-ucp/pom.xml +++ b/integrations/cdi/datasource-ucp/pom.xml @@ -42,7 +42,7 @@ com.oracle.database.jdbc - ojdbc8-production + ojdbc11-production pom compile diff --git a/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpConnectionStateResetBehavior.java b/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpConnectionStateResetBehavior.java new file mode 100644 index 00000000000..89643d3625c --- /dev/null +++ b/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpConnectionStateResetBehavior.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.helidon.integrations.datasource.ucp.cdi; + +import java.sql.Connection; +import java.sql.SQLException; + +import oracle.ucp.jdbc.ConnectionInitializationCallback; +import oracle.ucp.jdbc.PoolDataSource; +import oracle.ucp.jdbc.PoolDataSourceFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * A test class that shows that the Universal Connection Pool does not reset connection state when a borrowed connection + * is returned. + */ +class TestUcpConnectionStateResetBehavior { + + private PoolDataSource pds; + + private TestUcpConnectionStateResetBehavior() { + super(); + } + + @BeforeEach + void initializeDataSource() throws SQLException { + this.pds = PoolDataSourceFactory.getPoolDataSource(); + + // We register this callback, knowing that UCP will ignore it, despite documentation that does not say so. It + // ignores it because the connection factory (DataSource) we use is H2, not Oracle. In case UCP fixes this + // shortcoming we want to know about it. + this.pds.registerConnectionInitializationCallback(new FailingCallback()); + assertThat(this.pds.getConnectionInitializationCallback(), is(instanceOf(FailingCallback.class))); + + this.pds.setConnectionFactoryClassName("org.h2.jdbcx.JdbcDataSource"); + this.pds.setURL("jdbc:h2:mem:" + this.getClass().getSimpleName()); + this.pds.setUser("sa"); + this.pds.setPassword(""); + + this.pds.setInitialPoolSize(2); + this.pds.setMinPoolSize(2); + this.pds.setMaxPoolSize(8); // actually the default but just being explicit + } + + @AfterEach + void destroyDataSource() throws SQLException { + this.pds.unregisterConnectionInitializationCallback(); + } + + @Test + void testUCPErroneouslyDoesNotResetConnectionStateOnReturn() throws SQLException { + + // The connection pool has two connections in it. + + // Borrow connection zero. + Connection c0 = this.pds.getConnection(); + assertThat(c0.getAutoCommit(), is(true)); // we never set it anywhere; default value is true + + // Borrow connection one. + Connection c1 = this.pds.getConnection(); + assertThat(c1.getAutoCommit(), is(true)); // we never set it anywhere; default value is true + + // There are now no more connections available in the pool. + assertThat(this.pds.getAvailableConnectionsCount(), is(0)); + + // Change the state of connection one. + c1.setAutoCommit(false); + + // Return it to the pool. + c1.close(); + + // There is now exactly one connection available in the pool (the one we just returned). + assertThat(this.pds.getAvailableConnectionsCount(), is(1)); + + // Borrow connection two. (It will be connection one.) + Connection c2 = this.pds.getConnection(); + + // There are now no more connections available in the pool. + assertThat(this.pds.getAvailableConnectionsCount(), is(0)); + + // Note that the state of connection two includes the state of connection one. Oops. The pool really should + // reset at least this portion of the connection state, but it does not. + assertThat(c2.getAutoCommit(), is(false)); + + // Return it. + c2.close(); + + // Return connection zero. + c0.close(); + + // No more borrowed connections are extant. + assertThat(this.pds.getAvailableConnectionsCount(), is(2)); + } + + private static class FailingCallback implements ConnectionInitializationCallback { + + private FailingCallback() { + super(); + } + + @Override + public void initialize(Connection connection) throws SQLException { + // ConnectionInitializationCallbacks are ignored by the UCP unless you are using an Oracle JDBC driver. + fail(); + } + + } + +} diff --git a/integrations/cdi/datasource-ucp/src/test/logging.properties b/integrations/cdi/datasource-ucp/src/test/logging.properties index 564de3a7974..ca12e1b4ff4 100644 --- a/integrations/cdi/datasource-ucp/src/test/logging.properties +++ b/integrations/cdi/datasource-ucp/src/test/logging.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, 2022 Oracle and/or its affiliates. +# Copyright (c) 2019, 2024 Oracle and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # -.level=INFO -handlers=io.helidon.logging.jul.HelidonConsoleHandler -oracle.ucp.level=FINE +.level = INFO +# handlers = io.helidon.logging.jul.HelidonConsoleHandler +handlers = java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.level = FINEST +oracle.ucp.level = FINEST From ed0fba33cb6e28c5c3362d0561c16f1ae1652cf2 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Thu, 11 Jan 2024 09:47:29 -0800 Subject: [PATCH 2/5] Squashable commit; uses ojdbc11 instead of ojdbc8 throughout the codebase Signed-off-by: Laird Nelson --- dependencies/pom.xml | 2 +- examples/employee-app/pom.xml | 2 +- examples/integrations/cdi/datasource-hikaricp/pom.xml | 2 +- examples/integrations/oci/atp-cdi/pom.xml | 2 +- examples/integrations/oci/atp/pom.xml | 2 +- integrations/db/ojdbc/pom.xml | 4 ++-- messaging/connectors/aq/pom.xml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index bd449a25c43..62e8c134bca 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -1380,7 +1380,7 @@ com.oracle.database.jdbc ojdbc-bom - ${version.lib.ojdbc8} + ${version.lib.ojdbc} pom import diff --git a/examples/employee-app/pom.xml b/examples/employee-app/pom.xml index f239119493a..0b17c6968ba 100644 --- a/examples/employee-app/pom.xml +++ b/examples/employee-app/pom.xml @@ -39,7 +39,7 @@ com.oracle.database.jdbc - ojdbc8-production + ojdbc11-production pom diff --git a/examples/integrations/cdi/datasource-hikaricp/pom.xml b/examples/integrations/cdi/datasource-hikaricp/pom.xml index 7be2f532bfb..01b48eb0e68 100644 --- a/examples/integrations/cdi/datasource-hikaricp/pom.xml +++ b/examples/integrations/cdi/datasource-hikaricp/pom.xml @@ -52,7 +52,7 @@ com.oracle.database.jdbc - ojdbc8-production + ojdbc11-production pom runtime diff --git a/examples/integrations/oci/atp-cdi/pom.xml b/examples/integrations/oci/atp-cdi/pom.xml index 63e6b84a2d2..75ca6aac3bb 100644 --- a/examples/integrations/oci/atp-cdi/pom.xml +++ b/examples/integrations/oci/atp-cdi/pom.xml @@ -44,7 +44,7 @@ com.oracle.database.jdbc - ojdbc8-production + ojdbc11-production pom diff --git a/examples/integrations/oci/atp/pom.xml b/examples/integrations/oci/atp/pom.xml index bded371306e..4986b070cef 100644 --- a/examples/integrations/oci/atp/pom.xml +++ b/examples/integrations/oci/atp/pom.xml @@ -52,7 +52,7 @@ com.oracle.database.jdbc - ojdbc8-production + ojdbc11-production pom diff --git a/integrations/db/ojdbc/pom.xml b/integrations/db/ojdbc/pom.xml index d1ec868637e..59410db95a3 100644 --- a/integrations/db/ojdbc/pom.xml +++ b/integrations/db/ojdbc/pom.xml @@ -41,7 +41,7 @@ com.oracle.database.jdbc - ojdbc8-production + ojdbc11-production pom @@ -59,7 +59,7 @@ com.oracle.database.xml xmlparserv2_sans_jaxp_services - ${version.lib.ojdbc8} + ${version.lib.ojdbc} runtime diff --git a/messaging/connectors/aq/pom.xml b/messaging/connectors/aq/pom.xml index d2655e7c52a..7702547c534 100644 --- a/messaging/connectors/aq/pom.xml +++ b/messaging/connectors/aq/pom.xml @@ -63,7 +63,7 @@ com.oracle.database.jdbc - ojdbc8-production + ojdbc11-production pom From 7d28de4c32669e45c9d96aa5145e0e926fbb5155 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Wed, 14 Feb 2024 13:46:23 -0800 Subject: [PATCH 3/5] Squashable commit; upgrades ojdbc version to 21.11.0.0 Signed-off-by: Laird Nelson --- dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 62e8c134bca..c91ed4ba83b 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -127,7 +127,7 @@ 5.12.0 4.1.100.Final 3.34.0 - 21.9.0.0 + 21.11.0.0 ${version.lib.ojdbc} 3.4.0 From 662a9e5fdfe5e7361b8e9acfec027a3c1cefad47 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Wed, 14 Feb 2024 17:51:39 -0800 Subject: [PATCH 4/5] Squashable commit; upgrades the ojdbc/ucp version to 21.9.0.0 which is the highest version that can be used that does not throw NullPointerExceptions in certain cases; adds test to catch this problem Signed-off-by: Laird Nelson --- dependencies/pom.xml | 6 +- integrations/cdi/datasource-ucp/pom.xml | 5 -- .../datasource/ucp/cdi/TestUcpAndH2.java | 72 +++++++++++++++++++ 3 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java diff --git a/dependencies/pom.xml b/dependencies/pom.xml index c91ed4ba83b..dcd117ad218 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -127,7 +127,11 @@ 5.12.0 4.1.100.Final 3.34.0 - 21.11.0.0 + + 21.9.0.0 ${version.lib.ojdbc} 3.4.0 diff --git a/integrations/cdi/datasource-ucp/pom.xml b/integrations/cdi/datasource-ucp/pom.xml index 9fdcad6795d..3dcb1ac1b68 100644 --- a/integrations/cdi/datasource-ucp/pom.xml +++ b/integrations/cdi/datasource-ucp/pom.xml @@ -46,11 +46,6 @@ pom compile - - com.oracle.database.jdbc - ucp - compile - org.eclipse.microprofile.config microprofile-config-api diff --git a/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java b/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java new file mode 100644 index 00000000000..c73e3aeb774 --- /dev/null +++ b/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.helidon.integrations.datasource.ucp.cdi; + +import java.sql.Connection; +import java.sql.SQLException; + +import oracle.ucp.UniversalConnectionPoolException; +import oracle.ucp.admin.UniversalConnectionPoolManager; +import oracle.ucp.admin.UniversalConnectionPoolManagerImpl; +import oracle.ucp.jdbc.PoolDataSource; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static oracle.ucp.jdbc.PoolDataSourceFactory.getPoolDataSource; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.not; + +class TestUcpAndH2 { + + TestUcpAndH2() { + super(); + } + + @AfterEach + void destroyPools() throws SQLException, UniversalConnectionPoolException { + UniversalConnectionPoolManager ucpManager = UniversalConnectionPoolManagerImpl.getUniversalConnectionPoolManager(); + for (String n : ucpManager.getConnectionPoolNames()) { + ucpManager.destroyConnectionPool(n); + } + } + + /** + * Ensures we don't accidentally upgrade to a version of the Universal Connection Pool that throws {@link + * NullPointerException}s when no {@code serviceName} is set on a {@link PoolDataSource}. + * + *

The only way to set a service name on a {@link PoolDataSource} is, when the {@link PoolDataSource} is actually + * a {@link PoolDataSourceImpl}, by invoking its {@code private void setServiceName(String)} method via + * reflection.

+ * + * @exception SQLException if a database access error occurs + * + * @exception NullPointerException if the Universal Connection Pool version in effect cannot handle unset service + * names + */ + @Test + void testUcpAndH2Canary() throws SQLException { + PoolDataSource pds = getPoolDataSource(); + pds.setConnectionFactoryClassName("org.h2.jdbcx.JdbcDataSource"); + pds.setURL("jdbc:h2:mem:test"); + pds.setUser("sa"); + pds.setPassword(""); + try (Connection c = pds.getConnection()) { // Throws NullPointerException in versions 21.10.0.0 and 21.11.0.0 and possibly others + assertThat(c, not(nullValue())); + } + } + +} From 3bf8d6f5c52f2f93af9b48206f6ff2c4395d2512 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Wed, 14 Feb 2024 19:31:11 -0800 Subject: [PATCH 5/5] Squashable commit; style fix Signed-off-by: Laird Nelson --- .../helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java b/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java index c73e3aeb774..92729237f63 100644 --- a/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java +++ b/integrations/cdi/datasource-ucp/src/test/java/io/helidon/integrations/datasource/ucp/cdi/TestUcpAndH2.java @@ -26,9 +26,9 @@ import org.junit.jupiter.api.Test; import static oracle.ucp.jdbc.PoolDataSourceFactory.getPoolDataSource; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.CoreMatchers.not; class TestUcpAndH2 {