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

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.

Related

connection checker java class in spring boot using HikariCP

Jboss have a mechanism where by I can execute a connection checker class(OracleValidConnectionChecker) before a connection is checked out from the connection pool. That would be helpful in calling a stored procedure before each DB call.(This is needed for setting security context in DB layer for Oracle Layer Security)
Is there any similar mechanism in spring boot (tomcat) using HikariCP ?
I know that there is a connection checker SQL query config (spring.datasource.hikari.connection-test-query). But I am looking for a way to execute a Procedure with input parameters.
As per https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby I believe connectionInitSql would make more sense in your case. connectionTestQuery is for "legacy" drivers that do not support the JDBC4 Connection.isValid().
You may be able to construct your own stored procedure query and pass it into this property, however, be wary you will not benefit from the protection prepared statements generally provide eg. sql injection.

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.

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.

Spring DatasourceTransactionManager not release connection after commit/rollback

I have an Enterprise Application (ear) deployed in this configuration enviroment:
Weblogic 12c (12.1.1) + Oracle RAC 11g (release 2).
Web Module is an MVC application, implemented with Struts 2 and Spring-framework (3.2.2) for core services. Spring JDBC is used for database access with simple JdbcTemplate for single statements and DatasourceTransactionManager for complex ones. I noticed a strange behavior when I enable Weblogic jdbc logs. When I start a new transaction, I can see jdbc info logs about transaction creation, retriving jdbc connection from weblogic datasource pool and setting autocommit property to false value over connection itself. But I can't see transaction releasing connection log, and restoring autocommit flag to true value after commit/rollback invocation.
It's possible that Spring Transaction Manager does not release jdbc connection and does not restore "autocommit" value flag (to true)? After a while I can see within my application some persistent locks on db tables, causing an overall defect of my application and that I would not have depended on the behavior of the transaction manager.
Has anyone noticed a similar behavior?
Is it possible that jdbc connection is not released by the framework and it can compete in multiple transactions (as seen in jdbc log)?
Thanks
Paolo
Since you are using managed DataSource from WebLogic (JNDI?) you have to use managed TransactionManager as well:
<tx:jta-transaction-manager/>
should be enough:
if (weblogicPresent) {
return WEBLOGIC_JTA_TRANSACTION_MANAGER_CLASS_NAME;
}
And it is instead of that DatasourceTransactionManager.

JUnit - Oracle Database and StaleConnections

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?

Resources