Spring Boot how to configure list of Hikari datasources dynamically - java

If I only have one datasource and I want to configure it with Hikari then in application.yml I can do something like this:
spring:
datasource:
app:
platform: POSTGRESQL
url: jdbc:postgresql://localhost:5432/mydb
username: mydbuser
password: mydbpass
hikari:
maximum-pool-size: 15
leak-detection-threshold: 15000
max-lifetime: 900000
data-source-properties: stringtype=unspecified
pool-name: defaultHikariPool
And in code I do this:
#Bean
#Primary
#ConfigurationProperties("spring.datasource.app")
fun appDataSourceProperties(): DataSourceProperties {
return DataSourceProperties()
}
#Bean
#ConfigurationProperties(prefix = "spring.datasource.app.hikari")
fun appDataSource(): HikariDataSource {
return appDataSourceProperties()
.initializeDataSourceBuilder()
.type(HikariDataSource::class.java)
.build()
}
This works very well. But let's say I have N datasources where size of N can vary depending on deployment. I created a block like this in the applicaiton.yml:
my-custom-parties:
parties:
- my-custom-party-id: 1
datasource:
platform: POSTGRESQL
url: jdbc:postgresql://localhost:5432/my-db-1
username: user1
password: pass1
hikari:
pool-name: db1HikariPool
maximum-pool-size: 3
leak-detection-threshold: 5000
max-lifetime: 900000
data-source-properties: stringtype=unspecified
- my-custom-party-id: 2
datasource:
platform: POSTGRESQL
url: jdbc:postgresql://localhost:5432/my-db-2
username: user2
password: pass2
hikari:
pool-name: db2HikariPool
maximum-pool-size: 10
leak-detection-threshold: 20000
max-lifetime: 900000
data-source-properties: stringtype=unspecified
And I created a configuration class like this:
#Component
#ConfigurationProperties(prefix = "my-custom-parties")
class MyCustomParties {
private var parties: List<MyCustomParty> = listOf()
fun setParties(parties: List<MyCustomParty>) {
this.parties = parties
}
fun getParties() = parties
}
class MyCustomParty {
lateinit var myCustomPartyId: String
private var datasource: DataSourceProperties? = null
fun setDatasource(datasource: DataSourceProperties) {
this.datasource = datasource
}
fun getDatasource() = datasource?.initializeDataSourceBuilder()?.type(HikariDataSource::class.java)?.build()
}
This intializes a hikari datasource, but it doesn't pick up the configuration properties from the file.
I can't hardcode #Bean's for every datasource because the number of datasources is different in different deployments.
So how can I wire this together correctly?

Related

Spring Boot with Quartz Scheduler: Clustering not working

I am using the dependency spring-boot-starter-quartz and I have the following config in application.yaml for Quartz
spring:
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
properties:
org:
quartz:
scheduler:
instanceId: AUTO
threadPool:
threadCount: 2
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
useProperties: false
tablePrefix: SCHEDULER_
isClustered: true
clusterCheckinInterval: 20000
I have the following beans defined in the Quartz configuration
#Bean
JobDetailFactoryBean notificationJobDetail() {
JobDetailFactoryBean bean = new JobDetailFactoryBean();
bean.setJobClass(NotificationJob.class);
return bean;
}
#Bean
CronTriggerFactoryBean notificationCronTrigger() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setCronExpression(schedulerProperty.getCronNotification());
cronTriggerFactoryBean.setJobDetail(Objects.requireNonNull(notificationJobDetail().getObject()));
return cronTriggerFactoryBean;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setTriggers(notificationCronTrigger().getObject());
schedulerFactoryBean.setApplicationContextSchedulerContextKey(QUARTZ_APPLICATION_CONTEXT);
return schedulerFactoryBean;
}
But some how the application.conf properties I guess is not read by Quartz and therefor clustering is not working. In the logs it shows
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

Dijital Ocean spaces listObjects not working

My application.yml
## PostgreSQL
spring:
datasource:
url: jdbc:postgresql://myip:5432/db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
username: wqeqe
password: qweqwewqe$qwewqe
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
show-sql: true
---
server:
port: 8085
## DO properties
do:
spaces:
key: mykey
secret: mysecret
endpoint: digitaloceanspaces.com
region: myregion
bucket: mybusket
My read config read appication.yml
#Configuration
#PropertySource("classpath:application.yml")
#ConfigurationProperties(prefix = "do.spaces")
public class DoConfig {
#Value("${key}")
private String doSpaceKey;
#Value("${secret}")
private String doSpaceSecret;
#Value("${endpoint}")
private String doSpaceEndpoint;
#Value("${region}")
private String doSpaceRegion;
#Bean
public AmazonS3 getS3() {
BasicAWSCredentials creds = new BasicAWSCredentials(doSpaceKey, doSpaceSecret);
return AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(doSpaceEndpoint, doSpaceRegion))
.withCredentials(new AWSStaticCredentialsProvider(creds)).build();
}
}
My service
#Override
public List<TemplateDto> getAll() {
return (List<TemplateImage>) templateImageRepository.findAll();
}
My repo
#Repository
public interface TemplateImageRepository extends PagingAndSortingRepository<TemplateImage,Long> {
}
Hi everyone I am using this project dijital ocean spaces but the problem listObject images don't return null. What is the problem please help me I am new working is the file servers.
Thanks !!!

Multiple databases in dropwizard

I am trying to read and write into two databases and I am running into issues:
config.yml
database1:
driverClass: com.mysql.jdbc.Driver
user: user1
password: user!23
url: jdbc:mysql://url.to.connect:3306/db1
properties: charSet: UTF-8
maxWaitForConnection: 1s
minSize: 8
maxSize: 32
checkConnectionWhileIdle: false
checkConnectionHealthWhenIdleFor: 10s
closeConnectionIfIdleFor: 1 minute
database2:
driverClass: com.mysql.jdbc.Driver
user: user2
password: user!23
url: jdbc:mysql://url.to.connect:3306/db2
properties: charSet: UTF-8
maxWaitForConnection: 1s
minSize: 8
maxSize: 32
checkConnectionWhileIdle: false
checkConnectionHealthWhenIdleFor: 10s
closeConnectionIfIdleFor: 1 minute
configuration.java
public class ExampleConfiguration extends Configuration {
#Valid
#NotNull
private DataSourceFactory database1 = new DataSourceFactory();
#Valid
#NotNull
private DataSourceFactory database2 = new DataSourceFactory();
#JsonProperty("database1")
public DataSourceFactory getDb1DataSourceFactory() {
return database1;
}
#JsonProperty("database2")
public DataSourceFactory getDb2DataSourceFactory() {
return database2;
}
}
Now following: Maintain multiple migration files in parallel in dropwizard, I tried to add a bootstrap bundle as follows:
#Override
public void initialize(Bootstrap< ExampleConfiguration > bootstrap) {
bootstrap.addCommand(new RenderCommand());
bootstrap.addBundle(new AssetsBundle());
bootstrap.addBundle(new MigrationsBundle<ExampleConfiguration>() {
#Override
public DataSourceFactory getDataSourceFactory(ExampleConfiguration configuration) {
return configuration.getDb1DataSourceFactory();
}
});
bootstrap.addBundle(new MigrationsBundle<ExampleConfiguration>() {
#Override
public DataSourceFactory getDataSourceFactory(ExampleConfiguration configuration) {
return configuration.getDb2DataSourceFactory();
}
});
bootstrap.addBundle(hibernateBundle);
}
But I got command 'db' has been already used. I am still unclear what is happening in initialize(). How can I switch between DB instances for read and write operations?
Thank you.
You should override each MigrationsBundle implementation's method name to provide unique command's name. Then using CLI you will need to specify correct name to use according database configuration.

How set initial size connection to postgresql in application.yml

Always when i connect to my database, I see 10 idle connection. How can I set this in application.yml.
I use spring boot 1.5.6.RELEASE.
It's not working:
spring:
datasource:
maxActive: 5
maxIdle: 5
minIdle: 5
initialSize: 5
When I created #Bean it's working, but I need solution in application.yml
#Configuration
public class DBConfig {
#Value("${dbconfig.driver-class-name}")
private String driverClassName;
#Value("${dbconfig.url}")
private String url;
#Value("${dbconfig.username}")
private String username;
#Value("${dbconfig.password}")
private String password;
#Bean
public DataSource dataSource() throws SQLException {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(driverClassName);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
I think you're missing to say these are properties. I think the following will work.
spring:
dataSource:
properties:
maxActive: 5
maxIdle: 5
minIdle: 5
initialSize: 5
Note: If you're using tomcat-jdbc, you have to define it explicitly like,
spring:
dataSource:
tomcat:
max-active: 5
max-idle: 5
min-idle: 5
initial-size: 5

Add new conection to database in Jhipster

I need to do a new database connection in a Jhipster project, I am doing the next
Add in application-dev.yml:
datasource:
driver-class-name: org.postgresql.ds.PGSimpleDataSource
url: jdbc:postgresql://localhost:5432/analytics
name: analytics
username: elser
password: ******
datasources:
elser:
driver-class-name: org.hibernate.dialect.PostgreSQLDialect
url: jdbc:postgresql://localhost:5432/elser
name: elser
username: elser
password: ******
And in DatabaseConfiguration.java:
#Bean
#ConfigurationProperties(prefix="spring.datasources.elser")
public DataSource dataSourceElser() {
return DataSourceBuilder.create().build();
}
I added a new class to test this:
#Inject
#Qualifier("dataSourceElser")
private DataSource dataSourceElser;
private JdbcTemplate jdbcTemplate;
#PostConstruct
public void init() {
jdbcTemplate = new JdbcTemplate(dataSourceElser);
int rowCount = this.jdbcTemplate.queryForObject("select count(*) from commons.usuario", Integer.class);
System.out.println(rowCount);
}
But its giving me the next error:
java.sql.SQLException: org.hibernate.dialect.PostgreSQLDialect cannot be cast to java.sql.Driver
You are currently specifying a hibernate dialect, not the JDBC driver name. You need to use:
driver-class-name: org.postgresql.Driver
Instead of both driver-class-name: org.postgresql.ds.PGSimpleDataSource and driver-class-name: org.hibernate.dialect.PostgreSQLDialect

Categories