How to make Spring server to start even if database is down? - java

I'm using a Spring Boot(1.4.7) & MyBatis.
spring.main1.datasource.url=jdbc:mariadb://192.168.0.11:3306/testdb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&socketTimeout=5000&connectTimeout=3000
spring.main1.datasource.username=username
spring.main1.datasource.password=password
spring.main1.datasource.driverClassName=org.mariadb.jdbc.Driver
spring.main1.datasource.tomcat.test-on-borrow=true
spring.main1.datasource.tomcat.test-while-idle=true
spring.main1.datasource.tomcat.validation-query=SELECT 1
spring.main1.datasource.tomcat.validation-query-timeout=5000
spring.main1.datasource.tomcat.validation-interval=5000
spring.main1.datasource.tomcat.max-wait=5000
spring.main1.datasource.continue-on-error=true
I cannot start program with errors when database is disconnected on Eclipse or Linux server.
(Database is not located on localhost.)
When I try to start program with disconnected database,
print this.
java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=192.168.0.11)(port=3306)(type=master) : connect timed out
Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=192.168.0.11)(port=3306)(type=master) : connect timed out
Stopping service [Tomcat]
Application startup failed
Is there any way?
Thanks

You can set:
spring.sql.init.continue-on-error=true
in your application.properties.
According to the Spring Boot 2.5.5 user guide:
By default, Spring Boot enables the fail-fast feature of its script-based database initializer. This means that, if the scripts cause exceptions, the application fails to start. You can tune that behavior by setting spring.sql.init.continue-on-error.
P.S.: Before Spring Boot 2.5, the property was named spring.datasource.continue-on-error.

I was able to solve this. One main difference between what I got working and the code in the question, though, is that I'm using Hikari instead of Tomcat for the connection pool.
These were the key settings I had to make:
spring.datasource.hikari.minimum-idle: 0
spring.datasource.hikari.initialization-fail-timeout: -1
spring.datasource.continue-on-error: true
spring.datasource.driver-class-name: org.postgresql.Driver
spring.jpa.database-platform: org.hibernate.dialect.PostgreSQLDialect
Setting minimum-idle to 0 allows Hikari to be happy without any connections.
The initialization-fail-timeout setting of -1 tells Hikari that I don't want it to get a connection when the pool fires up.
From the HikariCP documentation:
A value less than zero will bypass any initial connection attempt, and the pool will start immediately while trying to obtain connections in the background. Consequently, later efforts to obtain a connection may fail.
The continue-on-error setting true allows the service to continue even when encountering an error.
Both the driver-class-name and database-platform were required. Otherwise, Hikari tries to figure out those values by connecting to the database (during startup).
Just in case I'm missing something, though, here's my full Spring config:
spring:
application:
name: <redacted>
datasource:
url: <redacted>
username: <redacted>
password: <redacted>
driver-class-name: org.postgresql.Driver
hikari:
minimum-idle: 0
maximum-pool-size: 15
connection-timeout: 10000 #10s
idle-timeout: 300000 #5m
max-lifetime: 600000 #10m
initialization-fail-timeout: -1
validation-timeout: 1000 #1s
continue-on-error: true
jpa:
open-in-view: false
database-platform: org.hibernate.dialect.PostgreSQLDialect
And my project has the following Spring Boot dependencies:
org.springframework.boot:spring-boot
org.springframework.boot:spring-boot-actuator
org.springframework.boot:spring-boot-actuator-autoconfigure
org.springframework.boot:spring-boot-autoconfigure
org.springframework.boot:spring-boot-configuration-processor
org.springframework.boot:spring-boot-devtools
org.springframework.boot:spring-boot-starter
org.springframework.boot:spring-boot-starter-actuator
org.springframework.boot:spring-boot-starter-jdbc
org.springframework.boot:spring-boot-starter-jooq
org.springframework.boot:spring-boot-starter-json
org.springframework.boot:spring-boot-starter-logging
org.springframework.boot:spring-boot-starter-security
org.springframework.boot:spring-boot-starter-test
org.springframework.boot:spring-boot-starter-tomcat
org.springframework.boot:spring-boot-starter-validation
org.springframework.boot:spring-boot-starter-web

You need to add
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
in order to make it works

If the tips above didn't help and you use jpa, then set
spring.jpa.hibernate.ddl-auto=none
it worked for me.

When you build your app you can add that
mvn clean install -DskipTests
it will skip the tests of database connection
(-D is used to define a system property)

Related

Unable to create initial pool of connections in springboot

I am trying to connect a database with the springboot but that is not running in any way. I have made about 3 applications till now but all have the same issue. I am a total spring newbie and working for the first time.
I have used JPA and Mysql for the application but all the time the error will show itself.
application file
datasource:
url: jdbc:mysql://localhost:3306/test_schema
username: root
password: user
jpa:
generate-ddl: true
show-sql: true
Error
Sat Jun 08 11:02:13 IST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
2019-06-08 11:02:13.362 ERROR 14040 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
java.sql.SQLException: Unable to load authentication plugin 'caching_sha2_password'.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:868) ~[mysql-connector-java-5.1.41.jar:5.1.41]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:864) ~[mysql-connector-java-5.1.41.jar:5.1.41]
at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1746) ~[mysql-connector-java-5.1.41.jar:5.1.41]
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1226) ~[mysql-connector-java-5.1.41.jar:5.1.41]
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2205) ~[mysql-connector-java-5.1.41.jar:5.1.41]
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2236) ~[mysql-connecto......
Error continues and is really a very long list
I have asked a similar question before but that solved the problem of database schema and table but now this is showing up . And this error is showing in almost all the applications. Mysql is up and running. The username password are correct. The database also has some initial entries.
caching_sha2_password is the default authentication plugin for MySQL.
Please try updating the mysql connector library to say mysql-connector-java-8.0.12 ( try to match mysql version and connector version )
Probably yo are using version around "5.1.44".
Also, if this doesnt work, try as what is suggested above
ALTER USER 'root'#'localhost' IDENTIFIED WITH mysql_native_password BY 'user';
If the change fixes this issue but leads to a different exception : java.sql.SQLException: Unknown system variable 'query_cache_size', it probably indicates the version of mySQL connector is not correct/matching for MySQL 8x versions
Remember, "The query cache is deprecated as of MySQL 5.7.20, and is removed in MySQL 8.0"
Update the dependency for MYSQL connector library to use latter versions, latest on date is 8.0.15:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
Run this command on your mysql server :
ALTER USER 'root'#'localhost' IDENTIFIED WITH mysql_native_password BY 'user';

Grails + mysql : The driver has not received any packets from the server

I am attempting to connect my grails application to a Mysql database running locally via MAMP. I am getting the following error, and nothing else. I've tried every configuration. I don't think this is a Grails issue but more of a configuration issue. Any help would be most appreciated.
The driver has not received any packets from the server.
Here is my application.yml
environments:
development:
dataSource:
dbCreate: update
driverClassName: "com.mysql.jdbc.Driver"
dialect: org.hibernate.dialect.MySQL5Dialect
url: "jdbc:mysql://localhost:3306/development"
username: "root"
password: ""
I've tried with the port, without port different dialects and still no luck. Any ideas on what could be going on?
Thanks in advance for your help.

mysql db connection lost [duplicate]

I have an app that uses spring-boot,jpa-hiberanate with mysql.I am getting this error log
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 56,006,037 milliseconds ago. The last packet sent successfully to the server was 56,006,037 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
Here is my application.properties
# DataSource settings: set here configurations for the database connection
spring.datasource.url = jdbc:mysql://localhost:3306/test
spring.datasource.username = test
spring.datasource.password = test
spring.datasource.driverClassName = com.mysql.jdbc.Driver
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate settings are prefixed with spring.jpa.hibernate.*
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming_strategy = org.hibernate.cfg.ImprovedNamingStrategy
To solve this issue I can use
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
But I checked that it's not recommended .So can anyone suggest me what should I do to overcome this error
The easiest way is to specify the autoReconnect property in the JDBC url, although this isn't the recommended approach.
spring.datasource.url = jdbc:mysql://localhost:3306/test?autoReconnect=true
This can give issues when you have an active connection and during a transaction something happens and a reconnect is going to happen. It will not give issues when the connection is validated at the start of the transaction and a new connection is acquired at the start.
However it is probably better to enable validation of your connections during the lifetime of your application. For this you can specify several properties.
First start by specifying maximum number of connections you allow for the pool. (For a read on determining the max poolsize read this).
spring.datasource.max-active=10
You also might want to specify the number of initial connections
spring.datasource.initial-size=5
Next you want to specify the min and max number of idle connections.
spring.datasource.max-idle=5
spring.datasource.min-idle=1
To validate connection you need to specify a validation-query and when to validate. As you want to validate periodically, instead of when a connection is retrieved from the pool (this to prevent broken connections in your pool).
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1
NOTE: The usage of a validation-query is actually discouraged with as JDBC4 has a better/different way of doing connection validation. HikariCP will automatically call the JDBC validation method when available.
Now that you are also validating while a connection is idle you need to specify how often you want to run this query for the connections and when a connection is considered idle.
spring.datasource.time-between-eviction-runs-millis=5000 (this is the default)
spring.datasource.min-evictable-idle-time-millis=60000 (this is also default)
This all should trigger validation of your (idle) connections and when an exception occurs or the idle period has passed your connections will be removed from the pool.
Assuming you are using Tomcat JDBC as the connection pool this is a nice read of what and how to configure.
UPDATE: Spring Boot 2.x switched the default connection pool to HikariCP instead of Tomcat JDBC.

Heroku - FATAL: password authentication failed for user <>

First of all, I created PostgreSQL DB in Heroku. I manually created my DB/schema/tables through pgAdmin remote access. I know I succeeded since it updated my row limit.
Now, I am deploying a Spring Boot application.
No DB props/credentials are found in my application.properties file since I am supposed to do this in Heroku Config Vars. For example, my DB username is janxgspmlpjgbn
Project builds successfully, however, in the logs I see that it has this exception.
2016-09-28 16:12:31.184 [ERROR] org.apache.juli.logging.DirectJDKLog.log:181 - Unable to create initial connections of pool.
2016-09-28T16:12:31.185772+00:00 app[web.1]: org.postgresql.util.PSQLException: FATAL: password authentication failed for user "u24453"
Question
Why does it fail for the user u24453 (by the way this user changes every time I redeploy) when in my Config Var, I typed the user janxgspmlpjgbn?
Edit
Here's how my Config Vars look right now:
u24453 is probably the OS user name (the one Heroku creates for your app as it runs on Ubuntu Linux).
I believe the Postgres Driver will use the OS username as your DB username by default (if a username is not provided). Thus, I suspect the DB username is not getting into the configuration properly.
In your application.yml you should have this:
spring:
datasource:
url: ${JDBC_DATABASE_URL}
username: ${JDBC_DATABASE_USERNAME}
password: ${JDBC_DATABASE_PASSWORD}
For more info see Connecting to Relational Databases on Heroku with Java

Connection to Db dies after >4<24 in spring-boot jpa hibernate

I have an app that uses spring-boot,jpa-hiberanate with mysql.I am getting this error log
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 56,006,037 milliseconds ago. The last packet sent successfully to the server was 56,006,037 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
Here is my application.properties
# DataSource settings: set here configurations for the database connection
spring.datasource.url = jdbc:mysql://localhost:3306/test
spring.datasource.username = test
spring.datasource.password = test
spring.datasource.driverClassName = com.mysql.jdbc.Driver
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate settings are prefixed with spring.jpa.hibernate.*
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming_strategy = org.hibernate.cfg.ImprovedNamingStrategy
To solve this issue I can use
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
But I checked that it's not recommended .So can anyone suggest me what should I do to overcome this error
The easiest way is to specify the autoReconnect property in the JDBC url, although this isn't the recommended approach.
spring.datasource.url = jdbc:mysql://localhost:3306/test?autoReconnect=true
This can give issues when you have an active connection and during a transaction something happens and a reconnect is going to happen. It will not give issues when the connection is validated at the start of the transaction and a new connection is acquired at the start.
However it is probably better to enable validation of your connections during the lifetime of your application. For this you can specify several properties.
First start by specifying maximum number of connections you allow for the pool. (For a read on determining the max poolsize read this).
spring.datasource.max-active=10
You also might want to specify the number of initial connections
spring.datasource.initial-size=5
Next you want to specify the min and max number of idle connections.
spring.datasource.max-idle=5
spring.datasource.min-idle=1
To validate connection you need to specify a validation-query and when to validate. As you want to validate periodically, instead of when a connection is retrieved from the pool (this to prevent broken connections in your pool).
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1
NOTE: The usage of a validation-query is actually discouraged with as JDBC4 has a better/different way of doing connection validation. HikariCP will automatically call the JDBC validation method when available.
Now that you are also validating while a connection is idle you need to specify how often you want to run this query for the connections and when a connection is considered idle.
spring.datasource.time-between-eviction-runs-millis=5000 (this is the default)
spring.datasource.min-evictable-idle-time-millis=60000 (this is also default)
This all should trigger validation of your (idle) connections and when an exception occurs or the idle period has passed your connections will be removed from the pool.
Assuming you are using Tomcat JDBC as the connection pool this is a nice read of what and how to configure.
UPDATE: Spring Boot 2.x switched the default connection pool to HikariCP instead of Tomcat JDBC.

Categories