I'm facing the following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'comissionamentoEntityManagerFactory' defined in class path resource [coruripe/comissionamento/config/ComissionamentoConfig.class]: [PersistenceUnit: comissionamento] Unable to build Hibernate SessionFactory; nested exception is java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
I am working on a project that initially had only one database for the "comissionamento" module. Now, I need to create a new separate module for "sis". I have configured it according to Spring's documentation and forums. Below are the configurations:
application.properties
# Database configurations for Comissionamento
spring.datasource.comissionamento.url=jdbc:postgresql://localhost:5432/comissionamento
spring.datasource.comissionamento.username=***
spring.datasource.comissionamento.password=***
spring.datasource.comissionamento.driver-class-name=org.postgresql.Driver
# JPA/Hibernate configurations for Comissionamento
spring.jpa.comissionamento.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.comissionamento.hibernate.ddl-auto=update
spring.jpa.comissionamento.show-sql=true
spring.jpa.comissionamento.format-sql=true
# Database configurations for SIS
spring.datasource.sis.url=jdbc:postgresql://localhost:5432/sis
spring.datasource.sis.username=***
spring.datasource.sis.password=***
spring.datasource.sis.driver-class-name=org.postgresql.Driver
# JPA/Hibernate configurations for SIS
spring.jpa.sis.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.sis.hibernate.ddl-auto=update
spring.jpa.sis.show-sql=true
spring.jpa.sis.format-sql=true
ComissionamentoConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "coruripe.comissionamento.repository",
entityManagerFactoryRef = "comissionamentoEntityManagerFactory",
transactionManagerRef = "comissionamentoTransactionManager"
)
public class ComissionamentoConfig {
@Primary
@Bean(name = "comissionamentoDataSource")
@ConfigurationProperties(prefix = "spring.datasource.comissionamento")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "comissionamentoEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource())
.packages("coruripe.comissionamento.model")
.persistenceUnit("comissionamento")
.properties(Map.of(
"hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect",
"hibernate.hbm2ddl.auto", "update",
"hibernate.show_sql", "true",
"hibernate.format_sql", "true"
))
.build();
}
@Primary
@Bean(name = "comissionamentoTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("comissionamentoEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
SisConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "coruripe.sis.repository",
entityManagerFactoryRef = "sisEntityManagerFactory",
transactionManagerRef = "sisTransactionManager"
)
public class SisConfig {
@Bean(name = "sisDataSource")
@ConfigurationProperties(prefix = "spring.datasource.sis")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sisEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource())
.packages("coruripe.sis.model")
.persistenceUnit("sis")
.properties(Map.of(
"hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect",
"hibernate.hbm2ddl.auto", "update",
"hibernate.show_sql", "true",
"hibernate.format_sql", "true"
))
.build();
}
@Bean(name = "sisTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("sisEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Everything seems to be configured correctly, including the part where the error occurs.
For context, here’s the project structure in case it helps.
Note: There are no entities yet in the "sis" package or any controllers. Only the directories exist at this point.
You should take a look at the documenation, skip the first sample but use the config as mentioned in the MyCompleteAdditionalDataSourceConfiguration
which seperates out the DataSourceProperties
for binding.
@Configuration(proxyBeanMethods = false)
public class MyCompleteAdditionalDataSourceConfiguration {
@Qualifier("second")
@Bean(defaultCandidate = false)
@ConfigurationProperties("app.datasource")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
@Qualifier("second")
@Bean(defaultCandidate = false)
@ConfigurationProperties("app.datasource.configuration")
public HikariDataSource secondDataSource(
@Qualifier("secondDataSourceProperties") DataSourceProperties secondDataSourceProperties) {
return secondDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}
Instead of binding properties to the resulting datasource you first want to bind the properties to a DataSourceProperties
object. Inject that specific one into a method that creates the datasource. That way it behaves in exact the same way that the default Spring Boot configuration would.
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "coruripe.comissionamento.repository",
entityManagerFactoryRef = "comissionamentoEntityManagerFactory",
transactionManagerRef = "comissionamentoTransactionManager"
)
public class ComissionamentoConfig {
@Primary
@Bean(name = "comissionamentoDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.comissionamento")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean(name = "comissionamentoDataSource")
@ConfigurationProperties(prefix = "spring.datasource.comissionamento.properties")
public DataSource dataSource(@Qualifier("comissionamentoDataSourceProperties) DataSourceProperties comissionamentoDataSourceProperties) {
return comissionamentoDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Primary
@Bean(name = "comissionamentoEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource())
.packages("coruripe.comissionamento.model")
.persistenceUnit("comissionamento")
.properties(Map.of(
"hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect",
"hibernate.hbm2ddl.auto", "update",
"hibernate.show_sql", "true",
"hibernate.format_sql", "true"
))
.build();
}
@Primary
@Bean(name = "comissionamentoTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("comissionamentoEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
This will make the config work exactly as the default Spring Boot one. Now you could also use spring.datasource.comissionamento.jdbc-url
as a property as that will bind directly to the underlying HikariCP datasource. However you might miss on some of the other properties you have configured which don't have a direct getter/setter on the HikariCP implementation.