0

I am using Spring 2.7.2 and I keep getting this WARN log when I do an operation that involves the database after some minutes passes by:

HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@ (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.

So I did use shorter and shorter value in this property max-lifetime: 140000 but I keep getting the warning, and checking in the database with query show global variables like '%wait_timeout%'; I have the following values:

enter image description here

wait_timeout I understand is the one that matters there, and it is in seconds, so that would be 10 minutes, and my current configuration is 140000 milliseconds which is 2 minutes and 20 seconds, so I should not be getting this WARN log. So the thing is it is my first time using a Datasource Bean, so right now I guessing that the problem is it is still being configured with the default value for max-lifetime because at the hikari documentation https://github.com/brettwooldridge/HikariCP it says that the default value is 1800000 (30 minutes) which is way above the wait_timeout value at mysql datbase im connecting (10 minutes), so thats why I think the Datasource bean is not getting the config I am specifing in properties, so here is the Bean:

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DataSourceConfig {
    @Bean
    @Qualifier("datasource")
    public DataSource getDataSource(final @Value("${spring.datasource.host}") String host,
            final @Value("${spring.datasource.username}") String user,
            final @Value("${spring.datasource.password}") String password)
            throws DecrypterException {
        return DataSourceBuilder.create().url(String.format(
                "jdbc:mysql://%s/%s?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false",
                decrypter.getEnv(host), "databasename")).username(user).password(decrypter.getEnv(password)).build();
    }
}

I must do it like that cause the host and the password are encrypted environment variables that can only be decrypted with a specific library, so I also have other properties, here is the properties yml:

spring:
  datasource:
    host: ENCRYPTED_HOST
    username: normal_user
    password: ENCRYPTED_PASSWORD
    driverClassName: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 65
      max-lifetime: 140000
  jpa:
    open-in-view: false
    show-sql: false

Am I missing something?? Is the Bean not being able to get the configurations specified in the application yml? Maybe the time specified in the max-lifetime property for some reason is seconds instead of milliseconds? (going to try this but I doubt it)...

Or maybe I need to do something like this (?) there in the Bean definition since it wont get it from the properties:

        HikariConfig config = new HikariConfig();
        config.setMaxLifetime(140000);
        config.setMaximumPoolSize(65);
        HikariDataSource source = new HikariDataSource(config);
        DataSourceBuilder builder = DataSourceBuilder.create();
        builder.derivedFrom(source);

If so where can I see a good example? Would like to keep all the default configs (except the maxPoolSize and maxLifeTime im trying to configure ofcourse) like it would normally be if all was configured via application.yml and no datasource beans, or it happens by default this way too? Thanks in advance

BugsOverflow
  • 386
  • 3
  • 19

1 Answers1

1

Just to confirm: hikari.max-lifetime is in milliseconds. In your case the property will not have effect because you have bean configuration of datasource. Spring Boot auto-configuration will back-off in this case.

You should configure everything in code but still using the properties. Like you already did for the datasource. Here just as example:

@Bean
public DataSource dataSource() {
    HikariConfig config = new HikariConfig();
    config.setDriverClassName(driverClassName);
    config.setJdbcUrl(url);
    config.setUsername(username);
    config.setPassword(password);
    config.setMaximumPoolSize(hikariMaximumPoolSize);
    config.setMaxLifetime(hikariMaxLifetime);
    HikariDataSource dataSource = new HikariDataSource(config);
    return dataSource;
}
Mar-Z
  • 2,660
  • 2
  • 4
  • 16
  • Thank you very much for confirming, but I still have one doubt, what about the properties I do not configure? Will they be default like they normally do without creating the DataSource Bean? for example another property like "minimumIdle" which in Hikari docs they do recommend to leave it default, like so "we recommend not setting this value and instead allowing HikariCP to act as a fixed size connection pool. Default: same as maximumPoolSize" – BugsOverflow May 03 '23 at 12:21
  • 1
    All defaults will be preserved as long you are not setting them explicitly. – Mar-Z May 03 '23 at 12:44
  • Thank you, the WARN is gone after configuring everything in the Bean, extracting the values from properties like you suggested :) I also found many other ways to do it in this post: https://stackoverflow.com/a/32093013/12085680 going to try some of them – BugsOverflow May 03 '23 at 13:19