How to resolve DataSource Error in Spring Application? - java

I am running into a "Unable to set value for property driver-class-name" (see last segment for full error details). I've read several other articles on SO that seem to suggest I have this set up correctly, but I can't figure out what I am missing so I apologize in advance since using a properties file is new to me. What is causing this error?
application.properties:
# MySQL
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/cafe?useTimezone=true&serverTimezone=UTC
db.user=root
db.password=root
pom.xml:
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
<scope>runtime</scope>
</dependency>
DataSource config:
#Configuration
#PropertySource("../../../../../../../../application.properties")
public class DBConfig {
#Bean
public DataSource getDataSource()
{
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("db.driver");
dataSourceBuilder.url("db.url");
dataSourceBuilder.username("db.user");
dataSourceBuilder.password("db.password");
return dataSourceBuilder.build();
}
}
Error:
10:58:11.577 [main] DEBUG com.zaxxer.hikari.HikariConfig - Driver class db.driver not found in Thread context class loader sun.misc.Launcher$AppClassLoader#18b4aac2, trying classloader sun.misc.Launcher$AppClassLoader#18b4aac2
10:58:11.580 [main] ERROR com.zaxxer.hikari.HikariConfig - Failed to load driver class db.driver from HikariConfig class classloader sun.misc.Launcher$AppClassLoader#18b4aac2
Exception in thread "main" org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under '' to com.zaxxer.hikari.HikariDataSource
at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:363)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:323)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:308)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:238)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:212)
at org.springframework.boot.jdbc.DataSourceBuilder.bind(DataSourceBuilder.java:94)
at org.springframework.boot.jdbc.DataSourceBuilder.build(DataSourceBuilder.java:75)
at edu.bu.met.cs665.database.DataConfig.getDataSource(DataConfig.java:22)
at edu.bu.met.cs665.database.CreateConnection.<init>(CreateConnection.java:26)
at edu.bu.met.cs665.database.CreateConnection.getInstance(CreateConnection.java:35)
at edu.bu.met.cs665.Main.seedDatabase(Main.java:51)
at edu.bu.met.cs665.Main.main(Main.java:39)
Caused by: java.lang.IllegalStateException: Unable to set value for property driver-class-name
at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.setValue(JavaBeanBinder.java:351)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:80)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:56)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:451)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:571)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:557)
at org.springframework.boot.context.properties.bind.Binder$Context.access$300(Binder.java:512)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:449)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:390)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:319)
... 10 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.setValue(JavaBeanBinder.java:348)
... 20 more
Caused by: java.lang.RuntimeException: Failed to load driver class db.driver in either of HikariConfig class loader or Thread context classloader
at com.zaxxer.hikari.HikariConfig.setDriverClassName(HikariConfig.java:486)

Since you're using spring-boot so application.properties should follow standard and you don't need to define any DB configuration like DBConfig.java
Here is detail how your application.properties look like https://spring.io/guides/gs/accessing-data-mysql/

Caused by: java.lang.RuntimeException: Failed to load driver class
db.driver
This means that dataSourceBuilder.driverClassName("db.driver"); pass as value the db.driver and not the value com.mysql.cj.jdbc.Driver
You need to read the value of those configuration properties. As you have it right now it passes as values the property names of those fields. The following should work for you
import org.springframework.core.env.Environment;
#Configuration
#PropertySource("../../../../../../../../application.properties")
public class DBConfig {
#Autowired
Environment env;
#Bean
public DataSource getDataSource()
{
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName(env.getProperty("db.driver"));
dataSourceBuilder.url(env.getProperty("db.url"));
dataSourceBuilder.username(env.getProperty("db.user"));
dataSourceBuilder.password(env.getProperty("db.password"));
return dataSourceBuilder.build();
}
}

Related

'Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.' error in springboot application

I created a springboot application that uses Spring Boot and Apache Camel JDBC Component for inserting a record in postgreSQL. For this purpose I am using the following dependencies:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jdbc</artifactId>
<version>${camel.version}</version>
<!-- use the same version as your Camel core version -->
</dependency>
As for the database configuration, I created the following java class with an application.properties file:
Database Configuration java class:
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import org.apache.camel.support.SimpleRegistry;
import org.apache.commons.dbcp2.BasicDataSource;
public class DatabaseConfiguration {
public static SimpleRegistry createDatabaseConfiguration() throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream("src/main/resources/application.properties"));
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName(properties.getProperty("PostgresDBClassname"));
basic.setUsername(properties.getProperty("PostgresDBUsername"));
basic.setPassword(properties.getProperty("PostgresDBPassword"));
basic.setUrl(properties.getProperty("PostgresDBUrl"));
SimpleRegistry registry = new SimpleRegistry();
registry.bind("myDataSource", basic);
return registry;
}
}
application.properties file:
PostgresDBUsername = username
PostgresDBPassword = password
PostgresDBClassname = org.postgresql.Driver
PostgresDBUrl = jdbc:postgresql://localhost:5432/postgres
I wrote the router in the following way, noting that I tried to replace dataSource with myDataSource:
#Component
public class InsertRestService extends RouteBuilder {
#Override
public void configure() throws Exception {
rest("/").produces("text/plain")
.get("insert")
.to("direct:hello");
from("direct:hello")
.transform().simple("INSERT INTO person (name, country) VALUES (DANY, LB)")
.to("jdbc:dataSource") //spring boot starter jdbc creates the bean in the registry
.transform().simple("Data inserted in Postgres successfully");
}
}
I got the following error:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
I provided the URL in the application.properties file PostgresDBUrl
Also note that I downloaded the jdbc driver jar file and added it to the module path, after a right click on the package, build path, configure build path
So what can I do to solve this issue?
Thank you!!
I removed the configuration file (DatabaseConfiguration) and replaced the content of the application.properties file with:
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.platform=postgres
spring.jpa.hibernate.ddl-auto=none
and it worked!
Check your pom.xml file and switch its packaging into war. It worked for me.
<packaging>war</packaging>

Cannot load ApplicationContext due to Hibernate selecting a non-existent column from information_schema.sequences

Problem
I get org.postgresql.util.PSQLException: The column name start_with was not found in this ResultSet. when trying to run applicationContext.refresh(); after I load my configuration.
EDIT: I can replicate this error on any Postgres instance by simply creating a sequence. I think this is an error with Hibernate.
This occurs when Hibernate runs the following query:
select * from information_schema.sequences
It expects the column start_with to be present in the ResultSet.
The exception is being raised specifically in SequenceInformationExtractorHSQLDBDatabaseImpl#sequenceStartValueColumn:
package org.hibernate.tool.schema.extract.internal;
/**
* #author Vlad Mihalcea
*/
public class SequenceInformationExtractorHSQLDBDatabaseImpl extends SequenceInformationExtractorLegacyImpl {
/**
* Singleton access
*/
public static final SequenceInformationExtractorHSQLDBDatabaseImpl INSTANCE = new SequenceInformationExtractorHSQLDBDatabaseImpl();
#Override
protected String sequenceStartValueColumn() {
return "start_with";
}
}
What I've Tried
I found a similar problem on SO. They needed to update Postgres, so I downloaded the Docker images for Postgres 13, 11, and 8. I am able to load Spring and persist entities in all of these versions.
I also tried downgrading my org.postgresql version (to 42.2.02) since I think my database might be a bit old. The same error occurred with my main database, but not with my Docker containers.
My database is using a schema. I tried setting the default schema to its schema in the Hibernate config. This didn't do anything.
I also made my Docker containers use a schema like in my main database. Nothing changed.
Running the query (select * from information_schema.sequences) that is causing the problem, I can see that my Docker containers return identical results to what my database returns.
I compared the calls stacks between running against Docker and my database. The code that is causing the exception is not even run when I'm running against Docker.
Questions
Why is SequenceInformationExtractorHSQLDBDatabaseImpl#sequenceStartValueColumn even being called? As I mentioned, this is not called when I run against my Docker containers.
Why is it searching for a non-existent column?
Is there something wrong with my configuration?
I'm not really sure where else to look on this one.
Details
PostgreSQL version:
PostgreSQL 11.10 (Ubuntu 11.10-1.pgdg18.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit
POM:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.5.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.5.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.2.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.23</version>
</dependency>
Configuration:
package main.java.configuration;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
#EnableTransactionManagement
public class HibernateConfiguration {
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://myhost:5432/db");
dataSource.setUsername("username");
dataSource.setPassword("pass");
return dataSource;
}
#Bean
#PersistenceContext
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setDataSource(dataSource());
localContainerEntityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
localContainerEntityManagerFactoryBean.setJpaProperties(hibernateProperties());
localContainerEntityManagerFactoryBean.setPackagesToScan("main.java.dbentities");
localContainerEntityManagerFactoryBean.setPersistenceUnitName("project");
return localContainerEntityManagerFactoryBean;
}
#Bean
public JpaTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setDataSource(dataSource());
return transactionManager;
}
private static Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
hibernateProperties.put("hibernate.show_sql", true);
hibernateProperties.put("hibernate.format_sql", true);
hibernateProperties.put("hibernate.hbm2ddl.auto", "validate");
hibernateProperties.put("hibernate.default_schema", "myschema");
return hibernateProperties;
}
}
Application code:
class HibernateUtil {
public static void main(String[] args) {
final AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(HibernateConfiguration.class);
applicationContext.refresh();
applicationContext.close();
}
}
Full stack trace:
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
ERROR SqlExceptionHelper The column name start_with was not found in this ResultSet.
ERROR LocalContainerEntityManagerFactoryBean Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: ifiweekly] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.SQLGrammarException: Unable to build DatabaseInformation
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in main.java.configuration.HibernateConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: ifiweekly] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.SQLGrammarException: Unable to build DatabaseInformation
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at main.java.HibernateUtil.main(Main.java:254)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ifiweekly] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.SQLGrammarException: Unable to build DatabaseInformation
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782)
... 10 more
Caused by: org.hibernate.exception.SQLGrammarException: Unable to build DatabaseInformation
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:103)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:189)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:61)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:200)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:81)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:327)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1410)
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:141)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
... 14 more
Caused by: org.postgresql.util.PSQLException: The column name start_with was not found in this ResultSet.
at org.postgresql.jdbc.PgResultSet.findColumn(PgResultSet.java:2589)
at org.postgresql.jdbc.PgResultSet.getLong(PgResultSet.java:2485)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.resultSetStartValueSize(SequenceInformationExtractorLegacyImpl.java:129)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:59)
at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:65)
at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:59)
at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:181)
... 23 more
By default, Hibernate tries to choose a dialect that fits to the database version in use. I still couldn't figure out from your text which database version does not work for you. Once you write that with PostgreSQL 13, 11 and 8 you were unable to reproduce this and in the next section you write that this problem occurs with 11.
This might be a bug in one of the older PostgreSQL dialects of Hibernate, so if you could clearly write which version produces this error and which dialect is in use (should be reported on startup), you could create an issue in the issue tracker(https://hibernate.atlassian.net) with the exception details and maybe some more information like the actual columns of the table in the respective PostgreSQL version.

Failed to bind properties under 'spring.ora-datasource' to javax.sql.DataSource:

I'm getting failed when compilling app
spring.ora-datasource.username=root
spring.ora-datasource.password=root
spring.ora-datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.ora-datasource.maximumPoolSize=2
my oracle dependency
<!--Oracle-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
</dependency>
Error
Failed to bind properties under 'spring.ora-datasource' to javax.sql.DataSource:
Property: spring.ora-datasource.driver-class-name
Value: oracle.jdbc.driver.OracleDriver
Origin: class path resource [application.properties]:11:41
Reason: Failed to load driver class oracle.jdbc.driver.OracleDriver in either of HikariConfig class loader or Thread context classloader
Action:
Update your application's configuration
Try spring.ora-datasource.driver-class-name=oracle.jdbc.OracleDriver
Note the package name.

org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class

All,
I am trying to crate the datasource for Oracle DB using Spring Boot. I am getting the following error:
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
I did look at the different stackoverflow questions on similar questions but nothing worked.
here is the sample code and other artifacts:
pom.xml:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ucp</artifactId>
<version>12.2.0.1</version>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ons</artifactId>
<version>12.2.0.1</version>
</dependency>
application.yml:
spring:
oracle-db:
url: jdbc:oracle:thin:<oracle db details>
username: <user id>
password: <password>
driver-class-name: oracle.jdbc.OracleDriver
In the above I even tried oracle.jdbc.driver.OracleDriver as driver-class-name. I changed the driver-class-name to driverClassName also but same error.
In the code I am creating the datasource as follows:
#Bean
#Primary
#ConfigurationProperties("spring.oracle-db")
public DataSourceProperties myDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("spring.oracle-db")
public HikariDataSource getMyds() {
return myDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
What is that I am missing?

replace real data source with embedded database for tests

I have two data sources in my spring boot application. both declared like:
#Lazy
#Configuration
#EnableJpaRepositories(
basePackages = "com.nws.signer.db.dao",
entityManagerFactoryRef = "signerEntityManager",
transactionManagerRef = "signerTransactionManager"
)
#EnableTransactionManagement
public class SignerJPAConfig {
private Map<String, String> sig_db_props;
private String sig_url;
#Autowired
private VedProfiledPropsSource p;
#PostConstruct
public void init() {
sig_db_props = new HashMap<>();
sig_url =
String.format("jdbc:postgresql://%s:%s/%s", p.getSigDbHost(), p.getSigDbPort(), p.getSigDbName());
sig_db_props.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQL92Dialect");
sig_db_props.put("javax.persistence.jdbc.url", sig_url);
sig_db_props.put("javax.persistence.jdbc.user", p.getSigDbUser());
sig_db_props.put("javax.persistence.jdbc.password", p.getSigDbPassword());
sig_db_props.put("hibernate.connection.autocommit", "true");
sig_db_props.put("hibernate.cache.use_second_level_cache", "false");
sig_db_props.put("hibernate.hbm2ddl.auto", "update");
}
...
}
so I am using VedProfiledPropsSource which is #ConfigurationProperties with properties for specific profile used. after initializing jpaPropertyMap in postConstruct I am setting it to LocalContainerEntityManagerFactoryBean which is declared as a bean alongside with DataSource and PlatformTransactionManager. same for the other data source.
Now I want to use embedded-database-spring-test dependency:
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>1.5.1</version>
<scope>test</scope>
</dependency>
to bootstrap the embedded database for tests and connect my data sources to this database. the build machine doesn't have a database so I want to use this within the test scope.
my e2e test class starts with:
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#ExtendWith(SpringExtension.class)
#Transactional
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {VedicaConfig.class})
#AutoConfigureMockMvc
#ActiveProfiles("mvntest")
#FlywayTest
#TestMethodOrder(MethodOrderer.OrderAnnotation.class)
#AutoConfigureEmbeddedDatabase(beanName = "signerJPAConfig")
public class RESTTest {
...
}
so I was thinking it will bootstrap the in-memory postgresql db and replace (by magic) the named data source anf flyway will apply migration scripts.
now I am missing/misunderstanding something as this is not happening and my data source configuration bean is still trying to connect to the database with credentials correctly red from profiled property file. and it fails with:
2019-10-07 00:05:53.785 ERROR 40358 --- [ prefetching-3] org.postgresql.Driver : Connection error:
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:245) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.makeConnection(Driver.java:452) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.connect(Driver.java:254) ~[postgresql-42.2.2.jar:42.2.2]
at java.sql.DriverManager.getConnection(DriverManager.java:664) [na:1.8.0_66]
at java.sql.DriverManager.getConnection(DriverManager.java:208) [na:1.8.0_66]
at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:154) [spring-jdbc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:145) [spring-jdbc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:205) [spring-jdbc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnection(AbstractDriverBasedDataSource.java:169) [spring-jdbc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.flywaydb.core.internal.jdbc.JdbcUtils.openConnection(JdbcUtils.java:56) [flyway-core-5.2.4.jar:na]
at org.flywaydb.core.internal.database.DatabaseFactory.createDatabase(DatabaseFactory.java:72) [flyway-core-5.2.4.jar:na]
at org.flywaydb.core.Flyway.execute(Flyway.java:1670) [flyway-core-5.2.4.jar:na]
at org.flywaydb.core.Flyway.migrate(Flyway.java:1356) [flyway-core-5.2.4.jar:na]
at io.zonky.test.db.flyway.DefaultFlywayDataSourceContext$FlywayDatabasePreparer.prepare(DefaultFlywayDataSourceContext.java:173) [embedded-database-spring-test-1.5.1.jar:na]
at io.zonky.test.db.provider.impl.ZonkyPostgresDatabaseProvider$DatabaseInstance$DatabaseTemplate.<init>(ZonkyPostgresDatabaseProvider.java:147) [embedded-database-spring-test-1.5.1.jar:na]
at io.zonky.test.db.provider.impl.ZonkyPostgresDatabaseProvider$DatabaseInstance$DatabaseTemplate.<init>(ZonkyPostgresDatabaseProvider.java:136) [embedded-database-spring-test-1.5.1.jar:na]
at io.zonky.test.db.provider.impl.ZonkyPostgresDatabaseProvider$DatabaseInstance$1.load(ZonkyPostgresDatabaseProvider.java:120) [embedded-database-spring-test-1.5.1.jar:na]
at io.zonky.test.db.provider.impl.ZonkyPostgresDatabaseProvider$DatabaseInstance$1.load(ZonkyPostgresDatabaseProvider.java:118) [embedded-database-spring-test-1.5.1.jar:na]
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3542) [signer-1.0-SNAPSHOT.jar:na]
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2323) [signer-1.0-SNAPSHOT.jar:na]
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2286) [signer-1.0-SNAPSHOT.jar:na]
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2201) [signer-1.0-SNAPSHOT.jar:na]
at com.google.common.cache.LocalCache.get(LocalCache.java:3953) [signer-1.0-SNAPSHOT.jar:na]
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3957) [signer-1.0-SNAPSHOT.jar:na]
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4875) [signer-1.0-SNAPSHOT.jar:na]
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4881) [signer-1.0-SNAPSHOT.jar:na]
at io.zonky.test.db.provider.impl.ZonkyPostgresDatabaseProvider$DatabaseInstance.getTemplate(ZonkyPostgresDatabaseProvider.java:133) [embedded-database-spring-test-1.5.1.jar:na]
at io.zonky.test.db.provider.impl.ZonkyPostgresDatabaseProvider.getDatabase(ZonkyPostgresDatabaseProvider.java:94) [embedded-database-spring-test-1.5.1.jar:na]
at io.zonky.test.db.provider.impl.PrefetchingDatabaseProvider$PrefetchingTask.lambda$new$0(PrefetchingDatabaseProvider.java:252) [embedded-database-spring-test-1.5.1.jar:na]
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) ~[na:1.8.0_66]
at java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:1.8.0_66]
at io.zonky.test.db.provider.impl.PrefetchingDatabaseProvider$PrefetchingTask.run(PrefetchingDatabaseProvider.java:259) [embedded-database-spring-test-1.5.1.jar:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_66]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_66]
at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_66]
Caused by: java.net.ConnectException: Connection refused
please advice me what should I do in order to replace my real data source with embedded one?
Thanks
For me, this worked. If you have a Spring boot project with JPA (Entities and Repositories), you can create the following test:
#ExtendWith(SpringExtension.class)
#DataJpaTest(excludeAutoConfiguration = { LiquibaseAutoConfiguration.class })
#AutoConfigureEmbeddedDatabase
#ActiveProfiles("junit")
public class JpaTest {
#Autowired
private MyRepository repo;
#Test
public void create(){
...
}
Be sure to set the following properties:
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database=POSTGRESQL

Categories

Resources