How does Spring-JPA EntityManager handle "broken" connections? - spring

I have an application that uses a Spring-EntityManager (JPA) and I wonder what happens if the database happens to be unavailable during the lifetime of my aforesaid application.
I expect in that situation it will throw an exception the first time to do anything on the database, right?
But, say I wait 10 minutes and try again then and the DB happens to be back. Will it recover? Can I arrange it so it does?
Thanks

Actually, neither Spring nor JPA have anything to do with it. Internally all persistence frameworks simply call DataSource.getConnection() and expect to receive (probably pooled) JDBC connection. Once they're done, they close() the connection effectively returning it to the pool.
Now when the DataSource is asked to give a connection but database is unaivalable it will throw an exception. That exception will propagate up and will be somehow handled by whatever framework you use.
Now to answer your question - typically DataSource implementation (like dbcp, c3p0, etc.) will discard connection known to be broken and replace it with a fresh one. It really depends on the provider, but you can safely assume that once the database is available again, the DataSource will gradually get rid of sick connections and replace them with healthy ones.
Also many DataSource implementors provide ways of testing the connection periodically and before it is returned to the client. This is important in pooled environemnts where the DataSource contains a pool of connections and when the database becomes unavailable it has no way to discover that. So some DataSources test connection (by calling SELECT 1 or similar) before giving it back to the client and do the same once in a while to get rid of broken connections, e.g. due to broken underlying TCP connection.
TL;DR
Yes, you will get an exception and yes the system will work normally once the database is back. BTW you can easily test this!

Related

Detecting Session Creation and Destroy with Spring Session JDBC

I am using Spring Session JDBC to persist sessions in my application. I am aware that this implementation does not support HTTP event publishing. However, I have a requirement to log session creation, expiration, and destruction. If I get some sort of notification that the session was destroyed, I already know how to determine if it was a logout or timeout.
I realize that the obvious answer is "don't use JDBC". However, I do not have the option to stand up Redis or Hazelcast due to strong port-management policies of my organization. If I want to open the Redis or Hazelcast ports, management has to get involved.
I'm asking if anyone has figured out how to "fake it", and determine if a sesson is created or destroyed in the absence of an HttpSessionEventPublisher. I have one idea which is the equivalent of a very large hammer approach, so I'm wondering if anyone else has done this in the past.

Possible concurrency conflict in getConnection() under multitenancy situation

I am implementing database schema based multitenancy strategy. I use PostgreSQL for db, HikariCP for pool, and it's a SpringBoot application. I will need to set the schema after getting the connection, like the code below. (this.ds is a hikari pool)
#Override public Connection getConnection() throws SQLException {
Connection connection = this.ds.getConnection();
// reset target schema to...
String schema = determineSchema();
connection.createStatement().execute("SET search_path to "+schema);
return connection;
}
So my question is, say two API calls with tenant1 and tenant2 comes nearly the same time visiting getConnection() function and set schema. I am wondering how will the code handle it? Ideally, I would like to see Hikari will give them 2 different connections and there would be no conflict in schema set. But is it the real case? Do we need a read/write lock here? Thanks ahead.
A connection pool keeps track of what connections it has checked out; once a connection is handed off to a thread it doesn’t give that same connection out again until the connection is handed back. If a connection isn’t handed back then you have a connection leak. The leak happens because the pool hasn’t gotten notified that the user of the connection is finished with it so it refuses to hand it out. It errs on the side of not handing out a connection if there is any doubt about if the connection is in use.
In the event the pool did mess up and hand out the same connection twice there is no locking you can do that would fix the problem, you would end up with one of the two threads writing to the wrong schema (unless both just happened to ask for the same schema, of course). If Hikari made this error it wouldn’t be useable. Fortunately connection pools don’t seem to have a problem getting this right.

Java client starting up when IBM MQ server is down or unreachable

I realize there is a method to set on MQConnectionFactory to attempt to reconnect if the connection of a consumer or producer is broken. However, I'm wondering if one can do something similar for an application that is starting up and setting up consumers and producers. The code I have right now will not recover if the server is down when my client application comes up.
Is there a common/recommended practice here?
My recommendation would simply be to use the tools that are provided in the Java language itself. For example, you could write a loop with exception handling to retry the initial connection or JNDI lookup a configurable number of times. It's hard to provide more specific recommendations when you haven't provided any client code of your own.

ActiveMQ actively check connection for server liveliness

Is there a way to check an ActiveMQ server is still up, without actually receiving or sending or doing a transaction? I am employing a "Best Effort 1 Phase Commit" logic - i.e. not using XA, but instead commit db right before committing the JMS, assuming that the JMS commit will go through unless the server has gone down (as opposed to the SQL commit, which can fail due to e.g. constraint violations).
This is very close to perfectly good enough. However, if I could, right before committing the database transaction, check whether the ActiveMQ server actually was running right now, I would tighten the potential crash-window just a tad bit more.
A way to send some kind of "ping" through the connection would be exactly what I was looking for, e.g. get hold of some kind of status from the actual server (not just ask the connection object whether it believes it has a connection to the server). For a SQL Server, "SELECT 1" is pretty nice for this scenario. I guess I could send a message to a topic without any consumers, but this seems a bit heavy handed. It would be no problem to employ methods on the actual ActiveMQConnection object (as opposed to purely the JMS API).

How to close idle connections in Spring JMS CachingConnectionFactory?

I used the Spring JMS cachingconnectionfactory to improve the performance of the my application based on Spring Integration and IBM MQ. I put sessioncachesize as 10 as we have the max of 10 concurrent threads working (ThreadPoolTaskExecutor) on consume/sending messages.
When I looked at the number of connections opened in MQ explorer (open output count for queue), it shows 10 and it stays on for days and never getting closed.
Is there a way to programatically to detect connections which are
potentially stale - say idle for half a day - I checked the
resetConnection() but not sure how to get the last used time for the
session.
Does Spring provides any connection time out parameter for
cacheconnection factory? or How to release these idle connections?
Also, the heartbeat/keepalive mechanism will not work for us as we want to physical close the cached connections based on last used time.
If the timeout is a property of the Session object returned by IBM, you could subclass the connection factory, override createSession(); call super.createSession(...) then set the property before returning it.
You might also have to override getSession(...) and keep calling it until you a get a session that is not closed. I don't see any logic to check the session state in the standard factory. (getSession() calls createSession() when the cache is empty).

Resources