2 Hikari CPs with different datasource configurations? - spring-boot

Has anyone successfully configured two hikari connection pools with different datasources in a spring boot application? How do I do it using application.properties?

I know that this was asked a long time ago, but I think that it might help others.
In addition, I don't think that the "possible duplicates" mentioned above answer the question.
I'm using spring boot 2.0.4 with maven.
Instead of having a dedicated scope for hikary, as you would if you use one db, e.g.
datasource:
hikari:
connection-test-query: SELECT 1 FROM DUAL
minimum-idle: 1
maximum-pool-size: 2
pool-name: some-pool-name
You can take the settings that you want and put the directly inside the db scope, e.g.:
spring:
datasource:
db1:
type: com.zaxxer.hikari.HikariDataSource
maximum-pool-size: 2
minimum-idle: 1
pool-name: db1-pool
connection-test-query: SELECT 1 FROM DUAL
jdbc-url: jdbc:mysql://${host1}:${port1}/${db1}
username: ${db1-user}
password: ${db1-pass}
driver-class-name: com.mysql.cj.jdbc.Driver
db2:
type: com.zaxxer.hikari.HikariDataSource
maximum-pool-size: 2
minimum-idle: 1
pool-name: db2-pool
connection-test-query: SELECT 1 FROM DUAL
jdbc-url: jdbc:mysql://${host2}:${port2}/${db2}
username: ${db2-user}
password: ${db2-pass}
driver-class-name: com.mysql.cj.jdbc.Driver
As you can see the pool-name and size were set inside that scope.
Then in a java configuration file:
#Configuration
public class AppConfiguration {
....
#Bean("db1")
#ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
#Bean("db2")
#ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
}

Related

springboot quartz init schema only on first startup

This is my config:
#Bean
#QuartzDataSource
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource quartzDataSource() {
return DataSourceBuilder.create().build();
}
and this is my app.yml:
datasource:
url: my-url
jdbcUrl: ${spring.datasource.url}
username: 'root'
password: 'root'
...
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
wait-for-jobs-to-complete-on-shutdown: true
properties:
org:
quartz:
dataSource:
quartz-data-source:
provider: hikaricp
driver: com.mysql.cj.jdbc.Driver
URL: ${spring.datasource.url}
user: ${spring.datasource.username}
password: ${spring.datasource.password}
maximumPoolSize: 5
connectionTestQuery: SELECT 1
validationTimeout: 5000
idleTimeout: 1
scheduler:
instanceId: AUTO
instanceName: my-project-scheduler
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
useProperties: false
misfireThreshold: 60000
clusterCheckinInterval: 30000
isClustered: true
dataSource: quartz-data-source
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 1
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
My question:
If I set initialize-schema: always then the qrtz tables are created on each application startup.
On the other side, if I set initialize-schema: never then I get an error on the first startup that the qrt tables are missing.
Is there a way to configure it to initialize the qrtz tables only if they do not exist?
You are gonna need a migration tool to handle the database creation.
Spring Boot provides two options: Flyway and LiquidBase.
Choose one, create migration scripts and you are up and running.
I personally like the Flyway approach.
You just add implementation 'org.flywaydb:flyway-core' to your build.gradle file (or the maven alternative).
Then add this to your application.yml
spring:
flyway:
enabled: true
baseline-on-migrate: true
Then create db/migration folder in resources folder and put in your migration scripts eg. V1_0_0__db_init.sql (flyway has its own naming convention).
To get the create SQL scripts I recommend that you export them from running database.
Also do not forget to change the spring.jpa.hibernate.ddl-auto to validate.

Why does 'ConversionException' occur in 'TrackingEventProcessor' of Axon framework?

with Axon 4.5
with Spring Boot 2.5.2
with Spring JPA
I wrote Saga management as below
#Saga
class OrderSagaManagement {
#Autowired
private lateinit var eventGateway: EventGateway
#StartSaga
#SagaEventHandler(associationProperty = "orderId")
fun handle(orderCreatedEvent: OrderCreatedEvent) {
val paymentId = Random().nextInt(10000)
SagaLifecycle.associateWith("paymentId", paymentId)
eventGateway.publish(PaymentEvent(paymentId, orderCreatedEvent.orderId))
}
...
}
When I dispatch OrderCreateEvent, ConversionException occurs in TokenEventProcessor#processingLoop() as below.
application.yml is as below.
spring:
application:
name: order-service
datasource:
url: mysql
username: mysql
password:
driver-class-name: com.mysql.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
axon:
serializer:
general: xstream
axonserver:
servers: localhost:8124
bulid.gradle
implementation("org.axonframework:axon-spring-boot-starter:4.5")
Why does 'ConversionException' occur in 'TrackingEventProcessor' of Axon framework?

Disable / remove spring boot datasource by profile

Using spring boot yaml config, I have a datasource that looks like this:
datasource:
url: jdbc:postgresql://somehost/somedb
username: username
password: password
hikari:
connection-timeout: 250
maximum-pool-size: 1
minimum-idle: 0
I can succesfully point to different DBs based on profile, but I'd like to setup a profile that does not use this datasource at all. When I use that profile, however, I get this:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified and no embedded datasource could be auto-configured.
Reason: Failed to determine a suitable driver class
How do I use this datasource in some profiles, but not in others?
You can skip the bean for specific profiles using `#Profile("!dev") annotation
profile names can also be prefixed with a NOT operator e.g. “!dev” to exclude them from a profile
from docs here
If a given profile is prefixed with the NOT operator (!), the annotated component will be registered if the profile is not active — for example, given #Profile({"p1", "!p2"}), registration will occur if profile 'p1' is active or if profile 'p2' is not active.
Profiles can also be configured in XML – the tag has “profiles” attribute which takes comma separated values of the applicable profiles:here
<beans profile="dev">
<bean id="devDatasourceConfig"
 class="org.baeldung.profiles.DevDatasourceConfig" />
</beans>
Change to:
spring:
datasource:
url: jdbc:postgresql://somehost/somedb
username: username
password: password
hikari:
connection-timeout: 250
maximum-pool-size: 1
minimum-idle: 0
Springboot works with Autoconfiguration by default, but you can customize excluding some AutoConfiguration classes
Edit your configuration to skip AutoConfiguration:
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
Make your own datasource by profile
#Bean
#Profile("dev")
DataSource dataSourceDevProfile(org.springframework.core.env.Environment environment) throws Exception {
return DataSourceBuilder.create().url("").driverClassName("").password("").username("").build();
}
#Bean
#Profile("!dev")
DataSource dataSourceNoDev(org.springframework.core.env.Environment environment) throws Exception {
return DataSourceBuilder.create().url(environment.getProperty("spring.datasource.url")).driverClassName("").password(environment.getProperty("spring.datasource.password")).username(environment.getProperty("spring.datasource.username")).build();
}
Or Totally Programatically
#Bean
DataSource dataSource2(org.springframework.core.env.Environment environment) throws Exception {
if (environment.acceptsProfiles("dev")){
//return datasource dev
}else{
//return datasource prod
}

Spring Cloud Config Server issue - Configuring multiple sources native and jdbc

I want to connect to multiple repositories i.e native (file system) and jdbc in spring cloud config. I created a spring cloud config server with below details
application.properties
server.port=8888
spring.profiles.include=native,jdbc
spring.cloud.config.server.native.search-locations=classpath:/config,classpath:/app1, classpath:/app2,classpath:/ep
encrypt.key=abcdef
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/configuration?useSSL=false
spring.cloud.config.server.jdbc.sql=SELECT properties.key, properties.value from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?
spring.datasource.username=root
spring.datasource.password=root
spring.cloud.config.server.native.order=1
spring.cloud.config.server.jdbc.order=2
Irrespective of priority order it always fetches information from jdbc and not from native.
I tried adding the last 2 properties for order to bootstrap.properties still same behavior.
Am is missing anything ? Is my configuration correct ? Please suggest
in spring boostrap.yml loaded before application.yml so you declare server port,config search location and active profile configuration is good approach for this stack,so keep it simple boostrap.yml also spring cloud default profile is native
and in application-"profile".yml is have environment and other configuration properties
and your boostrap.yml or properites like that
server:
port: 8888
spring:
application:
name: appName
profiles:
active: native,jdbc
cloud:
config:
server:
native:
order: 1
searchLocations: classpath:/config,classpath:/app1, classpath:/app2,classpath:/ep
and create applicaiton-jdbc.properties or yml file in same layer in boostrap.yml or properties and declare jdbc properties
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: 'jdbc:mysql://localhost:3306/configuration?useSSL=false'
cloud:
config:
server:
jdbc:
order: 2
sql: 'SELECT properties.key, properties.value from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?'
username: root
password: root
and your config server configuration like this
#SpringBootApplication
#EnableConfigServer
#Import({JdbcEnvironmentRepository.class})
public class ConfigServer {
#ConfigurationProperties(prefix = "spring.datasource")
#Bean
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
public static void main(String[] arguments) {
SpringApplication.run(ConfigServer.class, arguments);
}
}

unexpected Spring Boot metrics for org.apache.tomcat.jdbc.pool.DataSource

I'm using Spring Boot with a pooled datasorce
datasource:
type: org.apache.tomcat.jdbc.pool.DataSource
driverClassName: com.mysql.jdbc.Driver
url: ...
username: ...
password: ...
tomcat:
max-active: 50
max-idle: 50
testOnBorrow: true
validationQuery: select 1;
validationInterval: 30000
This configuration is properly taken as the logfile contains 10x the following line:
16:27:52.191 [] [ restartedMain] DEBUG g.apache.tomcat.jdbc.pool.PooledConnection - Instantiating driver using class: com.mysql.jdbc.Driver [url=...]
After that, I start using the application and made some database requests. The DAO implementation is using JPAContext und EntityManager, autowired by Spring and works perfectly returning the expected results from the database.
#Autowired
private JpaContext jpaContext;
#Autowired
private EntityManager em;
EntityManager em = jpaContext.getEntityManagerByManagedType(DownloadHistoryItemCustomEntity.class);
Query q = em.createNativeQuery(query, DownloadHistoryItemCustomEntity.class);
However, the Spring Boot metrics doesn't show any usage for that single datasource
http://localhost:8080/metrics
"datasource.primary.active": 0,
"datasource.primary.usage": 0.0
Why there aren't values > 0 ?
I would expect values greater then zero !
Isn't 'primary' the right datasource ?
Dominik
datasource.primary.active is the current number of active connections. datasource.primary.usage is a value between 0 and 1 where 0 indicates that there are no active connections and 1 indicates that every connection in the pool is active. For the values to be non-zero, a database connection will have to be active when you make the request to the /metrics endpoint.

Resources