JUnit - Oracle Database and StaleConnections - oracle

I was wondering is there any way in Java to force a stale connection?
We have some logic that determines if a sqlexception received is actually a Stale Connection - if it is we try and reconnect to the database.
I could not find any objects that could be mocked (using EasyMock or Powermock) in order to similulate a stale connection so I was there any properties we can set on the connection cache to expire a connection?

Related

Closing connections in Spring DATA jpa

I am using spring data jpa and hikari connection pooling. In repository file, I am using methods to connect to database. I would like to know how and where to close the database connections.
Repository
public interface abc extends JPARepository<abc, int>{
List<abc> findById(int id);}
Any help on how to close the connections and where(service layer or repository) would be really appreciated
`
With Connection Pooling, using the framework, The task of creating a connection before each operation and closing the connection after the operation is now taken from the programmer and transferred to the Spring Context:-
The application requests a connection from the connection pool.
If an unused connection exists, it is returned by the pool; otherwise, the pool creates a new connection.
The application sends a query to the Hybrid Data Pipeline connectivity service.
The application obtains query results.
The application displays the result to the end-user.
The application closes the connection, which returns the connection to the pool.
Note: The application calls the close() method, which allows the connection to remain open. The pool receives the notification of the close request.

spring boot connection pool with long running requests

When a spring boot request starts, it obtains a connection from the pool. My question is - is this connection remains tied to the request thread (even if it is not executing any query) and only returned to the pool when request completes?
For example, if I'm doing something like:
Request starts
Execute a query (20ms)
Call external http service (1500ms)
Request completes
Would the connection obtained by this request thread remain occupied with the thread (and not available to other requests) for 20ms or 1520ms?
PS: I'm using Spring Boot 2.0 with HikariCP and I'm not using #Transactional.
Thanks.
If you have Spring MVC on your classpath, Spring will configure an instance of OpenEntityManagerInViewInterceptor automatically (in org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.JpaWebConfiguration), unless you configure spring.jpa.open-in-view to false. This interceptor will open an instance of EntityManager and bind it to the TransactionSynchronizationManager for the whole duration of the request.
What that means is that at the first use of a repository query, it will borrow a connection from the pool and keep it until the end of the request when the EntityManager is closed by the interceptor. It's the EntityManager's responsibility to return the connection to the pool. So, in that case, the connection will be borrowed for 1520ms in your example.
If you disable the spring.jpa.open-in-view option, a connection will be borrowed and returned at each use of a repository query given you don't use any explicit transaction. While this may look better, you have to keep in mind that managed instances of your entities will need to be reattached systematically on each persist operation so it may be costly. You will also loose the benefits of the EntityManager caching. To avoid this, use transactions to read/modify/persist your entities and avoid reattaching.
Finally, keep in mind that if you disable spring.jpa.open-in-view, since you don't have an EntityManager around for the duration of the request, you will need to make sure your lazy loaded relations are loaded inside a transaction otherwise you'll get the dreaded LazyInitializationException.
Basically it depends,
If you close conection it will be release back to pool and will be ready soon according to configuration (below) so it will be ~20ms (+ time to get back to pool)
If you don't close the connection it will wait until the configuration allow it, if it allow indefinite time, theoretically it can be causing a leak in your application and not return to pool until apllication is shutdown.
See answer about Hikari handling returning connections to pool:
The Hikari housekeeper runs every 30s, which closes any connections that are not in use and are older than maxLifetime. If there are more than minimumIdle number of connections the housekeeper will close connections that have been idle for longer than idleTimeout.
See more about max life time of connection:
by default Oracle does not enforce a max lifetime for connections (neither on JDBC driver side (1), nor on server side(2)). So in this respect, the "infrastructure-imposed connection time limit" is +infinity

When sharing a Jdbc connection pool between spring-data-jpa and spring-security-oauth's JdbcTokenStore, how to handle transactions?

We are using the JdbcTokenStore from spring-security to persist oAuth2 access tokens. The same application does also heavily rely on spring-data-jpa. Both share a connection pool to a MySQL database.
Jdbc defaults to auto-commit mode and JdbcTokenStore appears to be written with the assumption that auto-commit is on. It never explicitly commits a change.
Spring-data and JPA on the other hand require a transaction for write operations. The application uses the #Transactional annotation.
We are observing the following issue:
Request (1): A client obtains an access token. JdbcTokenStore INSERTs this into the database.
Request (2): Then, the client uses this access token in a subsequent request. This request is rejected since the token cannot be found in the database.
This behaviour could be explained if transaction from request (1) was not yet committed.
I'm not very familiar with the internals of Spring. Is it possible that the following happens?
Some JPA operation acquires JDBC connection #1 from the pool, sets auto-commit=off, executes any number of SQL statements, and, then, commits.
Request (1): JdbcTokenStore acquires the same JDBC connection #1, executes INSERT statement. (This now happens inside a transaction. This is not committed.)
Request (2): JdbcTokenStore acquires a different JDBC connection #2, executes SELECT statement. (This does not see the uncommitted transaction.)
Some JPA operation acquires JDBC connection #1 again and commits. (Now the oAuth token is committed.)
What configuration would avoid this?
While I cannot explain the root cause, we have found a fix: Switching to the HikariCP JDBC connection pool (replacing Tomcat) eliminated all symptoms of the describe issue.

MyBatis+Spring+Jersey with Oracle Seems to reuses SQL sessions

I'm creating a rest service using MyBatis 3.3.1, Spring 4.3, Jersey 2.22 and Oracle 12c. My transactions are being managed by Spring using the DataSourceTransactionManager and the #Transaction annotaion. I am also using a MyBatis pooled data source as my javax.sql.DataSource. What I don't understand if why database sessions are being reused.
In my application, I am setting an oracle client identifier: DBMS_SESSION.SET_IDENTIFIER("my id"). With the debug logging statements, I can see MyBatis creating new sessions for each of the MyBatis sql operations. I also have debug to print out the database session identifier from DBMS_SESSION.UNIQUE_SESSION_ID.
What I don't understand is that if I access my rest endpoint multiple times, the unique session id is the same and the identifier from my last access is still set.
Shouldn't a new oracle session be used every time MyBatis gets a new SQLSession? Why is the oracle session always the same?
Thanks.
Session in Oracle is bound to a connection.
You are using connection pooling so after one rest request is finished the connection is returned to the connection pool. Session is not terminated in this case.
You probably want to clear identifier on returning connection to pool and setting it on retrieving connection from the pool. The exact way to do that depends on the connection pool you are using. For built-in mybatis connection pool see this answer.

Javers is grabbing all of my available Connections

One other thing I'm finding, is that it appears that Javers is grabbing all of the available Connections out of my connection pool (created via Spring DataSourceBuilder). I'm not using Hibernate/JPA, just straight JDBC via JdbcTemplate and mostly MyBatis for my entity queries.
I've added a logging statement to my ConnectionProvider for Javers, and at the start of the application when it queries for the schema, it pulls 4 connections to check for each of the tables, and then never returns any of them even after the commit from the PlatformTransactionManager.
I understand from https://stackoverflow.com/a/35147884/570291 that it's supposed to participate in the same connection as the current Transaction. Since I'm not using Hibernate/JPA, does that mean I need to implement the connection tracking/etc from MyBatis to the Javers ConnectionProvider to return the same connection (if there is one), and then handle closing (returning to the pool) of that connection at the end of the transaction?
I found DataSourceUtils.getConnection(DataSource) which is a Spring utility class to get a connection from the given DataSource including if it's tied to a current transaction or not as appropriate. Using that in the ConnectionProvider looks like it's done the trick of keeping the connection for the existing transaction.
JaVers won't return connections to application's connection pool for the same reason as it won't call sql commit or rollback.
Managing connactions and transactions is the application's responsibility, not JaVers. We call it passive mode, from Javers doc:
- JaVers doesn’t create JDBC connections on its own and uses connections provided by an application (via ConnectionProvider.getConnection()).
- JaVers philosophy is to use application’s transactions and never to call SQL commit or rollback commands on its own.
Thanks to this approach, data managed by an application (domain objects) and data managed by JaVers (object snapshots) can be saved to SQL database in one transaction.
In JaVers project there is no mybatis support, so you need to implement ConnectionProvider for mybatis on your own.
Proper implementation of ConnectionProvider shouldn't create new sql connection for every getConnection() call. It should return the connection which underlies current application's transaction. Typically, it's implemented using ThreadLocal.
As you mentioned, ConnectionProvider should handle committing transactions and closing connections.

Resources