Spring Boot - How to check number of active connections in the connection pool - spring

I am using Spring Boot 1.5.17 with multiple data sources configured. One of my data sources is configured as follows.
#Primary
#Bean
#ConfigurationProperties("app.primary.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
Now how do I get or log the number of active connections in the connection pool for this data source?

It's a bit late , but DataSource interface doesn't have any methods that lets you do this, but if you are using HikariCP (which is the default).
You could do this.
(HikariDataSource)dataSource).getHikariPoolMXBean().getActiveConnections()

Solution (Kotlin code):
#Autowired var dataSource: DataSource
val hikaridataSource = dataSource as HikariDataSource
logger.info(
active: ${hikaridataSource.hikariPoolMXBean.activeConnections} " + "idle: ${hikaridataSource.hikariPoolMXBean.idleConnections} " + "threadsAwaitingConnection: ${hikaridataSource.hikariPoolMXBean.threadsAwaitingConnection}"
)

Related

Custom DataSource Spring boot

spring works well when we use the default datasource and ways we can use in-build spring jpa.
So currently what we do is the following
specify the config for DB in the application.properties
myapp.datasource.url=jdbc:mysql:thin:#localhost:1521:myschema
myapp.datasource.username=user
myapp.datasource.password=password
myapp.datasource.driver-class=com.mysql.cj.jdbc.Driver
Custom datasource
#ConfigurationProperties(prefix = "myapp.datasource")
#Bean
public DataSource mySqlDataSource()
{
return DataSourceBuilder.create().build();
}
We have the same application running for multiple clients. Problem is each client has their own DB schema.
So, the problem now is that we need to be able to serve each client but in order to do this, we need to create multiple datasources
for instance:
#ConfigurationProperties(prefix = "myapp.partner1.datasource")
#Bean
public DataSource mySqlDataSourcePartner1()
{
return DataSourceBuilder.create().build();
}
#ConfigurationProperties(prefix = "myapp.partner2.datasource")
#Bean
public DataSource mySqlDataSourcePartner2()
{
return DataSourceBuilder.create().build();
}
#ConfigurationProperties(prefix = "myapp.partner3.datasource")
#Bean
public DataSource mySqlDataSourcePartner3()
{
return DataSourceBuilder.create().build();
}
and so on...
Is there a generic and more efficient way of doing this? where if in future when a new partner is added we can just specify the config in application properties and get that working?
You can use Spring Boot Multi-tenancy model using a separate database for each client. You can save the database configuration in config-properties or database then depending upon the ClientId you can you the Datasource. You need to add Interceptor to intercept the Request and identify the tenant. Please refer to the below example
https://tech.asimio.net/2017/01/17/Multitenant-applications-using-Spring-Boot-JPA-Hibernate-and-Postgres.html
please check
https://github.com/sumanentc/multitenant

Spring boot how to use Hikari auto configuration but set username/password at runtime

I am using Spring boot 2.0.1 with Hikari CP and want to use application properties to set Hikari datasource properties like Connection timeout, Maximum pool size etc but the username and password should be set at runtime. I tried below but when the datasource is created, it doesn't have the Connection timeout value I am trying to set.
Below is the code for datasource bean.
#Value("${spring.datasource.url}")
private String url;
#ConfigurationProperties(prefix = "spring.datasource.hikari")
#Bean
public DataSource dataSource() throws Exception {
//User name and password is fetched from some other data storage
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(url);
hikariConfig.setUsername(username);
hikariConfig.setPassword(password);
//The data source created here doesn't have connection timeout value
//set by me
return new HikariDataSource(hikariConfig);
}
Below is my application properties file
spring.datasource.url={Our DB URL}
spring.datasource.hikari.maximumPoolSize=100
spring.datasource.hikari.idleTimeout=30000
spring.datasource.hikari.poolName=SpringBootJPAHikariCP
spring.datasource.hikari.connectionTimeout=40000
spring.datasource.hikari.driver-class-
name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
I referred to below Spring documentation but it just talks about auto configuring properties like url and credentials (which worked) but not about connection timeout and idle timeout etc.
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-configure-a-datasource
Please let me know if I am missing anything.
#ConfigurationProperties(prefix = "spring.datasource.hikari")
#Bean
#Primary
public DataSource dataSource(String username,String password) {
return DataSourceBuilder.create().username(username).password(password).build();
}
and use these in yml/property file without giving username and password property.
spring:
profiles: dev
# Development database configuration
datasource.hikari:
driverClassName: oracle.jdbc.driver.OracleDriver
jdbcUrl: jdbc:oracle:thin:#url:1621:sid
type: com.zaxxer.hikari.HikariDataSource
connectionTimeout:40000
This will work. Let me know if it doesn't work for you.

Warning: Not loading a JDBC driver as driverClassName property is null, in springboot working with two datasources

I have currently configured spring boot to work with two different datasources. The application is working fine, however when I start the spring boot application I get an warning repeated 10 times like below:
2018-06-05 10:28:15.897 WARN 8496 --- [r://myScheduler] o.a.tomcat.jdbc.pool.PooledConnection : Not loading a JDBC driver as driverClassName property is null.
As I mentioned this is not affecting my application, but I would like to know why I am having this kind of warning and if there is any way to fix it.
When using two or more datasources you need to configure them yourself. In that case Spring Boot's DataSourceAutoConfiguration (and also DataSourceProperties) won't be used.
You most probably have the related DB details like the name of the JDBC driver class name in application.properties file as follows:
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
primary.datasource.url=jdbc:sqlserver://xxx.yyy.zzz.www:1433;databaseName=primaryDB
primary.datasource.username=username
primary.datasource.password=password
other.datasource.url=jdbc:sqlserver://xxx.yyy.zzz.www:1433;databaseName=otherDb
other.datasource.username=otheruser
other.datasource.password=otherpassword
Thus, to set the driver class name for the datasource just say:
#Value("${spring.datasource.driver-class-name}")
String driverClassName;
#Primary
#Bean(name = "primaryDb")
#ConfigurationProperties(prefix = "primary.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().driverClassName(driverClassName).build();
}
#Bean(name = "otherDb")
#ConfigurationProperties(prefix = "other.datasource")
public DataSource otherDataSource() {
return DataSourceBuilder.create().driverClassName(driverClassName).build();
}

Spring Boot auto reconnect to PostgreSQL using JdbcTemplate and multiple datasources

I have a Spring Boot v 1.5.1.RELEASE app which uses PostgreSQL 9.6 as a datasource. My app remains connected to Postgres even when idle, but if the connection is lost then the app does not reconnect and instead throws:
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is org.postgresql.util.PSQLException: This connection has been closed.
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:342) ~[spring-jdbc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) ~[spring-jdbc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.java:212) ~[spring-jdbc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.setDataSource(SQLErrorCodeSQLExceptionTranslator.java:134) [spring-jdbc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.<init>(SQLErrorCodeSQLExceptionTranslator.java:97) [spring-jdbc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jdbc.support.JdbcAccessor.getExceptionTranslator(JdbcAccessor.java:99) [spring-jdbc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649) [spring-jdbc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
Although I am not using JPA and I believe I am using the Tomcat pool that comes with spring-boot-starter, I have read and tried the suggestions discussed here and here with no luck. In my properties file, I have tried:
#spring.datasource.tomcat.test-on-borrow=true
#spring.datasource.tomcat.validation-query=SELECT 1
#spring.datasource.tomcat.test-while-idle=true
#spring.datasource.tomcat.time-between-eviction-runs-millis=3600000
#spring.datasource.tomcat.validation-query=SELECT 1
#spring.datasource.dbcp2.test-on-borrow=true
#spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1
However, I am using two data sources, configured like this:
#Configuration
public class DatabaseConfiguration
{
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.ds_pgsql_rtmain")
public DataSource rtmainDataSource()
{
DataSource dataSource = DataSourceBuilder.create().build();
return dataSource;
}
#Bean
#ConfigurationProperties(prefix = "spring.ds_pgsql_pdns")
public DataSource pdnsDataSource()
{
return DataSourceBuilder.create().build();
}
#Bean
#Primary
public JdbcTemplate rtmainJdbcTemplate(DataSource rtmainDataSource)
{
return new JdbcTemplate(rtmainDataSource);
}
#Bean
public JdbcTemplate pdnsJdbcTemplate(#Qualifier("pdnsDataSource") DataSource pdnsDataSource) {
return new JdbcTemplate(pdnsDataSource);
}
}
I'm not sure if the problem is that I did not configure the data pool correctly or because the pool does not work when I manually configure the data sources. Or something else. Assistance would be greatly appreciated, thank you.
Yes since you're not using an auto configured data source it is not working.
Since you're applying properties from your own prefix you just have to put test-on-borrow and validation-query on your own prefix. Try this:
spring.ds_pgsql_rtmain.test-on-borrow=true
spring.ds_pgsql_rtmain.validation-query=SELECT 1
spring.ds_pgsql_pdns.test-on-borrow=true
spring.ds_pgsql_pdns.validation-query=SELECT 1

How to change bitronix jms pool parameters?

I'm using Spring Boot 1.2.0.RC1 + bitronix + hornetq (embedded) + JPA, and I'd like to increase bitronix jmsConnectionFactory pool size, currently it's limited at 10. Is there a simple way to do it, inside application.properties for example or inside a #Configuration class?
You can't configure it via application.properties at the moment (I've opened an issue), but you can do it from a #Configuration class by declaring your own XAConnectionFactoryWrapper bean:
#Bean
public XAConnectionFactoryWrapper xaConnectionFactoryWrapper() {
return new XAConnectionFactoryWrapper() {
#Override
public ConnectionFactory wrapConnectionFactory(
XAConnectionFactory connectionFactory) {
PoolingConnectionFactoryBean pool = new PoolingConnectionFactoryBean();
pool.setConnectionFactory(connectionFactory);
pool.setMaxPoolSize(50);
return pool;
}
};
}

Resources