From 2d2cbff504ae80d82ba628115f972cd40604616b Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 24 Sep 2021 10:10:15 +0100 Subject: [PATCH] Avoid NoSuchMethodError from UCP's PoolDataSource.getPassword() While still present and marked as deprecated, the getPassword() method on UCP's PoolDataSource has been implemented to throw a NoSuchMethodError making it useless for our purposes. This commit updates DataSourceBuilder to avoid using the getter. This means that a password must now be provided when trying to derive a new DataSource from an existing PoolDataSource. Closes gh-28127 --- .../boot/jdbc/DataSourceBuilder.java | 12 +-------- .../boot/jdbc/DataSourceBuilderTests.java | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java index c2ae248fc7..d6a613115d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java @@ -646,17 +646,7 @@ public final class DataSourceBuilder { add(DataSourceProperty.DRIVER_CLASS_NAME, PoolDataSource::getConnectionFactoryClassName, PoolDataSource::setConnectionFactoryClassName); add(DataSourceProperty.USERNAME, PoolDataSource::getUser, PoolDataSource::setUser); - add(DataSourceProperty.PASSWORD, passwordGetter(), PoolDataSource::setPassword); - } - - @SuppressWarnings("deprecation") - static Getter passwordGetter() { - try { - return (dataSource) -> dataSource.getPassword(); - } - catch (NoSuchMethodError ex) { - return null; - } + add(DataSourceProperty.PASSWORD, null, PoolDataSource::setPassword); } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java index d891245791..345c58e1ae 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java @@ -30,6 +30,7 @@ import com.microsoft.sqlserver.jdbc.SQLServerDataSource; import com.zaxxer.hikari.HikariDataSource; import oracle.jdbc.internal.OpaqueString; import oracle.jdbc.pool.OracleDataSource; +import oracle.ucp.jdbc.PoolDataSource; import oracle.ucp.jdbc.PoolDataSourceImpl; import org.apache.commons.dbcp2.BasicDataSource; import org.h2.Driver; @@ -293,6 +294,16 @@ class DataSourceBuilderTests { .isThrownBy(() -> DataSourceBuilder.derivedFrom(dataSource).url("example.org").build()); } + @Test + void buildWhenDerivedFromOracleUcpWithPasswordNotSetThrowsException() throws Exception { + PoolDataSource dataSource = new PoolDataSourceImpl(); + dataSource.setUser("test"); + dataSource.setPassword("secret"); + dataSource.setURL("example.com"); + assertThatExceptionOfType(UnsupportedDataSourcePropertyException.class) + .isThrownBy(() -> DataSourceBuilder.derivedFrom(dataSource).url("example.org").build()); + } + @Test void buildWhenDerivedFromOracleDataSourceWithPasswordSetReturnsDataSource() throws Exception { oracle.jdbc.datasource.impl.OracleDataSource dataSource = new oracle.jdbc.datasource.impl.OracleDataSource(); @@ -308,6 +319,20 @@ class DataSourceBuilderTests { assertThat(built.getURL()).isEqualTo("example.com"); } + @Test + void buildWhenDerivedFromOracleUcpWithPasswordSetReturnsDataSource() throws SQLException { + PoolDataSource dataSource = new PoolDataSourceImpl(); + dataSource.setUser("test"); + dataSource.setPassword("secret"); + dataSource.setURL("example.com"); + DataSourceBuilder builder = DataSourceBuilder.derivedFrom(dataSource); + PoolDataSource built = (PoolDataSource) builder.username("test2").password("secret2").build(); + assertThat(built.getUser()).isEqualTo("test2"); + assertThat(built).extracting("password").extracting((opaque) -> ((oracle.ucp.util.OpaqueString) opaque).get()) + .isEqualTo("secret2"); + assertThat(built.getURL()).isEqualTo("example.com"); + } + @Test void buildWhenDerivedFromEmbeddedDatabase() { EmbeddedDatabase database = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build();