Professional Documents
Culture Documents
This paper describes the process of setting up a pooled data source, implemented by
Oracles latest JDBC architecture for pooled connections, the Universal Connection Pool UCP,
on Apache Tomcat 7 against on Oracle 11g XE database.
CONTENT
Abstract ............................................................................................................................... 2
Motivation........................................................................................................................... 2
Introduction ........................................................................................................................ 2
7.1
Previous Architectures................................................................................................. 3
7.2
7.3
Prequisites ................................................................................................................... 5
8.2
Datasource Configuration............................................................................................ 5
8.3
8.4
8.4.1
8.4.2
9.2
9.3
9.4
10 Conclusion ......................................................................................................................... 17
11 Acknowledgments............................................................................................................. 18
12 Readings ............................................................................................................................ 18
13 About the Autor ................................................................................................................ 18
by Volker Koster, MT AG
Seite 1
ABSTRACT
This paper describes the process of setting up a pooled data source, implemented by
Oracles latest JDBC architecture for pooled connections, the Universal Connection Pool UCP,
on Apache Tomcat 7 against on Oracle 11g XE database.
3
MOTIVATION
INTRODUCTION
What you are about to read here is a compilation of procedures and findings concerning the
topic of UCP on Tomcat 7 resulting from a recent BPM software assessment we conducted
here at MT.
While the BPM software itself was not even certified yet for Tomcat 7 and Oracle 11g, we
still figured that this will be our preferred productive setup in a not to distant future. So why
not just go for it?
We had a minor issue with UCP working in our specific environment: The connection pool
was not instantiated with configured number of upfront connections.
Our work around consisted of writing our own custom resource factory for Tomcat. This
work around will be described in detail in this paper.
We are going to discuss some general data pooling topics before going into the details of
setting up a UCP data source and testing it with a most simple test servlet.
We aim for the test servlet to connect with Oracle, borrow a first connection and hope for
UCP to fill up the data source with additional connections according to our data source
specifications (and we really want to see those connections in SQL Developer and jConsole
).
by Volker Koster, MT AG
Seite 2
SOFTWARE VERSIONS
If you dont do anything special within Tomcat while defining your data source, which means
youre using Tomcats standard resource factory for data sources, youll still end up with a
pooled data source. Tomcat ships with database connection pooling implemented by the
Apache Commons DBCP project.
Im not going to match UCP against DBCP here. Right now, I really dont care which performs
better under what circumstances and the like.
Its just that I know Im going to work against an Oracle 11g database, using an Oracle JDBC
implementation and for an Oracle aficionado like me, it is therefore practically imperative to
also use the newest Oracle pooling technology available.
7
7.1
The Implicit Connection Cache was Oracles connection pooling architecture up to Oracle 11g
Release 1.
Only with Release 2 ICC has been replaced by UCP so that ICC is now deprecated Oracle 11g
R2 databases.
Switching from ICC to UCP is painless from a functional point of view. All that could be done
with ICC can now be done with UCP.
7.2
The Universal Connection Pool is now the recommended architecture for Java 1.6 clients
connecting to Oracle 11g databases.
UCP is designed to work with single Oracle instance as well as with a whole Oracle Real
Application Cluster.
UCP is the most recent technology for managing pooled connections and is what this paper
focuses on.
by Volker Koster, MT AG
Seite 3
7.3
One thing Id like to mention here is that you can benefit from Oracles connection pooling
even if your application cannot for some reason use one of Oracles pool-supporting
database drivers (OCI, OCCI, JDBC, ODP.NET etc.).
Oracle supplies the so called Database Resident Connection Pool DRCP, a connection pool
managed directly within the database itself.
This connection pool has to be set up by your database administrators via some PLSQL API.
You can configure the pool like this (which is optional and only needed, if you have to
change the default settings):
SQL>execute dbms_connection_pool.configure_pool(null,
minsize=>10,
maxsize=>100,
inactivity_timeout=>300,
max_think_time=>600,
);
This pool has to be started, before clients can borrow and return connections:
SQL> execute dbms_connection_pool.start_pool;
From the application side, usage of this pool is specified within your SqlNet TNS-Names
connect string.
Hers is an example:
. . .
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp) (HOST=myhost.dom.com)
(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=sales)
(SERVER=POOLED)))
. . .
Oracle 11g supplies a special view to get information from this database resident pool:
dba_cpool_info
Selecting from this view will give you the following info (and more):
select * from dba_cpool_info
by Volker Koster, MT AG
Seite 4
SETTING UP UCP
When we were trying to configure UCP data sources on Tomcat 7, we naturally Googled the
topic and of course found a couple of examples demonstrating different configurations.
We had a standard procedure of evaluating a configuration:
Define the data source in Tomcat
Add the configuration to our test servlet
Connect to the database
Monitor the pool and check for the connections created
The common denominator with all tested configuration was that everything worked fine,
except for the initial creation of the connection pool. The pool was simply not initialized with
configured number of connections on first connect.
Our final solution was to write our own custom resource factory for Tomcat, which was quite
easy to do and gave as absolutely reliable results. We will describe this process here too.
8.1
PREQUISITES
Oracle delivers UCP in a separate file, so you have to download two files:
Odbc6.jar
Ucp.jar
Remember, you have to work with Java 1.6 or above to use this JDBC version.
Copy both files into Tomcats lib directory: <TOMCAT_HOME>\lib.
8.2
DATASOURCE CONFIGURATION
With Tomcat, data source configurations can be specified either globally, i.e. accessible for
all deployed applications, or on a per application basis.
Global resources are specified in <TOMCAT_HOME>\conf\server.xml whereas application
specific resources are defined in the applications context.xml file.
Either way the resource is defined in a <Context> element.
In this paper we go for an application specific data source, so the configuration goes into a
separate Context.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<Context override="true">
<Resource name="jdbc/cust_ucp"
auth="Container"
factory="com.mtag.oraclefactory.MtOracleUcpFactory"
type="oracle.ucp.jdbc.PoolDataSource"
connectionFactoryClassName=
"oracle.jdbc.pool.OracleDataSource"
minPoolSize="2"
maxPoolSize="20"
initialPoolSize="5"
user="vk"
password="vk"
url="jdbc:oracle:thin:@localhost:1521:xe"
connectionPoolName="LocalUCP" />
</Context>
USP with Tomcat 7 and Oracle 11g
by Volker Koster, MT AG
Seite 5
The factory property needs further explanation which will follow soon.
Everything else is quite straight forward:
name: the jndi name of the data source
once your application has successfully acquired an Initial Context, you will use this
name to look up the data source
(Tomcat <Resource> attribute)
auth: Container or Application
let the Container sign on to the resource manager
(Tomcat <Resource> attribute)
type: fully qualified java class name
represents the object that will be returned by the resource factory, i.e. the JNDI lookup
(Tomcat <Resource> attribute)
ConnectionFactoryClassName
property and value taken from UCP manual
minPoolSize: pool size wont drop below this value
property taken from UCP manual
maxPoolSize: pool size wont grow larger than this
property taken from UCP manual
user: Oracle user name
property taken from UCP manual
password: Oracle password for the user above
property taken from UCP manual
url: Oracle connect string
property taken from UCP manual
connectionPoolName: the name for this pool
property taken from UCP manual
The attributes name, auth and type are properties from Tomcats <Resource>
element.
The rest are UCP properties taken from the UCP manual, which describes how to create and
configure a UCP data source. Please note that these are just the basic ones. There a whole
bunch left for you to integrate into your configuration to make these data sources do what
you require.
The UCP manual is listed in the Further Readings section.
by Volker Koster, MT AG
Seite 6
8.3
PLACING OF CONTEXT.XML
If you go for an application specific context.xml file, you again have two options: you can
place it into your applications META-INF directory under the name of context.xml or
you can copy it into
$CATALINA_BASE/conf/[enginename]/[hostname]/[webappname].xml
Take a note to rename context.xml into [webappname].xml if you go for the second
option. Also be careful to realize that this context descriptor task precedence over anything
you specify in an application specific context descriptor subsequently.
Personally I like my context descriptors application specific. I will copy the context.xml
file into the META-INF directory of my test servlet later on.
8.4
My favorite resource concerning Oracle UCP data pools with Apache Tomcat is Michael
Pilones article on the subject listed here: http://drdobbs.com/java/222700353.
Modifying his data source configuration to suite our environment looks like this:
<Resource name="jdbc/std_pool"
auth="Container"
factory="oracle.ucp.jdbc.PoolDataSourceImpl"
type="oracle.ucp.jdbc.PoolDataSource"
description="UCP Test Data Source"
connectionFactoryClassName="oracle.jdbc.pool.OracleDataSource"
minPoolSize="2"
maxPoolSize="20"
initialPoolSize=5
user="vk"
password="vk"
url="jdbc:oracle:thin:@localhost:1521:xe
connectionPoolName="UcpStdPool"
/>
by Volker Koster, MT AG
Seite 7
Using the above configuration, we get this result when connecting to Oracle:
by Volker Koster, MT AG
Seite 8
by Volker Koster, MT AG
Seite 9
Writing a Custom Resource Factory for Tomcat is described within the Tomcat
documentation: http://tomcat.apache.org/tomcat-7.0-doc/jndi-resources-howto.html. At
the end of this document, youll find the chapter Adding Custom Resource Factories. Using
this as a guide, well do the following:
Create a Java project in Eclipse
Reference all the jars from <TOMCAT_HOME>\lib
Create a new class that implements javax.naming.spi.ObjectFactory
package com.mtag.oraclefactory;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Logger;
import
import
import
import
import
javax.naming.Context;
javax.naming.Name;
javax.naming.RefAddr;
javax.naming.Reference;
javax.naming.spi.ObjectFactory;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
/**
* Properties, die diese UCP-Datasource versteht
* o connectionFactoryClassname
* o url
* o user
* o password
* o connectionPoolName
* o minPoolSize
* o maxPoolSize
* o initialPoolSize
*
* @author vkoster
*
*/
public class MtOracleUcpFactory implements ObjectFactory {
private static Logger log =
Logger.getLogger("com.mtag.oraclefactory.MtOracleUcpFactory");
private PoolDataSource pds;
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Hashtable<?, ?> environment) throws
Exception {
log.info("MtOracleFactory.getObjectInstance aufgerufen");
pds = PoolDataSourceFactory.getPoolDataSource();
log.info("UCP PooldDataSource besorgt");
by Volker Koster, MT AG
Seite 10
There is only one method we have to implement: getObjectInstance. Tomcat calls this
method with a lot of parameters, but we are only interested the first one. Formally typed as
an Object, Tomcat passes a javax.naming.Reference object.
From this Reference we can extract a list of name-value pairs, where each pair represents a
data source property that we specified in our Tomcat Conext.xml file.
The implementation does nothing more than to match the name-part of a given name-value
pair with a list of properties Im interested in and sets the respective property to the valuepart of the pair.
You can do this in a much more flexible manner using reflection, but for demonstration
purposes this hard-coded matching will do.
At the end we simply return the now configured data source.
Finally, export your custom resource factory to a jar-file and copy this into Tomcats lib
directory <TOMCAT_HOME>\lib.
9
9.1
by Volker Koster, MT AG
Seite 11
Make the use of your data source visible by placing a reference into your applications
web.xml file located in the WEB-INF directory.
My reference looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
USP with Tomcat 7 and Oracle 11g
by Volker Koster, MT AG
Seite 12
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID"
version="3.0">
<display-name>DataPool</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<resource-env-ref>
<description>
Referenz auf die Beschreibung der JNDI-Resource im
Context-Element Web-App
</description>
<resource-env-ref-name>
jdbc/oralocal
</resource-env-ref-name>
<resource-env-ref-type>
oracle.jdbc.pool.OracleDataSource
</resource-env-ref-type>
</resource-env-ref>
</web-app>
As you can see from the <display-name> element, my test servlet will be called
DataPool.
The data source is referenced by a <resource-enf-ref> element which can be used
here instead of a <resource-ref> element because authentication is already specified in
the context.xml file.
Please take a note that this entry is for documentation purposes only, because we specified
everything in our context.xml file already (this is described in Tomcats documentation
within the JNDI Resources HOW-TO, http://tomcat.apache.org/tomcat-7.0-doc/jndiresources-howto.html in the context.xml configuration part).
9.3
BORROWING A CONNECTION
Borrowing a connection from the pool works just like you would expect with any data
source. Heres the code:
import
import
import
import
import
import
java.sql.Connection;
java.sql.ResultSet;
java.sql.Statement;
javax.naming.Context;
javax.naming.InitialContext;
javax.sql.DataSource;
by Volker Koster, MT AG
Seite 13
//
// Look up
DataSource
protocol =
//
// Allocate
Connection
protocol =
"ResultSet closed<br>";
"Statement closed<br>";
"Connection: closed<br>";
"Connection handling finished OK!<br>";
} catch (Exception e) {
System.out.println(e);
}
return protocol;
Tomcat ensures that the getObjectInstance-method is called only once for your application.
After this initial call, the object reference is stored in the JNDI-context of your application for
subsequent use.
9.4
Now we want to make sure that things are running according to our expectations.
My context.xml file reveals my connection details. You can see that the data source will be
created as user VK and password VK.
Im using this account to connect to my SqlDeveloper to Oracle.
Next I query all the sessions of this user from gv$session.
USP with Tomcat 7 and Oracle 11g
by Volker Koster, MT AG
Seite 14
by Volker Koster, MT AG
Seite 15
The servlet reflects the steps of borrowing a connection. This connection is then used to
retrieve all session of user VK from the database.
You can see that we now have 5 JDBC sessions for user VK. This corresponds to the initial
pool size we specified in our context.xml file. Notice that all are marked as INACTIVE except
the one that is actually running this query.
After running the query, the servlet closed the connection, i.e gave it back to pool.
We will now run the same query from SqlDeveloper expecting the connection pool to be still
running.
by Volker Koster, MT AG
Seite 16
Lets finally take a look at jConsole to see the UCP classes in action:
by Volker Koster, MT AG
Seite 17
11 ACKNOWLEDGMENTS
by Volker Koster, MT AG
Seite 18