Error connecting to database Spring boot

2.8k views Asked by At

Helo I have been trying to connect to a database with Spring Boot for a while and I keep getting the error:

java.sql.SQLException: The url cannot be null

I am not sure what is it that I am doing wrong. The reason I am trying to get the configuration like this is because I want to use the encoded password for the database.

This is what my files look like:

DataConfig.java

@Configuration
public class DataConfig {

    @Autowired
    private Environment env;

    @Configuration
    @Profile(value = "dev")
    public class DevPlaceHolderConfig {

        @Bean
        DataSource dataSource() {

            return DataSourceBuilder
                    .create()
                    .username(env.getProperty("spring.datasource.username"))
                    .password(env.getProperty("spring.datasource.password"))
                    .url(env.getProperty("spring.datasource.url"))
                    .driverClassName(env.getProperty("spring.datasource.driver-class-name"))
                    .build();
        }
    }

    @Configuration
    @Profile(value = "prod")
    public class ProdPlaceHolderConfig {
        @Bean
        DataSource dataSource() {

            return DataSourceBuilder
                    .create()
                    .username(env.getProperty("spring.datasource.username"))
                    .password(env.getProperty("spring.datasource.password"))
                    .url(env.getProperty("spring.datasource.url"))
                    .driverClassName(env.getProperty("spring.datasource.driver-class-name"))
                    .build();
        }
    }
}

EncryptorConfig.java

@Configuration
public class EncryptorConfig {

    @Bean
    public EnvironmentStringPBEConfig environmentVariablesConfiguration() {
        EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setPasswordEnvName("APP_ENCRYPTION_PASSWORD");
        return config;
    }

    @Bean
    public PooledPBEStringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setConfig(environmentVariablesConfiguration());
        return encryptor;
    }
}

application.yml

spring:
  profiles:
    active: prod
  output:
    ansi:
      enabled: always
---
spring:
  profiles: dev
  application:
    name: App-Dev
  datasource:
    url: jdbc:mysql://localhost:3306/database?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver 
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
server:
  port: 8080

---

spring:
  profiles: prod
  application:
    name: App-Prod
  datasource:
    url: jdbc:mysql://localhost:3306/database?useSSL=false
    username: root
    password: ENC(/98CfxmsjKBW5oZsLkLlmw==)
    driver-class-name: com.mysql.jdbc.Driver 
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
server:
  port: 3000

Here is the stack trace

2017-09-04 09:20:02.476  INFO 18128 --- [           main] com.vir.VirBackendApplication            : The following profiles are active: prod
2017-09-04 09:20:02.536  INFO 18128 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1ebd319f: startup date [Mon Sep 04 09:20:02 EDT 2017]; root of context hierarchy
2017-09-04 09:20:03.479  INFO 18128 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'dataSource' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.vir.config.DataConfig$ProdPlaceHolderConfig; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/vir/config/DataConfig$ProdPlaceHolderConfig.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.vir.config.EncryptorConfig$ProdPlaceHolderConfig; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/vir/config/EncryptorConfig$ProdPlaceHolderConfig.class]]
2017-09-04 09:20:03.898  INFO 18128 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2017-09-04 09:20:04.112  INFO 18128 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$55ffc8cc] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-09-04 09:20:04.421  INFO 18128 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 5000 (http)
2017-09-04 09:20:04.431  INFO 18128 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2017-09-04 09:20:04.432  INFO 18128 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.16
2017-09-04 09:20:04.589  INFO 18128 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-09-04 09:20:04.589  INFO 18128 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2055 ms
2017-09-04 09:20:04.764  INFO 18128 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-09-04 09:20:04.769  INFO 18128 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-09-04 09:20:04.769  INFO 18128 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-09-04 09:20:04.769  INFO 18128 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-09-04 09:20:04.769  INFO 18128 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-09-04 09:20:04.817  INFO 18128 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.0.12.Final}
2017-09-04 09:20:04.820  INFO 18128 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2017-09-04 09:20:04.821  INFO 18128 --- [           main] org.hibernate.cfg.Environment            : HHH000021: Bytecode provider name : javassist
2017-09-04 09:20:04.967  WARN 18128 --- [           main] o.a.tomcat.jdbc.pool.PooledConnection    : Not loading a JDBC driver as driverClassName property is null.
2017-09-04 09:20:04.978 ERROR 18128 --- [           main] o.a.tomcat.jdbc.pool.ConnectionPool      : Unable to create initial connections of pool.

java.sql.SQLException: The url cannot be null
    at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.8.0_144]
    at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.8.0_144]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:308) ~[tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:735) [tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:667) [tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:482) [tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) [tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.16.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.16.jar:na]
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) [spring-jdbc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) [spring-jdbc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) [spring-jdbc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) [spring-jdbc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) [spring-boot-autoconfigure-1.5.6.RELEASE.jar:1.5.6.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) [spring-boot-autoconfigure-1.5.6.RELEASE.jar:1.5.6.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) [spring-boot-autoconfigure-1.5.6.RELEASE.jar:1.5.6.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$bf862cec.CGLIB$jpaVendorAdapter$9(<generated>) [spring-boot-autoconfigure-1.5.6.RELEASE.jar:1.5.6.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$bf862cec$$FastClassBySpringCGLIB$$3d2e4b4f.invoke(<generated>) [spring-boot-autoconfigure-1.5.6.RELEASE.jar:1.5.6.RELEASE]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) [spring-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) [spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$bf862cec.jpaVendorAdapter(<generated>) [spring-boot-autoconfigure-1.5.6.RELEASE.jar:1.5.6.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_144]
1

There are 1 answers

0
AudioBubble On BEST ANSWER

Ok so it took me a while but this is how I solved my issues; which turned out to be a few.

  1. Make sure you include a property placeholder in the configuration so then the actual property value can bind to. Make sure to read about it here enter link description here

So now my application.yml file looks like bellow, and APP_ENCRYPTION_PASSWORD is an environment variable holding the encryption password.

spring:
  profiles:
    active: prod
  output:
    ansi:
      enabled: detect
---
spring:
  profiles: dev
  application:
    name: App-Dev
  datasource:
    url: jdbc:mysql://localhost:3306/database?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver 
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
server:
  port: 8080

---

spring:
  profiles: prod
  application:
    name: App-Prod
  datasource:
    url: jdbc:mysql://localhost:3306/database?useSSL=false
    username: root
    password: ENC(/98CfxmsjKBW5oZsLkLlmw==)
    driver-class-name: com.mysql.jdbc.Driver 
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
jasypt:
  encryptor:
    algorithm: PBEWithMD5AndDES
    password: ${APP_ENCRYPTION_PASSWORD}
server:
  port: 3000
  1. Only one data source configuration bean needed. I have it set to change active profiles so the correct configuration is picked.

Also create private variables and bind them with a @Value() annotation. Also add the @EnableEncryptableProperties to the class.

DataConfig.java

@Configuration
@EnableEncryptableProperties
public class DataConfig {

    @Value("${spring.datasource.username}")
    private String userName;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;


    @Bean
    DataSource dataSource() {
        return DataSourceBuilder
                .create()
                .username(userName)
                .password(password)
                .url(url)
                .driverClassName(driverClassName)
                .build();
    }
}

And that's it it solved all my problems.