Code Example

Other examples of Tomcat configuration for JDBC usage can be found in the Tomcat documentation.

Plain Ol’ Java

Here is a simple example of how to create and use a data source.

 

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.Statement;

 

import org.apache.tomcat.jdbc.pool.DataSource;

import org.apache.tomcat.jdbc.pool.PoolProperties;

 

public class SimplePOJOExample {

 

public static void main(String[] args) throws Exception {

PoolProperties p = new PoolProperties();

p.setUrl(“jdbc:mysql://localhost:3306/mysql”);

p.setDriverClassName(“com.mysql.jdbc.Driver”);

p.setUsername(“root”);

p.setPassword(“password”);

p.setJmxEnabled(true);

p.setTestWhileIdle(false);

p.setTestOnBorrow(true);

p.setValidationQuery(“SELECT 1”);

p.setTestOnReturn(false);

p.setValidationInterval(30000);

p.setTimeBetweenEvictionRunsMillis(30000);

p.setMaxActive(100);

p.setInitialSize(10);

p.setMaxWait(10000);

p.setRemoveAbandonedTimeout(60);

p.setMinEvictableIdleTimeMillis(30000);

p.setMinIdle(10);

p.setLogAbandoned(true);

p.setRemoveAbandoned(true);

p.setJdbcInterceptors(

“org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;”+

“org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer”);

DataSource datasource = new DataSource();

datasource.setPoolProperties(p);

 

Connection con = null;

try {

con = datasource.getConnection();

Statement st = con.createStatement();

ResultSet rs = st.executeQuery(“select * from user”);

int cnt = 1;

while (rs.next()) {

System.out.println((cnt++)+”. Host:” +rs.getString(“Host”)+

” User:”+rs.getString(“User”)+” Password:”+rs.getString(“Password”));

}

rs.close();

st.close();

} finally {

if (con!=null) try {con.close();}catch (Exception ignore) {}

}

}

 

}

As a Resource

And here is an example on how to configure a resource for JNDI lookups

 

<Resource name=”jdbc/TestDB”

auth=”Container”

type=”javax.sql.DataSource”

factory=”org.apache.tomcat.jdbc.pool.DataSourceFactory”

testWhileIdle=”true”

testOnBorrow=”true”

testOnReturn=”false”

validationQuery=”SELECT 1″

validationInterval=”30000″

timeBetweenEvictionRunsMillis=”30000″

maxActive=”100″

minIdle=”10″

maxWait=”10000″

initialSize=”10″

removeAbandonedTimeout=”60″

removeAbandoned=”true”

logAbandoned=”true”

minEvictableIdleTimeMillis=”30000″

jmxEnabled=”true”

jdbcInterceptors=”org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;

org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer”

username=”root”

password=”password”

driverClassName=”com.mysql.jdbc.Driver”

url=”jdbc:mysql://localhost:3306/mysql”/>

Asynchronous Connection Retrieval

The Tomcat JDBC connection pool supports asynchronous connection retrieval without adding additional threads to the pool library. It does this by adding a method to the data source called Future<Connection> getConnectionAsync(). In order to use the async retrieval, two conditions must be met:

  • You must configure the fairQueue property to be true.
  • You will have to cast the data source to org.apache.tomcat.jdbc.pool.DataSource

An example of using the async feature is show below.

Connection con = null;

try {

Future<Connection> future = datasource.getConnectionAsync();

while (!future.isDone()) {

System.out.println(“Connection is not yet available. Do some background work”);

try {

Thread.sleep(100); //simulate work

}catch (InterruptedException x) {

Thread.currentThread().interrupt();

}

}

con = future.get(); //should return instantly

Statement st = con.createStatement();

ResultSet rs = st.executeQuery(“select * from user”);

Interceptors

Interceptors are a powerful way to enable, disable or modify functionality on a specific connection or its sub components. There are many different use cases for when interceptors are useful. By default, and for performance reasons, the connection pool is stateless. The only state the pool itself inserts are defaultAutoCommit, defaultReadOnly, defaultTransactionIsolation, defaultCatalog if these are set. These 4 properties are only set upon connection creation. Should these properties be modified during the usage of the connection, the pool itself will not reset them.

An interceptor has to extend the org.apache.tomcat.jdbc.pool.JdbcInterceptor class. This class is fairly simple, You will need to have a no arg constructor

 

public JdbcInterceptor() {

}

 

When a connection is borrowed from the pool, the interceptor can initialize or in some other way react to the event by implementing the

 

public abstract void reset(ConnectionPool parent, PooledConnection con);

 

method. This method gets called with two parameters, a reference to the connection pool itself ConnectionPool parent and a reference to the underlying connection PooledConnection con.

When a method on the java.sql.Connection object is invoked, it will cause the

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable

method to get invoked. The Method method is the actual method invoked, and Object[] args are the arguments. To look at a very simple example, where we demonstrate how to make the invocation to java.sql.Connection.close() a noop if the connection has been closed

if (CLOSE_VAL==method.getName()) {

if (isClosed()) return null; //noop for already closed.

}

return super.invoke(proxy,method,args);

There is an observation being made. It is the comparison of the method name. One way to do this would be to do “close”.equals(method.getName()). Above we see a direct reference comparison between the method name and static final String reference. According to the JVM spec, method names and static final String end up in a shared constant pool, so the reference comparison should work. One could of course do this as well:

if (compare(CLOSE_VAL,method)) {

if (isClosed()) return null; //noop for already closed.

}

return super.invoke(proxy,method,args);

 

The compare(String,Method) will use the useEquals flag on an interceptor and do either reference comparison or a string value comparison when the useEquals=true flag is set.

Pool start/stop

When the connection pool is started or closed, you can be notified. You will only be notified once per interceptor class even though it is an instance method. and you will be notified using an interceptor currently not attached to a pool.

public void poolStarted(ConnectionPool pool) {

}

 

public void poolClosed(ConnectionPool pool) {

}

 

When overriding these methods, don’t forget to call super if you are extending a class other thanJdbcInterceptor

Configuring interceptors

Interceptors are configured using the jdbcInterceptors property or the setJdbcInterceptors method. An interceptor can have properties, and would be configured like this

 

String jdbcInterceptors=

“org.apache.tomcat.jdbc.pool.interceptor.ConnectionState(useEquals=true,fast=yes)”

Interceptor properties

Since interceptors can have properties, you need to be able to read the values of these properties within your interceptor. Taking an example like the one above, you can override the setProperties method.

 

public void setProperties(Map<String, InterceptorProperty> properties) {

super.setProperties(properties);

final String myprop = “myprop”;

InterceptorProperty p1 = properties.get(myprop);

if (p1!=null) {

setMyprop(Long.parseLong(p1.getValue()));

}

}

Getting the actual JDBC connection

Connection pools create wrappers around the actual connection in order to properly pool them. We also create interceptors in these wrappers to be able to perform certain functions. If there is a need to retrieve the actual connection, one can do so using the javax.sql.PooledConnection interface.

Connection con = datasource.getConnection();

Connection actual = ((javax.sql.PooledConnection)con).getConnection();

Advanced usage
Building

Get industry recognized certification – Contact us

keyboard_arrow_up
Open chat
Need help?
Hello 👋
Can we help you?