How can we sure Connection.close() is called - java

I am working on Spring MVC + Mysql using JDBC (Non Hibernate). In project we have many services which does the CRUD work. for each method we have to do some steps like
open Connection
Rollback on error
Close connection in finally
Many developers are working on the same project and its very hard to check if connection is closed in finally by every one or not.
So is their any way where after completion of method connection get closed. can i write any class which check if execution of current method is done then close the connection.
Update
Or can we develop some class from which each developer have to ask for Connection will do work on the connection object the at the finally every one have to pass that object to destroyer. If destroyer is not called the show compile time error on that method.
Something like:
someMethod()
{
Connection connection=null
try
{
Connection connection =icrudOperation.getConnection();
//do work with connection object like preparedStatement etc.
}
catch (Exception e)
{
//logging
}
finally
{
icrudOperation.destroy(connection); // if this is not written by any one then at compile time error will shown for this method.
}
}

You shouldn't be messing with the connection in the first place. Use a JdbcTemplate to do the querying. If you really want to do stuff with the connection use a ConnectionCallback. Complete this with springs declarative transaction management and you have 1 problem less to solve.
If you really want to work with the Connection and refuse to use use the common approach of the JdbcTemplate you could fix this with Springs declarative transaction management. Wrap the datasource in a TransactionAwareDataSourceProxy. Then configure Spring to manage the transaction, this will ensure that during the transaction a single connection will be used and spring will close the connection at the end of the transaction.
I would however strongly suggest to move to the usage of the JdbcTemplate as that will make your life a whole lot easier and allows you to solve the actual business problems
One other thing your service layer shouldn't be involved in JDBC coding that should be in a data access layer which is used by the service layer.

The following should work:
try{
Connecition.close();
}
finally{
System.err.println();
Connection.close();
}

Related

How Propagation.REQUIRES_NEW works on jdbc level?

I've read the documentation and I understand how Propagation.REQUIRES_NEW works but
Create a new transaction, and suspend the current transaction if one exists. Analogous to the EJB transaction attribute of the same name.
NOTE: Actual transaction suspension will not work out-of-the-box on all transaction managers. This in particular applies to org.springframework.transaction.jta.JtaTransactionManager, which requires the javax.transaction.TransactionManager to be made available to it (which is server-specific in standard Java EE).
See Also:
org.springframework.transaction.jta.JtaTransactionManager.setTransactionManager
I can't understand how suspension could work.
For a single level transaction I suppose that spring creates the code like this:
Connection connection = DriverManager.getConnection(...);
try {
connection.setAutoCommit(false);
PreparedStatement firstStatement = connection.prepareStatement(...);
firstStatement.executeUpdate();
PreparedStatement secondStatement = connection.prepareStatement(...);
secondStatement.executeUpdate();
connection.commit();
} catch (Exception e) {
connection.rollback();
}
Could you please provide an example for the Propagation.REQUIRES_NEW?
Is it done somehow via jdbc savepoint?
but I can't understand how suspension could work.
It mostly doesn't.
Is it done somehow via jdbc savepoint ?
JDBC doesn't support the notion of suspending transactions (it supports the notion of subtransactions, though - that's what savepoints are about. JDBC does, that is - many DB engines do not).
So how does it work?
By moving beyond the confines of JDBC. The database needs to support it, and the driver also needs to support it, outside of the JDBC API. So, via a non-JDBC-based DB interaction model, or by sending an SQL command.
For example, In WebLogic, there's the WebLogic TransactionManager. That's not open source, so I have no idea how it works, but the fact that it's a separate API (not JDBC) is rather telling.
It's also telling that the javadoc of JtaTransactionManager says that there are only 2 known implementations, and that these implementations steer quite close to the definitions in JTA.
Straight from that javadoc:
WebSphere-specific PlatformTransactionManager implementation that delegates to a UOWManager instance, obtained from WebSphere's JNDI environment.
So, JNDI then. "Voodoo skip JDBC talk directly to the database magic" indeed.

Do I need to close connection manually in spring boot data jpa + hibernate

I've developed an application using spring boot and I also use spring data jpa hibernate I also use hikaricp for connection pooling. I need to to know do I need to manually close the connection after every crud operation ?
there are three layers model , repository, service and controller
#Override
public void delete(int id) {
try {
notificationRepository.deleteById(id);
}
finally {
//This code not working this is for explanation purpose and I need to know if I need to
//manually close connection then how can I do it
notificationRepository.close();
}
}
Well nice to meet a SLIIT undergraduate , Answer to your question is closing the connection will handle automatically .If you close your connection after every operation then your application performance will be decrease heavily.Only thing you want to ensure is usage of #Transactional annoation in your business(Service) layer,apart from that you don't wan't do anything manually.

Spring + Hibernate+ HikariCP: how to handle DB connection while doing long running REST call?

I have a project running on Spring Boot 1.3.8, Hikari CP 2.6.1 and Hibernate (Spring ORM 4.2.8). The code on service layer looks like this:
public void doStuff() {
A a = dao.findByWhatever();
if (a.hasProperty()) {
B b = restService.doRemoteRequestWithRetries(); // May take long time
}
a.setProp(b.getSomethig());
dao.save(b);
}
Hikari configuration has this: spring.datasource.leakDetectionThreshold=2000.
The problem is that external REST service is quite slow and often takes 2+ seconds to respond, as a result we see a lot of java.lang.Exception: Apparent connection leak detected which are nothing else but false negatives, though the problem can be clearly seen: we hold DB connection for the time we executing rest request.
The question would be: how to properly decouple DB and REST stuff? Or how to tell hibernate to release connection in between? So that we return DB connection to pool while waiting for REST response.
I have tried setting hibernate.connection.release_mode=AFTER_TRANSACTION and it kind of helps, at least we do not have connection leak exceptions. The only problem is that our tests started showing this:
2018-04-17 15:48:03.438 WARN 94029 --- [ main] o.s.orm.jpa.vendor.HibernateJpaDialect : JDBC Connection to reset not identical to originally prepared Connection - please make sure to use connection release mode ON_CLOSE (the default) and to run against Hibernate 4.2+ (or switch HibernateJpaDialect's prepareConnection flag to false`
The tests are using injected DAO to insert records in DB and later check them via application API. They are not annotated with #Transactional and the list of listeners looks like this:
#TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
TransactionDbUnitTestExecutionListener.class
})
Any ideas what could be the problem with tests?
In the code
public void doStuff() {
A a = dao.findByWhatever();
if (a.hasProperty()) {
B b = restService.doRemoteRequestWithRetries(); // May take long time
}
a.setProp(b.getSomethig());
dao.save(b);
}
I see three tasks here - fetching entity A, connecting to remote service and updating entity A. And all these are in same transaction, so the underlying connection will be held till the method is complete.
So the idea is to split the tasks one and three into separate transactions, there by allowing the connection to be releases before making the call to remote service.
Basically, with spring boot you need to add spring.jpa.open-in-view=false. This will not register OpenEntityManagerInViewInterceptor and thus entityManager (in-turn connection) is not bound to the current thread/request.
Subsequently, split the three tasks into separate methods with #Transactional. This helps us bind the entityManager to the transaction scope and releasing connection at end of transaction method.
NOTE: And do ensure that there isn't any transaction started/in progress before (i.e., caller - like Controller etc) calling these methods. Else the purpose is defeated and these new #Transactional methods will run in the same transaction as before.
So the high-level approach could look like below:
In spring boot application.properties add property spring.jpa.open-in-view=false.
Next you need to split doStuff method into three methods in new service class. Intent is to ensure they use different transactions.
First method with #Transactionalwill call A a = dao.findByWhatever();`.
Second method makes remote call.
Third method with #Transactionalwill call rest of the code with JPA merge or hibernate saveOrUpdate on objecta`.
Now Autowired this new service in your current code and call the 3 methods.

JDBC distributed transaction and explicit rollback/commit

I'm working on an existing project that's configured for distributed transaction.
The project is using Hibernate but for some historical reasons, the part on which I'm working on uses JDBC and needs to stay that way.
To get a connection I have to call an API which gives me back the JDBC connection of the hibernate session.
I need to wrap up some updates/inserts in one transaction so here's what I'm doing :
Set autoCommit to false on my connection.
Do my inserts (prepare statements, execute query)
Call commit.
At commit, I get an SQLException because apparently it's not allowed to call commit/rollback explicitely with distributed transactions. I should state that changing the datasource configuration to non XA is not an option.
Any ideas how I might get around this ?
connexionDiff.setAutoCommit(false);
psInsertLiv = connexionDiff.prepareStatement(reqInsertLivraison);
psInsertLivHisto = connexionDiff.prepareStatement(reqInsertLivraisonHisto);
psSequence = connexionDiff.prepareStatement(reqCleLivraison);
ps = connexionDiff.prepareStatement(requeteRelivraison);
rs = ps.executeQuery();
while(rs.next()) {
rsSequence = psSequence.executeQuery();
while ( rsSequence.next() ) {
sequenceLivraison = rsSequence.getInt(1);
}
psInsertLiv.setInt(1, sequenceLivraison);
psInsertLiv.setInt(2, rs.getInt(1));
psInsertLiv.executeUpdate();
psInsertLivHisto.setInt(1, sequenceLivraison);
psInsertLivHisto.setInt(2, rs.getInt(1));
psInsertLivHisto.executeUpdate();
connexionDiff.commit();
}
} catch (SQLException ex) {
try{
connexionDiff.rollback();
}catch {
//......
}
} finally {
//.....
}
Thx
As you are using a XA connection, you surely are managing your transactions using JTA.
If it is a standalone JTA, get the UserTransaction and call begin and commit there. If it is inside an Application Server, use the transactional annotation or whatever the app server gives you to manage transactions. Look at this page to get an idea of how it is done in JavaEE 6.
If you are using Spring, you can also use the transactional annotation to wrap your code inside a transaction. Here is the relevant documentation.
The transaction management should be the same no matter if you are using Hibernate or plain JDBC. So check how it is done when it is using Hibernate in your project, and follow the same steps.

Testing the database connection with spring and hibernate

I'm currently working on a java application. It's a standalone client with Spring and Hibernate. Also C3P0.
In the previous version we used a standard user(hardcoded in the configuration file) for the database connection but now we changed it so that every user has to provide his own credentials.
The beans with the code for the database are basically created on-demand.
I changed the XML-files and added a postprocessor which sets the credentials as well as some connection settings. It looks similar to this now:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
configurer = new PropertyPlaceholderConfigurer();
// properties are retrieved from a private method
configurer.setProperties(getProperties());
context.addBeanFactoryPostProcessor(configurer);
context.setConfigLocations(new String[] { "first.xml","second.xml" });
context.refresh();
return context.getBean("myClass", MyClass.class);
This all works as expected but now we reach the part where I'm currently stuck.
I want to provide a test functionality for the connection, so that the user can click a button and then is told if his credentials were accepted or not.
My first idea was to do a simple select on the database. Sifting through the logs however, I noticed that Spring tries to connect to the database during the refresh() (or rather the instantiation of the bean) anyway. I can see exceptions in the logs, for example: java.sql.SQLException: Connections could not be acquired from the underlying database!
Unfortunately, Spring doesn't seem to actually care. The exceptions are logged away but refresh() finishes and is not throwing any exceptions because of this. I had hoped that I could simply catch the exception and then I would know that the connection failed.
I could just do the select as planned, but I want to limit the connection attempts as much as possible, because the database server will block the user after several attempts. Even permanently if there are to many attempts(already had some fun with that, before I changed the settings for the connection pool).
My searches regarding this problem came up with practically nothing. Is there a way to get the exception somehow? Or does Spring provide an API of sorts that would tell me about the connection error during the instantiation/refresh?
Failing that, any ideas for an alternative approach? Preferably one that needs only a single attempt to determine if a connection is possible.
Edit: For anyone interested: I went with the suggestion from Santosh and implemented a connection test in JDBC.
Unfortunately there seems to be no easy way to make use of the database errors/exceptions encountered during the bean instantiation.
The kind of functionality you are looking for would be very tricky to accomplish using spring+hibernate.
The connection properties are set at the session-factory level and if credentials are incorrect, the session-factory is not instantiated.
Quoting #Bozo from his answer here.
What you can do is extend LocalSessionFactoryBean and override the
getObject() method, and make it return a proxy (via
java.lang.reflect.Proxy or CGLIB / javassist), in case the
sessionFactory is null. That way a SessionFactory will be injected.
The proxy should hold a reference to a bare SessionFactory, which
would initially be null. Whenever the proxy is asked to connect, if
the sessionFacotry is still null, you call the buildSessionFactory()
(of the LocalSessionFactoryBean) and delegate to it. Otherwise throw
an exception. (Then of course map your new factory bean instead of the
current)
There is also a simple and rudimentary approach wherein before creating ClassPathXmlApplicationContext, simply try to obtain a connection using raw JDBC calls. If that succeed then proceed or else give use appropriate message.
You can limit the connection attempts here as you are in full control.

Categories