In application start up , I am loading data source as shown below code -
#Bean(name = "dataSource")
public DataSource getDataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource ();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/usersdb");
dataSource.setUsername("root");
dataSource.setPassword("secret");
return dataSource;
}
So here I would like to verify that whether the data source loaded properly,
One possible way could be datasource.getConnection() before return but here I have to create unnecessary connection object which is having some high cost.
Please help me to find a way to verify that data source has been instantiated properly. I have heard something about validate query but not sure how it would work. please suggest.
It is impossible to validate DataSource without test connection.
First of all, you define bean with singleton scope by default so single DataSource will be created with single check.
Secondly, do not worry about the creation cost of Connection because you use PooledDataSource. 'Pooled' means that pool of connections exists that is why physical connection once created can be used many times by the application.
The validate query (or test query) is used to check if existing Connection was broken. See Configuring Connection Testing for more details.
Related
I have a small commandline utility. My code is simple I create a SingleConnectionDataSource and pass it along till it is needed and I do
ds.getConnection()
Uptil now it was working and I would get a connection and would use it but some months back this stopped working and threw an exception
Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Connection was closed in SingleConnectionDataSource. Check that user code checks should Close() before closing Connections, or set 'suppress Close' to 'true'
Now when i create the datasource I added
((SingleConnectionDataSource)db).setSuppressClose(true);
and now it works fine ( as the exception suggested)
My question is why did it stop working or how was it working before, why would it be closed even at first user. As per the java doc it is supposed to be
Implementation of SmartDataSource that wraps a single JDBC Connection
which is not closed after use.
So I should be the one closing it to begin with at the end of the process.
So technically, I have a question of why did i get the problem that i have already solved but i don't understand when did this start coming.
Edit -- It behaves like this on SQL server only and not Oracle.
Edit2 -- Sorry, In oracle it uses a different way so it works
JdbcTemplate template = new JdbcTemplate(dataSource);
So either use SuppressClose(true) or use JdbcTemplate
We would need to know your database and application server to answer definitively, but my guess is that one or the other was closing the connection after a timeout. Why are you trying to manage the connection to begin with however? Many application servers provide a connection pool.
This is a partial answer to my own question: why would it close the connection before first use?
in SingleConnectionDatasource getConnection calls
/**
* Initialize the underlying Connection via the DriverManager.
*/
public void initConnection() throws SQLException {
if (getUrl() == null) {
throw new IllegalStateException("'url' property is required for lazily initializing a Connection");
}
synchronized (this.connectionMonitor) {
closeConnection();
this.target = getConnectionFromDriver(getUsername(), getPassword());
prepareConnection(this.target);
if (logger.isDebugEnabled()) {
logger.debug("Established shared JDBC Connection: " + this.target);
}
this.connection = (isSuppressClose() ? getCloseSuppressingConnectionProxy(this.target) : this.target);
}
}
This basically, creates a closed connection to begin with. Which makes it more intriguing why did it work in the first place. This class has been with the same initConnection() method since its inception ( as far as I can see on github).
When i tried to create a HTable instance in this way.
Configuration conf = HBaseConfiguration.create();
HConnection conn = HConnectionManager.getConnection(conf);
conn.getTable("TABLE_NAME");
Then i got a Exception.
#Override
public HTableInterface getTable(TableName tableName, ExecutorService pool) throws IOException {
if (managed) {
throw new IOException("The connection has to be unmanaged.");
}
return new HTable(tableName, this, pool);
}
So , i wants to know the concrete reflection of managed and 'unmanaged' Hconnection?
Before call HConnectionManager.getConnection you have to create connection using HConnectionManager.createConnection passing to it earlier created HBaseConfiguration instance. HConnectionManager.getConnection return connection which is already exists. A bit of HConnectionManager javadoc about how it handle connection pool:
This class has a static Map of HConnection instances keyed by Configuration; all invocations of getConnection(Configuration) that pass the sameConfiguration instance will be returned the sameHConnection instance
In your case, you can simply create connection using HConnectionManager.createConnection and use returned connection to open HTable
Edit:
#ifiddddddbest, I found javadocs for HConnectionImplementation which has description of managed flag(may be it will help you to understand):
#param managed If true, does not do full shutdown on close; i.e.
cleanup of connection to zk and shutdown of all services; we just
close down the resources this connection was responsible for and
decrement usage counters. It is up to the caller to do the full
cleanup. It is set when we want have connection sharing going on --
reuse of zk connection, and cached region locations, established
regionserver connections, etc. When connections are shared, we have
reference counting going on and will only do full cleanup when no more
users of an HConnectionImplementation instance.
In the newer versions of HBase(>1.0), managed flag was disappeared and all connection management now on client side,e.g. client responsible to close it and if it do this, it close all internal connections to ZK,to HBase master, etc, not only decrease reference counter.
My problem is straightforward. I want to access some data from the database when the application loads on Tomcat. To do something at that point in time I use #PostConstruct (which does its job properly).
However, in that method I make 2 separate connections to the DB: one for bringing a list of entities and another for adding them into a common library. The second step implies some behind-the-scenes queries for resolving some lazy-loading associations. Here is the code snippet:
#Override
#PostConstruct
public void populateLibrary() {
// query for the Book Descriptors - 1st query works!!!
List<BookDescriptor> bookDescriptors= bookDescriptorService.list();
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
// resolving some lazy-loading associations - 2nd query fails!!!
for (BookDescriptor book: bookDescriptors) {
library.addEntry(book);
}
transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
1st query works while the 2nd fails, as I wrote in the comments. The failure gives:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.freightgate.domain.SecurityFiling_$$_javassist_7.getSfSubmissionType(SecurityFiling_$$_javassist_7.java)
at com.freightgate.dao.SecurityFilingTest.test(SecurityFilingTest.java:73)
Which is very odd since I explicitly opened and closed a transaction. However, if I inspect some details of how the 1st query works it seems like behind the scenes the session is bound to AbstractLazyInitializer class.
I resolved my problem by abstracting away the functionality from the for loop into a separate service class that is annotated with #Transactional(readOnly = true). Still I'm puzzled as to why the approch that I posted here fails.
If anyone has some hints, I'd be very happy to hear them.
You load entities in a first session, then close this session, then open a new session, and try to lazy-load collections of the entities. That can't work.
For lazy-loading to work, the entity must be attached to an open session. Just opening another session doesn't make any entity you have loaded before attached to this new session. In the meantime, some other transaction could have radically changed the database, the entity could not exist anymore...
The best solution is what you have done. Encapsulate evrything into a single transactional service. You could also have open the transaction before calling the first service, but why handle transactions programmatically, since Spring does it for you declaratively?
I am pretty sure that somebody else already asked this question, but I still couldn't find a satisfactory answer to it.
So, here is my scenario: I want to use the Oracle's JDBC driver implicit statement caching (documented here: http://docs.oracle.com/cd/B28359_01/java.111/b31224/stmtcach.htm#i1072607)
I need to use the connections from a 3rd party JDBC pool provider (to be more specific, Tomcat JDBC) and I have no choice there.
The problem is that the way to enable the implicit caching is a two-step process (accordingly to the documentation):
1.
Call setImplicitCachingEnabled(true) on the connection
or
Call OracleDataSource.getConnection with the ImplicitCachingEnabled
property set to true. You set ImplicitCachingEnabled by calling
OracleDataSource.setImplicitCachingEnabled(true)
2.
In addition to calling one of these methods, you also need to call
OracleConnection.setStatementCacheSize on the physical connection. The
argument you supply is the maximum number of statements in the cache.
An argument of 0 specifies no caching.
I can live with 1 (somehow I can configure my pool to use the OracleDataSource as a primary connection factory and on that I can set the OracleDataSource.setImplicitCachingEnabled(true)).
But at the second step, I already need the connection to be present in order to call the setStatementCacheSize.
My question is if there is any possibility to specify at the data source level a default value for the statementCacheSize so that I can get from the OracleDataSource connections that are already enabled for implicit caching.
PS: some related questions I found here:
Oracle jdbc driver: implicit statement cache or setPoolable(true)?
Update (possible solution):
Eventually I did this:
Created a native connection pool using oracle.jdbc.pool.OracleDataSource.
Created a tomcat JDBC connection pool using org.apache.tomcat.jdbc.pool.DataSource that uses the native one (see the property dataSource).
Enabled via AOP a poincut so that after the execution of 'execution(public java.sql.Connection oracle.jdbc.pool.OracleDataSource.getConnection())' I pickup the object and perform the setting I wanted.
The solution works great; I am just unhappy that I had to write some boilerplate to do it (I was expecting a straight-forward property).
The white paper Oracle JDBC Memory Management says that
The 11.2 drivers also add a new property to enable the Implicit Statement Cache.
oracle.jdbc.implicitStatementCacheSize
The value of the property is an
integer string, e.g. “100”. It is the initial size of the statement
cache. Setting the property to a positive value enables the Implicit
Statement Cache. The default is “0”. The property can be set as a
System property via -D or as a connection property via getConnection.
You can only change statement cache size through OracleConnection.setStatementCacheSize method.
Instead of modifying your application to call OracleConnection.setStatementCacheSize on every connection, you can create a JDBC interceptor.
#Override
public void reset(ConnectionPool pool, PooledConnection connection) {
if (connection == null) {
return;
}
Connection original = connection.getConnection();
if (!(original instanceof OracleConnection)) {
return;
}
try {
if (!((OracleConnection) original).getImplicitCachingEnabled() && implicitCachingEnabled) {
((OracleConnection) original).setImplicitCachingEnabled(implicitCachingEnabled);
log.info("Activated statement cache");
((OracleConnection) original).setStatementCacheSize(statementCacheSize);
log.info("Statement cache size set to " + statementCacheSize);
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
}
I am looking to retrofit our existing transaction API to use Spring’s PlatformTransactionManager, such that Spring will manage our transactions. I chained my DataSources as follows:
DataSourceTransactionManager - > LazyConnectionDataSourceProxy - > dbcp.PoolingDataSource - > OracleDataSource
In experimenting with the DataSourceTransactionManager , I have found that where PROPAGATION_REQUIRES_NEW is used, it seems that Spring’s transaction management requires that the transactions be committed/rolled back in LIFO fashion, i.e. you must commit/rollback the most recently created transactions first.
Example:
#Test
public void testSpringTxns() {
// start a new txn
TransactionStatus txnAStatus = dataSourceTxnManager.getTransaction(propagationRequiresNewDefinition); // specifies PROPAGATION_REQUIRES_NEW
Connection connectionA = DataSourceUtils.getConnection(dataSourceTxnManager.getDataSource());
// start another new txn
TransactionStatus txnBStatus = dataSourceTxnManager.getTransaction(propagationRequiresNewDefinition);
Connection connectionB = DataSourceUtils.getConnection(dataSourceTxnManager.getDataSource());
assertNotSame(connectionA, connectionB);
try {
//... do stuff using connectionA
//... do other stuff using connectionB
} finally {
dataSourceTxnManager.commit(txnAStatus);
dataSourceTxnManager.commit(txnBStatus); // results in java.lang.IllegalStateException: Cannot deactivate transaction synchronization - not active
}
}
Sadly, this doesn’t fit at all well with our current transaction API which allows you to create transactions, represented by Java objects, and commit them in any order.
My question:
Am I right in thinking that this LIFO behaviour is fundamental to Spring’s transaction management (even for completely separate transactions)? Or is there a way to tweak its behaviour such that the above test will pass?
I know the proper way would be to use annotations, AOP, etc. but at present our code is not Spring-managed, so it is not really an option for us.
Thanks!
yes,I have met the same problems below when using spring:
java.lang.IllegalStateException: Cannot deactivate transaction synchronization - not active.
According above,Spring’s transaction management requires that the transactions be committed/rolled back in LIFO fashion(stack behavior).The problem disappear.
thanks.
Yes, I found this same behavior in my own application. Only one transaction is "active" at a time, and when you commit/rollback the current transaction, the next active transaction is the next most recently started transaction (LIFO/stack behavior). I wasn't able to find any way to control this, it seems to be built into the Spring Framework.