Perform commit(), rollabck(), setAutoCommit(false) on JDBC Connection from CMT JTA - jdbc

I have created glassfish connection pool with ResourceType as ConnectionPoolDataSource.So, glassfish will use the native connection pool implementation for connection pooling. I am not using XADatasource ResourceType as I don't want to perform any distributed transactions.
My application requires the use of TEMPERORY MYSQL table creation at run time. So I am using
the below code to get the connection from JNDI Datasource of glassfish.
#Resource(mappedName = "jdbc/xxxxx")
private DataSource dataSource;
public Connection getConnection() throws SQLException {
Connection con = dataSource.getConnection();
return con;
}
Now, My question is, Can I perform setAutoCommit(false), commit() and rollback(), close() on this Connection object????
In forum, I read that, we should not call these methods on Connection object, if we get the Connection from Container Managed Distributed Transaction (XADataSource) as its involved in distributed transactions.
But, I am getting this connection from non-distributed transactions.So, I can call those methods right???
Other question is, after performing db operations, If I call con.close(), will this connection go back to the connection pool again?

Related

Optimizing oracle database connection acquisition time on Spring boot

I have an Spring boot application that runs several services and uses oracle database. The database is maintained properly, indexes also added up, and when executing SQL statements directly on SQL Developer, it's getting executed in milliseconds.
In the spring boot, I use this to execute the statement:
Session session = sessionFactory.getCurrentSession();
session.createQuery("from Table where id = :id and status = 0").setParameter("id", id);
Here is the config properties for the database:
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
hibernate.hbm2ddl.auto=none
Here is the way of datasource initialization in the datasource config:
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource(url, name, pw);
dataSource.setDriverClassName(...);
return dataSource;
}
Recently, it takes so much time to acquire the database connection, it can go up to 10 seconds jut for acquiring connection. I don't think there is any problem in the query. As from the database side, it's also ok. The resources of server which running this service and the database server are also fine, as well as the network. The servers also have auto-scale feature to create new instance when the memory getting low. I just can't figure out what should I do to improve the acquisition time. Could you please help?

org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection

I sometimes notice below mentioned error in my springboot app logs.
org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
I suspect it could be because of exception thrown from #Transactional method ( only at times though).
Is it Ok to throw excaption from #Transactional method? or it is a bad practice?
Here is my service layer code
#Override
#Transactional
public void updateMessageStatus(String status, String sid, String errorCode) throws NotFoundException {
OutgoingMessage outgoingMessage = outgoingMessageRepository.findByResourceSid(sid);
if (outgoingMessage == null) {
throw new NotFoundException(ErrorCode.MESSAGE_NOT_FOUND, sid);
}
outgoingMessage.setStatus(status);
outgoingMessage.setUpdatedTime(Calendar.getInstance().getTime());
outgoingMessageRepository.save(outgoingMessage);
}
This usually happens when app is idle for longer time than the server’s connection timeout period.
So if a connection has been idle longer than this timeout value, it will be dropped by the server. By default, Hibernate uses its internal database connection pool library,
keeping the connection open to be reused later.
Hibernate reuses the idle connection which was already dropped by the server, hence we get JDBCConnectionExceptionis error.
What I noticed is even with the following database auto-reconnect setup should not work in this case.
spring.datasource.validation-query=select 1
spring.datasource.testOnBorrow=true
May be need to increase the pool size OR Entity Manager needs to be closed once the transaction is done.
spring.datasource.hikari.maximum-pool-size=10.
Please let me know if this worked for you.

Is it possible to have a remote pooled JMS connection factory (WildFly 10)?

I have a remote java client which looks up a JMS connection factory on Wildfly 10, and everything works fine as expected. It is just a test program; a simple JMS chat system. When I start more than one instance of the chat client sometimes the following message appears:
WARN: AMQ212051: Invalid concurrent session usage. Sessions are not supposed to be used by more than one thread concurrently.
Followed by a trace.
Now I want to fix this warning, therefore I need a pooled connection factory. But the pooled connection factory isn't available remotely (and as I read it shouldn't be available remotely).
What can I do to fix this warning when I want to start multiple JMS chat clients locally?
I know that the error won't appear when I just different machines.
This is the working non-pooled remote code (but with warning)
final Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
try {
context = new InitialContext(properties);
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
jmsContext = connectionFactory.createContext("quickstartUser", "quickstartPwd1!");
} catch (NamingException e) {
e.printStackTrace();
}
The problem isn't caused by not using a pooled connection factory and won't be solved by using a pooled connection factory. The problem is the way your application is using the same JMS session concurrently between multiple threads (as the WARN message indicates). The stack-trace which is logged will show you which class & method is triggering the WARN message.
You need to ensure that your application does not use the same JMS session concurrently between multiple threads. You can do this by giving each thread its own JMS session or by setting up concurrency controls around the session so that only one thread at a time can access it.

Spring jdbctemplate is it required to close the connection

I am fetching the connection in jdbctemplate in below fashion:-
getJdbcTemplate().getDataSource().getConnection()
Is it necessary to close the connection fetched in the above manner? The spring JDBCTemplate API states that connection closures will be handled automatically , so I am not sure if this is happening correctly.
http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html
When you are obtaining the DataSource from the JdbcTemplate and use that to obtain a Connection you are basically completely bypassing the JdbcTemplate. You now have a very complex way of obtaining a new Connection. Because this connection isn't managed by Spring but yourself you also need to close it and apply exception handling.
It is better to use the ConnectionCallback instead to get a Connection. The JdbcTemplate will then manage the Connection and do all resource handling.
getJdbcTemplate().execute(new ConnectionCallback<Void>() {
public Void doInConnection(Connection conn) {
// Your JDBC code here.
}
});
It would even better to use one of the other JdbcTemplate methods and write proper code which would save you from messing with plain JDBC code at all.

Spring JDBC and Connection Object

I'm building an app using a proprietary api. To connect to the database I use a method that returns a Connection object and then on that connection I call the appropriate methods to run queries on the database for example....
Connection conn = JdbcServiceFactory.getInstance().getDefaultDatabase().getConnectionManager().getConnection();
PreparedStatement ps = conn.prepareStatement("select * from test");
If I'm choosing to use Spring MVC 3 for my next project, what must I do to get the database connection setup? From what I've seen in the documentation, I have use the datasource tag in the container and pass a URL, username, and password. As shown, I currently don't have to do that to get the connection.
At the end of the day your proprietary API must access some database (available on some server), using some credentials. You just don't see this. In Spring you must first define some DataSource. Either use existing librariess like dbcp, bonecp or c3p0 or take one provided by your application server via jndi. As long as they implement DataSource interface, it doesn't matter what approach you choose. Too much to explain each one in detail.
Once you have DataSource bean set up, I strongly recommend using JdbcTemplate which simplifies your JDBC code a lot, e.g:
List<Map<String,Object>> res = jdbcTemplate.queryForList("select * from test");
...and much more.
UPDATE: If you want to use your existing legacy API with modern frameworks expecting DataSource (pretty much all of them), implementing DataSource adapter is trivial (remaining methods can stay unimplemented, throwing UnsupportedOperationException):
public class LegacyDataSourceAdapter implements DataSource {
#Override
public Connection getConnection() throws SQLException {
return JdbcServiceFactory.getInstance().getDefaultDatabase().getConnectionManager().getConnection();
}
#Override
public Connection getConnection(String username, String password) throws SQLException {
return getConnection();
}
//other methods are irrelevant
}
Now just create an instance of LegacyDataSourceAdapter (maybe as a Spring bean) and pass it to JdbcTemplate, Hibernate, myBatis...
BTW you have here some first class example of bad API design:
Connection conn = JdbcServiceFactory.
getInstance().
getDefaultDatabase().
getConnectionManager().
getConnection();

Resources