All times default to seconds, but can use longer time periods:

The class that corresponds to <database> is

database

Configure a database driver. The driver is a class provided by the database vendor, it is responsible for the communication with the database.

The jar file with the driver in it can be placed in WEB-INF/lib, although it is often best to place your datbase driver's jar file in $RESIN_HOME/lib/local/, which makes the driver available to all of your web applications.

Examples of common driver configurations are in Third-party Database Configuration.

The class that corresponds to <driver> is

Database vendors usually provide many different classes that are potential candidates for type. The JDBC api has developed over time, and is now being replaced by the more general JCA architecture. The driver you choose depends on the options the vendor offers, and whether or not you need distributed transactions.

JCA is replacing JDBC as the API for database drivers. JCA is a much more flexible approach that defines an API that can be used for any kind of connection, not just a connection to a database. If a database vendor provides a JCA interface, it is the best one to use.

A JCA driver implements ManagedConnectionFactory. When you specify such a class for type, Resin will notice that it is a JCA driver and take advantage of the added functionality that the JCA interface provides.

The same JCA driver is used for both non-distributed and distributed transactions

JDBC 2.0 defined the interface ConnectionPoolDataSource. A ConnectionPoolDataSource is not a connection pool, but it does provide some extra information that helps Resin to pool the connection more effectively.

A driver that implements ConnectionPoolDataSource is better than a JDBC 1.0 driver that implements Driver.

JDBC 2.0 defined the interface XADataSource for connections that can participate in distributed transactions. A distributed transaction is needed when transactions involve multiple connections. For example, with two different database backends, if the guarantees that transactions apply need to apply to operations that occur on both databases within the same transaction, distributed transactions are needed.

Distributed transactions are rarely needed, and few databases really support them. Some vendors will provide XADataSource drivers even though the database does not really support distributed transactions. Often, XADataSource drivers are slower than their ConnectionPoolDataSource counterparts.

XADataSource should only be used if distributed transactions are really needed, and can probably be safely ignored for most applications.

Driver is the original JDBC interface, and is the least desirable kind of driver to use. Resin can still pool database connections using these drivers, but it will not be as efficient as the newer drivers.

init-param is used to set properties of the database driver that are specific to the driver and are not generic enough for resin to provide a named configuration tag.

For example, MySQL drivers accept the useUnicode parameter, if true the driver will use Unicode character encodings when handling strings.

<database> <jndi-name>jdbc/mysql</jndi-name> <driver> <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type> <url>jdbc:mysql://localhost:3306/dbname</url> <user>username</user> <password>password</password> <init-param useUnicode="true"/> </driver> ... </database>

Pooling configuration controls the behaviour of Resin's pooling of database connections. For most applications and databases the only needed change is to increase the max-connections value to meet high demand. Other pooling parameters have defaults that are based on our years of experience with many different databases in many different applications. Changes from the defaults should only be done in response to specific problems, and with a good understanding of how pooling works.

Resin's database pool can test if the pooled database connection is still alive by configuring a ping query. This is typically only necessary if the pooling parameters are changed from their default values.

If the pool is configured with a long max-idle-time the database connection may become stale if the database is restarted, or if the database is configured with a shorter connection timeout value than the configuration of the Resin pool. Normally when a database connection is returned to the pool it will wait there until the next request or the idle-time expires. If the database goes down in the meantime or closes the connection, the connection will become stale. The ping configuration can test the database connection.

When pinging, Resin's DBPool will test a table specified with the ping-table parameter before returning the connection to the application. If the ping fails, the connection is assumed to be no good and a different connection from the pool is returned. For a ping-table of my_table, Resin will use a query like the following:

SELECT 1 FROM my_table

You can test the database reliability using the following steps:

  1. Configure the database with ping-table and ping.
  2. Execute some servlet that queries the database.
  3. Restart the database server.
  4. Execute another servlet that queries the database.

The DataSource is a factory that is used to obtain a connection. The DataSource is obtained using the specified when configuring the database resource.

Ideally, the JNDI lookup of DataSource is done only once, the DataSource obtained from the lookup can be stored in a member variable or other appropriate place. The stored DataSource can then be used each time a connection is needed. If it is not stored, there will be an impact on performance from having to do the lookup each time you want to get a connection.

public class .... { private final static String DATASOURCE_NAME = "jdbc/test"; DataSource _pool; ... void init() { try { Context env = (Context) new InitialContext().lookup("java:comp/env"); _pool = (DataSource) env.lookup(DATASOURCE_NAME); if (_pool == null) throw new ServletException("`" + DATASOURCE_NAME + "' is an unknown DataSource"); } catch (NamingException e) { throw new ServletException(e); } } ... }

A connection is obtained from the DataSource. The connection is used as needed, and then released with a call to close() so that Resin knows it is available for a subsequent request.

It is very important that the close() is always called, even if there as an exception. Without the close(), Resin's database pool can loose connections. If you fail to close() a connection, Resin does not know that it is available for reuse, and cannot allocate it for another request. Eventually, Resin may run out of connections.

Always put a close() in a finally block, to guarantee that it is called.

The following example shows the use of a finally block that contains the close(). Because the close() is in a finally block, it will happen even if the code using the connection throws an exception.

Connection conn = null; try { conn = pool.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(" ... "); ... rs.close(); stmt.close(); } catch (SQLException e) { throw new ServletException(e); } finally { try { if (conn != null) conn.close(); } catch (SQLException e) { } }
Copyright (c) 1998-2009 Caucho Technology, Inc. All rights reserved.
caucho® , resin® and quercus® are registered trademarks of Caucho Technology, Inc.