Spring Boot error with multiple data-sources :: dataSource or dataSourceClassName or jdbcUrl is required - spring

I can see following error in my Intellij local for sometime now.
Caused by: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
I have multiple data-sources configured for my project. Something similar as given below.
dataSource-1:
driverClassName: oracle.jdbc.OracleDriver
jdbc-url: so-and-so
datasource-2:
driver-class-name: org.postgresql.Driver
url: so-and-so
As you notice above, somewhere I'm using driverClassName, somewhere the 3 words are separated by hyphens.
So do I need to maintain the same standard in Spring-boot 2.0 across the entire yml file?
By standard, I mean,
driverClassName word would be the same in all places (driver-class-name)
jdbc-url/url text also need to be the same jdbcUrl in all places
This link in stackOverFlow discusses the same.
Please note, the hikari-config setter methods read the values properly in all the config classes wherever they are used, no issues with that.
Any help would be welcome.

Related

Spring stateMachine persistance with Jpa

I got a problem with persister configuration. The problem is similar to Spring State machine - Table Scripts , but I dont want to generate tables by myself or with liquibase. So I'd like to use StateMachineJpaRepositoriesAutoConfiguration but I can't find info how I should enable it.
I already tried to use #ImportAutoConfiguration and do some stuff in property file, for example:
spring:
statemachine:
data:
jpa:
repositories:
enabled: true
But, unfortunately It didn't work for me, and I still get the error:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException:
Schema-validation: missing table [action]
Maybe the way with StateMachineJpaRepositoriesAutoConfiguration is not suitable here, so I'm needed any advice
Tried to use embedded H2 and all the tables was created. So the problem was in my spring.jpa.hibernate settings.
So it should be spring.jpa.generate-ddl=true and spring.jpa.hibernate.ddl-auto=create

How to specify utf8 encoding for db and tables, using embedded database MariaDB in Spring application?

Developing web application I'd like to use an embedded database to store data. However instead of proposed in-memory databases I`d like to prefer to use custom one. My choice is MariaDB. I have been ruled with this article how to get MariaDB as embedded database in my project, everything is fine, database appears, except one thing: I cannot change an encoding for my tables values.
I tried to set additional application properties in my application.yml file, tried to complete connection string with parameters of specifying encoding, but all those stuff didn't work unfortunately :(
May any of you have ever faced with such problem and can help me? Thank you in advance!
My current application.yml is following:
mariaDB4j:
dataDir: ./localMariaDB
port: 3307
databaseName: embeddedDB
spring:
datasource:
url: jdbc:mariaDB://localhost:3307/
username: root
password:
driver-class-name: org.mariadb.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: create
And finally I get exception bellow:
Caused by: java.sql.SQLException: Incorrect string value: '\xD0\x92 \xD1\x80\xD0...' for column 'current_status' at row 1
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readErrorPacket(AbstractQueryProtocol.java:1688) ~[mariadb-java-client-2.6.2.jar:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readPacket(AbstractQueryProtocol.java:1550) ~[mariadb-java-client-2.6.2.jar:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.getResult(AbstractQueryProtocol.java:1513) ~[mariadb-java-client-2.6.2.jar:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.executeQuery(AbstractQueryProtocol.java:318) ~[mariadb-java-client-2.6.2.jar:na]
... 121 common frames omitted
By the way, when I run the application, the connection string which I get looks like jdbc:mysql://localhost:3307/embeddedDB.
I am confused why there is :mysql: instead of :mariadb: as specified in my connection properties. Does it have an influence on my database behavior?
So, I have found the resolution to my issue.
It appeared as usual very simple :)
To change standard character encoding, which MariaDB proposes, I had to specify additional configuration properties before setting up the MariaDB's DataSource.
As this source provides to configure MariaDBSpringService entity to further use in DataSourceconfiguration, it is necessary to extend it (MariaDBSpringService) with some character encoding description utils. So, to specify custom encoding (i.e. to change standard one) I've just added the following lines of code to MariaDBSpringService bean:
service.getConfiguration().addArg("--character-set-server=utf8mb4");
service.getConfiguration().addArg("--collation-server=utf8mb4_general_ci");
In general, the full bean declaration is below:
#Bean
public MariaDB4jSpringService mariaDB4jSpringService(){
MariaDB4jSpringService service = new MariaDB4jSpringService();
service.getConfiguration().addArg("--character-set-server=utf8mb4");
service.getConfiguration().addArg("--collation-server=utf8mb4_general_ci");
return service;
}
Hope, this will help somebody, who further can possibly face with such issue))
Thanks to everybody, who tried to help me!

Why is the placeholder not set properly in hikari.data-source-properties

I am setting the hikari.data-source-properties with a placeholder, but the placeholder value does not get substituted. It is a spring-boot 2.1.4.RELEASE based application. My intention is to set the Session properties so the DBAs can identify my application. Currently I get a default JDBC Thin Client for my connection when I run SELECT PROGRAM FROM V$SESSION from the DB
Below is what I have in my application.yml file
spring:
datasource:
url: "jdbc:oracle:thin:#machine:1521:service_name"
driver-class-name: "oracle.jdbc.driver.OracleDriver"
hikari.data-source-properties:
v$session.program:${spring.application.name}
Below is what I have in my bootstrap.yml file
spring:
application:
name: ms-db-service
When I query the Oracle DB, I notice that the value for program is literally ${spring.application.name}, instead of the expected value ms-db-service
I have tried the below, with same logical result:
Tried redefining the spring.application.name again in the application.yml
Tried using a different locally defined key ${name}
Added the following bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Tried specifying the property as such: spring.datasource.hikari.data-source-properties: v$session.program=${spring.application.name}
I tried the below items to gain more knowledge of the situation:
I tried using a placeholder for spring.datasource.url and that worked fine
I tried to read the value manually using the below code, and that shows the correct values: #Value("${spring.datasource.hikari.data-source-properties}") String propVal;
My conclusion is that HikariCp reads these values before the placeholder substitution is done. I don't understand the relative timing of when the substitution and datasource bean creation happen in the spring-boot bean life-cycle
I am trying to avoid using a bean for hikaricp datasource (not sure if that will even solve the issue), as I don't want to manually build the whole datasource as hikari supports huge number of properties.
So, how can I set the spring.datasource.hikari.data-source-properties in application.yml using a placeholder. And, is there any other way to assign spring.application.name to identify my current db connection?
You have to use it like this:
spring:
datasource:
hikari:
data-source-properties:
"[v$session.program]": ${spring.application.name}

JPA with Multiple database and application.yml

My application (spring-boot) need to access multiple databases.
For some reason, I can't find a propper example using application.yml
This example: http://smasue.github.io/spring-yml-datasources
-> application.yml but not jpa
this example: https://www.baeldung.com/spring-data-jpa-multiple-databases
-> jpa but not application.yml
So I created a very simple project based on this gs: https://spring.io/guides/gs/accessing-data-jpa/
You can find my simple example here: https://github.com/Tyvain/JpaMultipleDatabaseAndApplicationYml
spring:
datasource:
db-1:
url: jdbc:postgresql://10.10.100.100:5432/db1
username: db1
password: db1
driver-class-name: org.postgresql.Driver
db-2:
url: jdbc:postgresql://10.10.100.100:5432/db2
username: db2
password: db2
driver-class-name: org.postgresql.Driver
From here, I am not sure how to affect my repositories to each database.
This example https://www.baeldung.com/spring-data-jpa-multiple-databases is unclear as it's based on properties... and I am not sure how to adapt all code
#PropertySource({ "classpath:persistence-multiple-db.properties" })
[...]
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
env.getProperty("hibernate.dialect"));
How would you assign each repo (CustomerRepositoryDB1 and CustomerRepositoryDB2) to their database ?
Properties and yaml are two absolutely equal means of configuration. The format is only slgihtly different.
You could just replace foo.properties with foo.yml and
com.foobar.var1=value
com.foobar.var2=value2
simply becomes
com.foobar:
var1: value
var2: value2
Plus there is an official Spring Data Repository on Github full of examples. There is even one with two datasources, configured completely in code, no yaml or properties needed:
https://github.com/spring-projects/spring-data-examples/tree/master/jpa/multiple-datasources
In Application.java they exclude the AutoConfig classes and then in each package (Order, Customer), they have a Config class, configuring the datasource. Then there is no need to set the datasource on the repository itself, as that is handled by package scanning with:
factoryBean.setPackagesToScan(OrderConfig.class.getPackage().getName());
in the config. To reiterate: it's datasource per java package, no annotation on the Repository needed.

Spring Boot - Hikari Database Configuration

Recently worked on migrating code to Spring Boot 2.x and am running into an issue configuring the datasource bean. We have two datasources and so we are building the DataSource beans by hand using a DataSourceBuilder.
Per the documentation , I am setting these properties:
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
However, when I do that I get the following error:
java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:1059) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:109) ~[HikariCP-2.7.9.jar:na]
If I change my settings to do this:
spring.datasource.jdbcUrl=jdbc:mysql://localhost/test
then it works.
It also works for a single datasource if I comment out the bean that creates the datasource explicitly which leads me to believe there's a problem in the datasourcebuilder code.
An example repository with just a single data source showing the issue is available here: https://github.com/azizabah/hikari-issue
So what changed between SB 1.5.X and SB 2.X from a configuration stand point when having multiple data sources?
You are missing the configuration of DataSourceProperties and directly trying to wire it.
You need to follow the following documentation to achieve what you want to do in first place :
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources
Co-incidentally somebody did same mistake and raised as bug in git, if you want you can see the same documentation getting referred as solution:
https://github.com/spring-projects/spring-boot/issues/12758

Resources