How do I get Spring Boot to automatically reconnect to PostgreSQL? - java

I am running Spring Boot connecting to a PostgreSQL database. I have verified that data is written to the database if Spring Boot is started after the database.
spring.datasource.url = jdbc:postgresql://localhost/dbname
spring.datasource.username = user
spring.datasource.password = secret
spring.datasource.driver-class-name = org.postgresql.Driver
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
When there are changes in the database in development, I run into exceptions:
PreparedStatementCallback; SQL []; This connection has been closed.; nested exception is org.postgresql.util.PSQLException: This connection has been closed.
Note that the database is accessible again when the exceptions occur; I think the problem is that connection is stale because the database endpoint it originally connected to is no longer available because of the restart. Restarting Spring Boot resolves the issue.
How do I configure Spring Boot to reconnect to PostgreSQL so that I do not need to restart it?
I have attempted to follow the answers in Spring Boot JPA - configuring auto reconnect and How to reconnect database if the connection closed in spring jpa?. I am not sure whether the PostgreSQL behavior is different from MySQL. My reading of the Spring Boot documentation has not helped; I do not know the components described well enough to understand what documentation I should be looking at.

Spring boot should be configured to reconnect automatically, problem is that it is not aware of the broken connection.
Since you are already using test on borrow and validation query, just try reducing validation interval so it is executed every time.
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.tomcat.validation-query=SELECT 1
spring.datasource.tomcat.validation-interval=0
Tomcat jdbc connection pool on testOnBorrow:
(boolean) The indication of whether objects will be validated before being borrowed from the pool. If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. NOTE - for a true value to have any effect, the validationQuery or validatorClassName parameter must be set to a non-null string. In order to have a more efficient validation, see validationInterval. Default value is false
But be aware of validationInterval:
(long) avoid excess validation, only run validation at most at this frequency - time in milliseconds. If a connection is due for validation, but has been validated previously within this interval, it will not be validated again. The default value is 30000 (30 seconds).

Related

Spring JDBC Hikari constantly logon logoffs in Oracle Database

I am using spring boot hikari db pool to connect to an Oracle database (19C).
Our properties are as below:
spring.datasource.app.hikari.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.app.hikari.minimumIdle=5
spring.datasource.app.hikari.maximumPoolSize=10
spring.datasource.app.hikari.idleTimeout=600000
spring.datasource.app.hikari.connectionTimeout=180000
spring.datasource.app.hikari.max-lifetime=60000
Our Database's AUD table is filling up due to constant logon logoff actions getting registered from the services every second.
I used solution from below question (to decrease minimumIdle and increase idleTimeout for long idle times), but it did not resolve the issue.
spring jdbc hikari connection pool - constantly logs on and off to database
Can somebody help in this case. Thanks in advance.
If you have not override datasource with different property name for hikaricp then use below properties
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.connection-timeout=180000
spring.datasource.hikari.max-lifetime=60000

Connection closed exception when using Oracle Weblogic's JNDI datasource

I'm making use of Oracle Weblogic's (12.1.3) JNDI datasource for connection pooling. The max idle time for a connection is set to 30 seconds in the admin console. But, there is this method that takes more than a minute to complete, which results in the connection getting automatically closed.
My problem is that I have set autoCommit as false, and I'm unable to rollback the transaction in case of an Exception. I'm making use of pure JDBC. I tried using Spring's JdbcTemplate, surprisingly there is no Connection related issue when I'm making use of the #Transactional annotation.
Is there a technique using which I can keep the connections that I get from the Weblogic's JNDI datasource alive for more than 30 seconds, without modifying the configurations in the admin console?

Testing Spring boot validation Query for Oracle spring.datasource.validationQuery=SELECT 1 from dual

I have a spring boot application in production. The spring boot version is 1.3.5. The connection to database is getting closed since no requests are being hit for a large amount of time. I have decided to use below properties to keep the connection alive
**spring.datasource.validationQuery=SELECT 1 from dual
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=30000**
Ideally the query need to be run for every 30 seconds. I would like to test whether the query is being working properly. I am unable to understand how to test these properties. Can anyone let me know is there any way to test this. I have added below properties in properties file but still query is not getting printed in console.
**spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=INFO
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE**

How to check if you're still connected to the database with jpa

I'm trying to check the database connection with jpa using the EntitityManager/Session class.
To check both cases (connected/not connected), I simply start/deactivate the service mysql before running the code.
Asking simple sql queries to the database is out of mind since it doesn't cover all cases.
I already tried:
Session session = entityManager.unwrap(Session.class)
session.isConnected();
But that always returns true...
When I disable the mySQL service I want session.isConnected() to return false, but it always returns true;
Is there any other way to check for the database connection(using any other classes maybe)?
Short answer: don't
Long answer: if you're developing an application where this is important, you will probably be using some sort of database connection pooling framework, like the
Tomcat JDBC pool
Apache Commons DBCP
HikariCP
C3P0 Connection pool
This will manage many important aspects for you, including connection lifecycle. In tomcat jdbc for example you can specify:
testOnBorrow="true"
validationQuery="select 1 from sysibm.dual"
This on an IBM DB2 database will test whether a connection went stale every time you use it, and also swap it out for a fresh one if the select fails. Done this way, you will never have to worry about this on the level of you application code.

Oracle connection/query timeout

Is it possible to specify connection/query timeout for the Oracle database queries? Either on Oracle side or in Oracle's JDBC driver (10.2.0.4)? So, that Java client just got an error back after, let's say, 2 minutes instead of waiting until Oracle finishes executing the query?
If you are executing the query in the context of a transaction, the transaction timeout value of the JTA transaction monitor will be the determinant to query timeout. The configuration for this depends from one application server to another.
At an individual query level (in the absence of a JTA transaction monitor), the setQueryTimeout method can be used to set the timeout on the execution of a Statement/PreparedStatement/CallableStatement object.
Update
setQueryTimeout is not to be relied on, although it works (atleast from a J2SE client). It works via the JDBC driver performing a full round-trip to the Oracle database server. Then, it is upto the database to halt execution of the query. Don't rely on it for time critical applications.
Have a look at Oracle profiles. This allows you to specify several limits at the database level. One of them is a maximum CPU time per query.
If you have queries running for more than 2 minutes on a regular basis you might want to do some tuning of your queries first.
According to http://www.javamonamour.org/2012/09/oraclenetconnecttimeout.html
oracle.net.READ_TIMEOUT for jdbc versions < 10.1.0.5 oracle.jdbc.ReadTimeout for jdbc versions >=10.1.0.5
So if you are using a JDBC driver version 10.1.0.5 or higher, then oracle.jdbc.ReadTimeout is the correct property.
Setting oracle.jdbc.ReadTimeout helped to timeout the jdbc calls. I have used it in a production spring boot app by specifying datasource properties as below
spring.datasource.hikari.connection-timeout=1000
spring.datasource.hikari.dataSourceProperties=oracle.jdbc.ReadTimeout=2000
Note: Earlier this app was using tomcat connection pool and after setting the above properties for the same, timeouts were happening but the pool was not able to handle the closed connection objects efficiently. Therefore, I switched to hikariCP and got lot better results. I have made a video simulating the slow jdbc calls which compares the results with tomcat and hikari connection pools while using the ReadTimeout property.

Categories