I'm using a Connection via severals pools :
DataSource ds = initialContext.lookup("poolname1");
Connection cn = ds.getConnection();
submethod1(cn);
submethod2(cn);
void submethod1(Connection cn)
{
// using connection
// ..
}
My question is: how to log "poolname" in submethods ? or similar informations about DataSource.
Perhaps this will help
getClientInfo()
or
getMetaData()
as mentionned in the Official Java Doc
The poolname in your example is actually a JNDI Name. This is generally a configuration which is configured in resource definition (e.q under in tomcat config).
For your problem as #sourlcheck mentioned, its not possible as connection are not aware of their datasource.
Once way to solve your problem is to give label to the datasource. Most of the Pooled datasource implementations (e.q. C3P0) offer a setter for setting up a name to the datasource. In C3P0 the datasournce class is ComboPooledDataSource and the method is getDataSourceName(). Once you get this name, it remains the same throughout its life cycle. But off course you need to introduce third party library
You can't log "poolname" in methods that receive Connection. Connections don't know if they are pooled or served directly from non-pooling DataSource.
Also you can create and access your pool in many different ways, not all of them guaranteeing existence of "poolname".
Related
I wondered how works method getConnection() at DataSource? I assume that DataSource calling DriverManager.getConnection every time when we call DataSource.getConnection with our properties that we setting in DataSource. Is that true?
The answers to your question can be deduced from the DataSource javadoc.
"The DataSource interface is implemented by a driver vendor. There are three types of implementations:
Basic implementation -- produces a standard Connection object
Connection pooling implementation -- produces a Connection object that will automatically participate in connection pooling. This
implementation works with a middle-tier connection pooling manager.
Distributed transaction implementation -- produces a Connection object that may be used for distributed transactions and almost always
participates in connection pooling. This implementation works with a
middle-tier transaction manager and almost always with a connection
pooling manager."
Thus:
I wondered how works method getConnection() at DataSource?
It is vendor specific, and depends on the type of implementation that the vendor provides.
I assume that DataSource calling DriverManager.getConnection every time when we call DataSource.getConnection with our properties that we setting in DataSource. Is that true?
Not necessarily. For example, DataSource.getConnection() could return the same Connection object each time it is called. Or more plausibly, it could return a new Connection proxy for an underlying database pool connection that has been recycled. Furthermore, that DriverManager method is not necessarily called to get the connection.
If you want to know how a specific DataSource works, you would need to look at the vendor documentation ... or alternatively its source code.
I have a web application that currently uses c3p0 and Hibernate to connect to a Firebird 1.5 database.
I am facing a problem from time to time where the database just stops responding, even trying to manually restart the service doesn't have any effect, and it doesn't generate any logs, so I have to manually reboot the machine to get it working again.
I think that maybe Firebird hangs when the pool tries to acquire a specific number of connections or something like that. So, I need to test my app without connection pooling, to check if this is or is not the problem.
I can't simply remove c3p0 configs from persistence because this way Hibernate would use its own integrated connection pool. So how to do it?
The most flexible solution is to use an explicit DataSource, instead of configuring the connection pooling through Hibernate. One option to configure a non-pooling DataSource is by using DriverManagerDataSource:
#Override
protected Properties getProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
//log settings
properties.put("hibernate.hbm2ddl.auto", "update");
//data source settings
properties.put("hibernate.connection.datasource", newDataSource());
return properties;
}
protected ProxyDataSource newDataSource() {
DriverManagerDataSource actualDataSource = new DriverManagerDataSource();
actualDataSource.setUrl("jdbc:hsqldb:mem:test");
actualDataSource.setUsername("sa");
actualDataSource.setPassword("");
ProxyDataSource proxyDataSource = new ProxyDataSource();
proxyDataSource.setDataSource(actualDataSource);
proxyDataSource.setListener(new SLF4JQueryLoggingListener());
return proxyDataSource;
}
This way you can choose a pooling or a non-pooling DataSource.
To get a better understanding of you connection pooling resources usage, you can configure FlexyPool to collect metrics for:
concurrent connections
concurrent connection requests
data source connection acquiring time
connection lease time
maximum pool size
total connection acquiring time
overflow pool size
retries attempts
I found documentation for hibernate 3.3 and 4.3 that says:
Just replace the hibernate.connection.pool_size property with
connection pool specific settings. This will turn off Hibernate's
internal pool.
Hibernate will use its org.hibernate.connection.C3P0ConnectionProvider
for connection pooling if you set hibernate.c3p0.* properties
So remove hibernate.connection.pool_size and any hibernate.c3p0... properties from configuration, than connection pooling is disabled.
Adding to Vlad's answer:
If somebody still faces this:
Be sure to remove "hibernate-c3p0" from your classpath, if exists, since this will automatically enable MChange c3p0 connection pool.
Another option that, you can close the connection manually when closing the entity manager:
....
SessionImpl ses = (SessionImpl) session;
close(ses.connection());
try {
session.close();
} catch (Exception e) {
logger.error(e);
}
........
Note: the above manual closing will work with the default pool of hibernate, not hibernate default one.
Good Luck
In a CMT J2EE environement (Container Managed Transaction) what transaction / connection is used when I JDNI-lookup for a DataSource object and invoke DataSource.getConnection?
Is this connection part of the (potentially distributed) transaction? Does getConnection() return the same Connection every time I call it for the same DataSource object? I only know using Connections by the same EntityManager using native SQL statements.
It is something that keeps me puzzling. As I understood the SessionContext defines a transactional system that is used throught every time I use a datasource. I have the problem that inside a session bean a DataSource.getConnection() is used and this connection is then closed. If a problem is encountered SessionContext.setForRollBack(true) is issued.
Therefore how does the transactional context of a service relate to a DataSource?
If we spawn a new Connection each time a datasource is used or at least looked up, I have problems to understand things I already know. Any clarification would be wonderful. I know container managed transaction and other systems, but the actual behavior of DataSource is totally beyond me.
In Java EE a transaction is a concept that is not exclusive to databases, for example JMS connection sessions can also be part of container managed transaction. The idea is if one or more than one method is running under container managed transaction boundary, the container will commit or rollback the transaction as needed.
In data base related data source, there are multiple layers, fist is the managed pool of connection which is maintained by the container, second is the actual connection management of the database driver with the database, in Java a Connection is an abstraction for a session with a database and not a physical connection, that is managed by the driver.
With the above context, your questions could be addressed viz.:
what transaction / connection is used when I JDNI-lookup for a DataSource object and invoke DataSource.getConnection.
Under container managed transaction, though it is implementation dependent, a connection/session with the database is associated that is marked with the transaction boundary. The actual physical connection could be shared with the database by the driver but that is transparent to application as well as the container.
Is this connection part of the (potentially distributed) transaction? Does getConnection return the same Connection every time I call it for the same DataSource object?
Refer above, a Connection has no relation with the underlying socket to the database as opened by the driver. It is logically a separate session and if within transaction boundary, the same session is associated with the connection retrieved from the data source, how this is implemented is part of the container design
I have the problem that inside a session bean a DataSource.getConnection is used and this connection is then closed
In a pooled implementation for connection a Connection.close() has no impact, the connection is returned to the pool(http://commons.apache.org/proper/commons-dbcp/api-1.3/org/apache/commons/dbcp/PoolableConnection.html), this behaviour is similar for all pools. So clsing a connection does not necessarily disassociate it from container transaction boundary, though a connection should not be closed within container managed transaction. Similarly, commit, setAutoCommit, rollback must not be called from within CMT as this will issue the following command equivalent to the actual database and the behaviour of the transaction after that will undefined.
Have a look at the declaration of the #Resource annotation.
It includes a shareable attribute that allows you to specify connection sharing behaviour. It defaults to true, which means that you will get connection sharing automatically if you do nothing.
This attribute is also included in the XML schema for any resource-ref defined datasources that you may lookup using JNDI.
All resources (JDBC, JMS, ResourceManager) that are included during an invocation are enrolled in the current transaction. You may sometimes need to specify the use of XA for this to work correctly.
I have a large amount of legacy code that relies on being able to pass around a DataSource instead of a Connection object. I can see sample code for making a connection, ie:
Class.forName("org.apache.cassandra.cql.jdbc.CassandraDriver");
con = DriverManager.getConnection("jdbc:cassandra:root/root#localhost:9160/MyKeyspace");
However I can't see from the documentation any way to create a DataSource. Am I going to have to write my own DataSource to wrap the above code?
You can use BasicDataSource class of Apache Commons DBCP http://commons.apache.org/proper/commons-dbcp/ which is a DataSource implementation that can work with any JDBC driver. See usage example here http://www.kodejava.org/how-do-i-create-a-basicdatasource-object/
You can use the CassandraDataSource class.
https://code.google.com/a/apache-extras.org/p/cassandra-jdbc/source/browse/src/main/java/org/apache/cassandra/cql/jdbc/CassandraDataSource.java
I'm just starting to learn Jboss AP6 and I have a few questions:
I created Local Tx Datasource (MySql Database)and can access it in my code using JNDI.
Now I would like to create kind of Transaction Management resource inside of my Jboss AP.
1) Is there any JTA feature built in Jboss AP6?
2) Can I apply it to my local DataSource which I created?
3) Can you please point me to any documentation which explains how to configure it and use it in my code, ot is there any article which coversthese topics in depth?
I googled it for some period of time, but haven't found any useful documentation. I don't want to use Spring/Hibernate out of the box solution just Mysql and plain JTA.
JBoss AP6 support JTA 1.1
Yes you can
If you declareLocalTxDatasource, this is mean, than whenever you get
connection from this datasource this connection will participate in "current" transaction.
If you want to manupulate transaction yourself, without EJB for example, you must enject TransactionManager from JNDI.
Example
TransactionManager tm = (TransactionManager)context.lookup("java:/TransactionManager");
tm.begin();
try{
DataSource ds = context.lookup("java:/testDS");
connection = ds.getConnection()
//do useful work
connection.close();
tm.commit();
}catch(Exception e){
tm.rollback()
}