Open gberche-orange opened 2 years ago
Testing with the image: ghcr.io/vmware-tanzu/servicebinding/test/petclinic:20200922
proposed by default ...
... fails with apparently missing postgresql driver
022-07-20 13:23:11.902 WARN 1 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.bean
s.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor pa
rameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/j
dbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: org.postgresql.Driver
2022-07-20 13:23:11.919 INFO 1 --- [ main] org.ehcache.core.EhcacheManager : Cache 'vets' removed from EhcacheManager.
2022-07-20 13:23:11.933 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2022-07-20 13:23:12.004 INFO 1 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-07-20 13:23:12.013 ERROR 1 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: org.postgresql.Driver
Likely would need to rebuild the image with paketo buildpacks and a postgres profile ?
when adding the TRACE=true environment variable, other relevant traces get displayed but did not yet help me diagnose nor fix the issue
16:00:41.906 DEBUG o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties'
16:00:41.906 TRACE o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties'
16:00:41.906 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalCacheAdvisor'
16:00:41.906 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalJCacheAdvisor'
16:00:41.906 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
16:00:41.907 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.context.properties.BoundConfigurationProperties'
16:00:41.911 TRACE o.s.util.PropertyPlaceholderHelper : Resolved placeholder 'database'
16:00:41.916 TRACE o.s.util.PropertyPlaceholderHelper : Resolved placeholder 'database'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'configurationProperties'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'kubernetesServiceBindingSpecific'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'kubernetesServiceBindingFlattened'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'servletConfigInitParams'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'servletContextInitParams'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'systemProperties'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'systemEnvironment'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'random'
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'Config resource 'class path resource [application-postgres.properties]' via location 'optional:classpath:/''
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in PropertySource 'Config resource 'class path resource [application.properties]' via location 'optional:classpath:/''
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Could not find key 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic' in any property source
16:00:41.917 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'configurationProperties'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'kubernetesServiceBindingSpecific'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'kubernetesServiceBindingFlattened'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'servletConfigInitParams'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'servletContextInitParams'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'systemProperties'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'systemEnvironment'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'random'
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'Config resource 'class path resource [application-postgres.properties]' via location 'optional:classpath:/''
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Searching for key 'POSTGRES_URL' in PropertySource 'Config resource 'class path resource [application.properties]' via location 'optional:classpath:/''
16:00:41.918 TRACE ySourcesPropertyResolver$DefaultResolver : Could not find key 'POSTGRES_URL' in any property source
16:00:41.918 TRACE o.s.util.PropertyPlaceholderHelper : Resolved placeholder 'POSTGRES_URL:jdbc:postgresql://localhost/petclinic'
16:00:41.918 TRACE o.s.b.f.s.DefaultListableBeanFactory : Invoking afterPropertiesSet() on bean with name 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties'
16:00:41.925 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalCacheAdvisor'
16:00:41.925 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalJCacheAdvisor'
16:00:41.925 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
16:00:41.925 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalCacheAdvisor'
16:00:41.925 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalJCacheAdvisor'
16:00:41.925 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
16:00:41.928 TRACE o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties'
16:00:41.928 DEBUG o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from bean name 'dataSource' via factory method to bean named 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties'
16:00:41.940 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.context.properties.BoundConfigurationProperties'
16:00:41.976 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalCacheAdvisor'
16:00:41.976 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalJCacheAdvisor'
16:00:41.976 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
16:00:41.976 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalCacheAdvisor'
16:00:41.976 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.cache.config.internalJCacheAdvisor'
16:00:41.976 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
16:00:41.982 TRACE o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'dataSource'
16:00:41.983 TRACE o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties'
Finally, the root cause of my issue was that the K8S binding secret was missing the jdbc-url
and database
values.
Reading the documentation at
https://github.com/spring-cloud/spring-cloud-bindings#postgresql-rdbms, it was not clear to me whether database
was indeed required to get the spring.datasource.url
property defined.
Property | Value -- | -- spring.datasource.url | {jdbc-url} or if not set then jdbc:postgres://{host}:{port}/{database}. If a binding for {sslmode}, {sslrootcert}, or {options} are set, the value is appended as properties to the generated URL.
As a result, the spring.datasource.url=${POSTGRES_URL:jdbc:postgresql://localhost/petclinic}
from petclinic was always used
Defining an empty database
field into the K8S secret fixed the problem.
I think it would much help to add a debug trace in spring-cloud-bindings which lists the keys being inserted into the PropertySource, potentially omitting the values for security reasons.
@gberche-orange Thanks for reaching out. Glad you were able to resolve the issue.
I'm a little surprised that it required all of those properties to be set. I could possibly see it just filling in an empty value if it's not present. What's more surprising is that if they are not all set it just quietly skips the operation. I really believe that if you're going to require those fields you should at least pop up some sort of warning, or probably more appropriate fail.
That said, I'm pretty sure this is the code that enforces that requirement.
I'll drop a quick PR in to update the README to indicate it's all or none for the JDBC URLs.
Beyond that, I totally agree that we can do better with logging and debugging. I'll leave this issue open as a feature request to log the property keys at debug level & to log the length of the property value. That should give a clue about what's set but not leak the value. Does that seem reasonable?
Thanks @dmikusa-pivotal for looking into this issue. Your proposant of doc update and more friendly logging seems good to me !
As a springboot developer, in order to fix misconfigurations, I need to be able to troubleshoot when servicebinding fail to be injected
In this particular case, a K8S binding seems properly detected and injected, but the driver seems to not notice it and still be using the default datasource constructed from https://github.com/spring-projects/spring-petclinic/blob/3f8468432d86dcbd0cf4372e93e06d2f47aed26a/src/main/resources/application-postgres.properties#L1-L6
observed behavior
given a petclinic deployment from image
quay.io/service-binding/spring-petclinic:latest
with logging enabledand an injected secret by https://github.com/redhat-developer/service-binding-operator
I see the following debug traces showing a
binding-specific PropertySource from Kubernetes Service Bindings
was created, but still the driver trying to connect tolocalhost:5432
whereas the binding IP address is 10.69.0.34And the container exits immediately after springboot failed start, preventing manual inspection of the mounted bindings
After transiently adding the following command to the petclinic deployment
And ssh into the container and run the following commands
bash