Spring Boot gets exception when using oracle ucp datasource and actuator.

This is because that "isWrapperFor" call specifically throws an exception if the class it's checking is not an interface. The HikariDataSource.class class is not an interface, so it explodes.

I am on spring boot 2.3.3.RELEASE, and using version 12.1.0.2.0 of oracle UCP, and it looks like the DataSourceUnwrapper for a hikaridatasource causes the following exception to be thrown when the underlying datasource is an oracle ucp datasource.

java.sql.SQLException: The argument is not an interface
    at oracle.ucp.util.UCPErrorHandler.newSQLException(UCPErrorHandler.java:479) ~[com.oracle.ucp-12.1.0.2.0.jar:12.1.0.2.0]
    at oracle.ucp.util.UCPErrorHandler.throwSQLException(UCPErrorHandler.java:154) ~[com.oracle.ucp-12.1.0.2.0.jar:12.1.0.2.0]
    at oracle.ucp.jdbc.PoolDataSourceImpl.isWrapperFor(PoolDataSourceImpl.java:3237) ~[com.oracle.ucp-12.1.0.2.0.jar:12.1.0.2.0]
    at org.springframework.boot.jdbc.DataSourceUnwrapper.safeUnwrap(DataSourceUnwrapper.java:77) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.jdbc.DataSourceUnwrapper.unwrap(DataSourceUnwrapper.java:56) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration.lambda$hikariPoolDataSourceMetadataProvider$0(DataSourcePoolMetadataProvidersConfiguration.java:66) ~[spring-boot-autoconfigure-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.jdbc.metadata.CompositeDataSourcePoolMetadataProvider.getDataSourcePoolMetadata(CompositeDataSourcePoolMetadataProvider.java:50) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.actuate.metrics.jdbc.DataSourcePoolMetrics$CachingDataSourcePoolMetadataProvider.getDataSourcePoolMetadata(DataSourcePoolMetrics.java:113) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.actuate.metrics.jdbc.DataSourcePoolMetrics.bindTo(DataSourcePoolMetrics.java:68) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration.bindDataSourceToRegistry(DataSourcePoolMetricsAutoConfiguration.java:82) ~[spring-boot-actuator-autoconfigure-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration.lambda$bindDataSourcesToRegistry$0(DataSourcePoolMetricsAutoConfiguration.java:75) ~[spring-boot-actuator-autoconfigure-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[?:1.8.0_121]
    at org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration.bindDataSourcesToRegistry(DataSourcePoolMetricsAutoConfiguration.java:74) ~[spring-boot-actuator-autoconfigure-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_121]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_121]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_121]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:755) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]

Comment From: wilkinsona

Thanks for the report. safeUnwrap should catch and swallow any exception thrown by isWrapperFor(Class<?>):

https://github.com/spring-projects/spring-boot/blob/602e62998eb2254517d695fa67246399ba40b8bf/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceUnwrapper.java#L76-L83

It's not clear to me at the moment where you're seeing the exception. Is this a purely cosmetic problem as it's appearing in the logs or is it have an unwanted effect on functionality?

Comment From: nwertzberger

You know what? it is cosmetic... Sorry!

Comment From: wilkinsona

Thanks for the clarification. It may still be worth fixing even if it's only cosmetic. We'd need to be careful that we don't break anything with other wrappers that are less strict about the interface requirement.