Greetings,
 the attached patch will extend the JDBCStore configuration possibilities
to allow setting of all (arbitrary in fact) Commons DBCP configuration
properties and to pass properties directly to the underlying JDBC-driver.

Commons DBCP have a plethora of options that can be studied in detail here:
 http://jakarta.apache.org/commons/dbcp/configuration.html

This patch addresses the following issues:

 1. Cannot set (or control usage of) the DBCP connection validation query

    After applying the patch, any DBCP properties like validationQuery,
    testOnBorrow, testWhileIdle, can be set in the Slide domain configuration
    with a "dbcp." prefix.

    Example nodestore config for Oracle:

        <parameter name="dbcpPooling">true</parameter>
        <parameter name="dbcp.maxWait">5000</parameter>
        <parameter name="dbcp.maxActive">50</parameter>
        <parameter name="dbcp.maxIdle">25</parameter>
        <parameter name="dbcp.validationQuery">SELECT 1 FROM DUAL</parameter>
        <parameter name="dbcp.testOnBorrow">true</parameter>
        <parameter name="dbcp.testOnReturn">false</parameter>
        <parameter name="dbcp.testWhileIdle">false</parameter>


2. Cannot pass properties to the JDBC-driver

    (With MySQL it was previously possible, but not all drivers support
    extending the JDBC URL with ?property=value. Oracle for one does not.)

    After applying the patch, it is now possible to pass a list of JDBC-driver
    properties from the Slide domain configuration through the
    "dbcp.connectionProperties" setting. The format is semicolon separated,
    eg "defaultRowPrefetch=30;disableDefineColumnType=true" for setting
    Oracle row-prefetching to 30 rows per server rountrip and switching to
    the Oracle-recommended default of disableDefineColumnType=true for
    the Oracle 10 JDBC thin-driver.


3. Shutting down the Slide JDBCStore does not shutdown DBCP pool

    After applying the patch, the DBCP pool will be decommisioned on
    the disconnect() call on a clean Slide exit (it can be reconnected
    by calling connect() and the isConnected semantics is updated
    so that connectIfNeeded will call connect() if the pool is down).


4. Synchronization issue when using DBCP in multiple JDBCStore- instances within a Domain

    Naming the DBCP connection pool with System.identityHashCode is not
    guaranteed to be unique withing the Domain.

    After applying the patch, the JDBCStore will use the DBPC
    BasicDataSource with a Store-local (protected instance var)
    reference and it will be guaranteed that each Store instance
    uses a unique DBCP DataSource/pool instance.


Some of the DriverManager deadlock issues reported on the list and in bugzilla should be addressed by #1 (set dbcp.maxWait != -1 to prevent waiting forever for a new connection) and #4 above (.

If the patch gets applied I will do some more extensive testing with
a newly built Slide from CVS and see if we can close some bugzilla
issues as a result.

I have tested the patch with a real-world multithreaded application
using several Connection instances simultaneously and two different
JDBCStore configurations for different stores in the domain (one
fully JDBC-based and one with descriptors in DB and content in
the ContextTxFileContentStore).

Test were done with Oracle9i RDBMS, Oracle thin JDBC driver
 and JDBCStore (with patch applied) configured with OracleRDBMSAdapter.

A previous patch posted here, but not yet applied, was also applied
on the local source.
(See http://www.mail-archive.com/slide-dev@jakarta.apache.org/msg14543.html)

The patch is in unified format and created against the trunk, updated
from CVS around lunchtime today.

I have also updated the forrest xdoc for the J2EE/JDBC store HOWTO and
the patch includes this change and the resulting generated site-doc HTML.

Regards,
 Martin
Index: src/stores/org/apache/slide/store/impl/rdbms/JDBCStore.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/JDBCStore.java,v
retrieving revision 1.23
diff -u -r1.23 JDBCStore.java
--- src/stores/org/apache/slide/store/impl/rdbms/JDBCStore.java 1 Oct 2004 
15:20:09 -0000       1.23
+++ src/stores/org/apache/slide/store/impl/rdbms/JDBCStore.java 27 Apr 2005 
16:23:23 -0000
@@ -5,7 +5,7 @@
  *
  * ====================================================================
  *
- * Copyright 1999-2002 The Apache Software Foundation 
+ * Copyright 1999-2005 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,15 +28,17 @@
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Properties;
 
-import org.apache.commons.dbcp.DriverManagerConnectionFactory;
-import org.apache.commons.dbcp.PoolableConnectionFactory;
-import org.apache.commons.dbcp.PoolingDriver;
-import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.dbcp.BasicDataSourceFactory;
 import org.apache.slide.common.NamespaceAccessToken;
 import org.apache.slide.common.ServiceInitializationFailedException;
 import org.apache.slide.common.ServiceParameterErrorException;
 import org.apache.slide.common.ServiceParameterMissingException;
+import org.apache.slide.common.ServiceDisconnectionFailedException;
+import org.apache.slide.common.ServiceConnectionFailedException;
 import org.apache.slide.store.ContentStore;
 import org.apache.slide.store.LockStore;
 import org.apache.slide.store.NodeStore;
@@ -47,29 +49,44 @@
 
 /**
  * Store implementation that is able to store all information (like structure,
- * locks and content) in a JDBC-aware relational database system. As this 
- * implementation only uses a single connection to the database, it does not 
- * work properly in production environments that require simultaneous access by
- * multiple clients.
+ * locks and content) in a JDBC-aware relational database system.
+ * <p>
+ * Set the [EMAIL PROTECTED] #CONF_KEY_DBCP_ENABLED} configuration attribute 
to true
+ * to enable Commons DBCP connection pooling.
  * 
  * @version $Revision: 1.23 $
+ * @see <a href="http://jakarta.apache.org/slide/howto-j2eestore.html";>Slide 
Configuration HOWTO</a>
+ * for complete configuration information
  */
 public class JDBCStore
     extends AbstractRDBMSStore
     implements LockStore, NodeStore, RevisionDescriptorsStore, 
RevisionDescriptorStore, SecurityStore, ContentStore {
 
-    public static final String DBCP_URL = "jdbc:apache:commons:dbcp";
+    /** Configuration key: "true"=use Commons DBCP connection pooling. */
+    protected static final String CONF_KEY_DBCP_ENABLED = "dbcpPooling";
 
-    public static final String TRANSACTION_NONE = "NONE";
-    public static final String TRANSACTION_READ_UNCOMMITTED = 
"READ_UNCOMMITTED";
-    public static final String TRANSACTION_READ_COMMITTED = "READ_COMMITTED";
-    public static final String TRANSACTION_REPEATABLE_READ = "REPEATABLE_READ";
-    public static final String TRANSACTION_SERIALIZABLE = "SERIALIZABLE";
+    /**
+     * Configuration key prefix for all Commons DBCP settings.
+     * To pass properties directly to the underlying JDBC-driver,
+     * use the <b>[EMAIL PROTECTED] 
#CONF_KEY_DBCP_PREFIX}.connectionProperties</b>
+     * configuration property in your Slide domain configuration,
+     * set the value to semicolon-separated name=value pairs
+     * (eg "cachePreparedStatements=true;rowPrefetchSize=50;foo=bar").
+     * @see <a 
href="http://jakarta.apache.org/commons/dbcp/configuration.html";>
+     * Commons DBCP website</a> for info about possible settings
+     */
+    protected static final String CONF_KEY_DBCP_PREFIX = "dbcp.";
+
+    protected static final String TRANSACTION_NONE = "NONE";
+    protected static final String TRANSACTION_READ_UNCOMMITTED = 
"READ_UNCOMMITTED";
+    protected static final String TRANSACTION_READ_COMMITTED = 
"READ_COMMITTED";
+    protected static final String TRANSACTION_REPEATABLE_READ = 
"REPEATABLE_READ";
+    protected static final String TRANSACTION_SERIALIZABLE = "SERIALIZABLE";
 
     public static final int DEFAUT_ISOLATION_LEVEL = 
Connection.TRANSACTION_READ_COMMITTED;
 
     protected static String isolationLevelToString(int isolationLevel) {
-        String levelString;
+        final String levelString;
         switch (isolationLevel) {
             case Connection.TRANSACTION_NONE :
                 levelString = TRANSACTION_NONE;
@@ -95,50 +112,48 @@
     }
 
     protected static int stringToIsolationLevelToString(String levelString) {
+        final int transactionIsolationLevel;
         if (TRANSACTION_NONE.equals(levelString)) {
-            return Connection.TRANSACTION_NONE;
+            transactionIsolationLevel = Connection.TRANSACTION_NONE;
         } else if (TRANSACTION_READ_UNCOMMITTED.equals(levelString)) {
-            return Connection.TRANSACTION_READ_UNCOMMITTED;
+            transactionIsolationLevel = 
Connection.TRANSACTION_READ_UNCOMMITTED;
         } else if (TRANSACTION_READ_COMMITTED.equals(levelString)) {
-            return Connection.TRANSACTION_READ_COMMITTED;
+            transactionIsolationLevel = Connection.TRANSACTION_READ_COMMITTED;
         } else if (TRANSACTION_REPEATABLE_READ.equals(levelString)) {
-            return Connection.TRANSACTION_REPEATABLE_READ;
+            transactionIsolationLevel = Connection.TRANSACTION_REPEATABLE_READ;
         } else if (TRANSACTION_SERIALIZABLE.equals(levelString)) {
-            return Connection.TRANSACTION_SERIALIZABLE;
+            transactionIsolationLevel = Connection.TRANSACTION_SERIALIZABLE;
         } else {
-            return -1;
+            transactionIsolationLevel = -1;
         }
+        return transactionIsolationLevel;
     }
 
     // ----------------------------------------------------- Instance Variables
 
-    /**
-     * Driver class name.
-     */
+    /** JDBC driver class name. */
     protected String driver;
 
-    /**
-     * Connection URL.
-     */
+    /** JDBC connection URL. */
     protected String url;
 
-    /**
-     * User name.
-     */
-    protected String user = "";
+    /** Database user-name. */
+    protected String user;
 
-    /**
-     * Password.
-     */
-    protected String password = "";
+    /** Database password. */
+    protected String password;
 
-    protected boolean useDbcpPooling = false;
+    /** Transaction isolation level. */
+    protected int isolationLevel;
 
-    protected String dbcpPoolName = "dbcpPool" + System.identityHashCode(this);
+    /** Switch for enabling Commons DBCP connection pooling. */
+    protected boolean useDbcpPooling;
 
-    protected int maxPooledConnections = -1;
+    /** Properties set from Store configuration, to be used with DBCP. */
+    protected Properties dbcpProperties;
 
-    protected int isolationLevel = DEFAUT_ISOLATION_LEVEL;
+    /** Connection pool DataSource (set only if using Commons DBCP). */
+    protected BasicDataSource dbcpDataSource;
 
     // -------------------------------------------------------- Service Methods
 
@@ -174,17 +189,21 @@
         }
 
         // User name
+        user = "";
         value = (String) parameters.get("user");
         if (value != null) {
             user = value;
         }
 
         // Password
+        password = "";
         value = (String) parameters.get("password");
         if (value != null) {
             password = value;
         }
 
+        // Transaction isolation level
+        isolationLevel = DEFAUT_ISOLATION_LEVEL;
         value = (String) parameters.get("isolation");
         if (value != null) {
             isolationLevel = stringToIsolationLevelToString(value);
@@ -208,85 +227,75 @@
             }
         }
 
-        value = (String) parameters.get("dbcpPooling");
+        // Connection pooling
+        useDbcpPooling = false;
+        value = (String) parameters.get(CONF_KEY_DBCP_ENABLED);
         if (value != null) {
             useDbcpPooling = "true".equals(value);
         }
 
         if (useDbcpPooling) {
-            value = (String) parameters.get("maxPooledConnections");
-            if (value != null) {
-                try {
-                    maxPooledConnections = Integer.parseInt(value);
-                } catch (NumberFormatException nfe) {
-                    getLogger().log(
-                        "Could not set maximum pooled connections, parameter 
must be integer",
-                        LOG_CHANNEL,
-                        Logger.WARNING);
+            // Set up configuration properties to be used with Commons DBCP
+            dbcpProperties = getDbcpPoolProperties(parameters);
 
-                }
-            }
+            // Add driver and logon information
+            dbcpProperties.put("driverClassName", driver);
+            dbcpProperties.put("url", url);
+            dbcpProperties.put("username", user);
+            dbcpProperties.put("password", password);
+
+            // Set TX isolation level
+            final String isolationLevelString;
+            isolationLevelString = isolationLevelToString(isolationLevel);
+            dbcpProperties.put("defaultTransactionIsolation",
+                isolationLevelString);
+
+            // Turn off autocommit
+            dbcpProperties.put("defaultAutoCommit",
+                String.valueOf(Boolean.FALSE));
         }
 
         super.setParameters(parameters);
     }
 
     /**
-     * Initializes driver.
+     * Initializes this store.
      * <p/>
-     * Occurs in four steps :
-     * <li>Driver class is loaded</li>
-     * <li>Driver is instantiated</li>
-     * <li>Driver registration in the driver manager</li>
-     * <li>Creation of the basic tables, if they didn't exist before</li>
-     * 
-     * @exception ServiceInitializationFailedException Throws an exception 
-     * if the data source has already been initialized before
+     * If Commons DBCP is used, initialization is done by:
+     *  <ol>
+     *   <li>Loading JDBC-driver class (and running static initializers)</li>
+     * </ol>
+     * DBCP will handled DriverManager registration internally, which will
+     * (together with further initialization of Connection pool) occur in
+     * the [EMAIL PROTECTED] #connect} method.
+     * <p/>
+     * Otherwise (ie not using DBCP), initialization is done by:
+     *  <ol>
+     *   <li>Loading JDBC-driver class (and running static initializers)</li>
+     *   <li>Instantiating Driver instance</li>
+     *   <li>Driver registration in the JDBC DriverManager</li>
+     *  </ol>
+     *
+     * @exception ServiceInitializationFailedException if JDBC driver
+     * classloading or registration fails
      */
     public synchronized void initialize(NamespaceAccessToken token) throws 
ServiceInitializationFailedException {
 
         // XXX might be done already in setParameter
         if (!alreadyInitialized) {
             try {
-                // Loading and registering driver
+                // Load driver class and force static init
                 getLogger().log("Loading and registering driver '" + driver + 
"'", LOG_CHANNEL, Logger.INFO);
-                Class driverClass = Class.forName(driver);
-                Driver driverInstance = (Driver) driverClass.newInstance();
 
-                String levelString = isolationLevelToString(isolationLevel);
+                final ClassLoader cl = 
Thread.currentThread().getContextClassLoader();
+                final Class driverClass = Class.forName(driver, true, cl);
 
-                getLogger().log("Setting isolation level '" + levelString + 
"'", LOG_CHANNEL, Logger.INFO);
-
-                // use DBCP pooling if enabled
+                // Use Commons DBCP pooling if enabled
                 if (useDbcpPooling) {
                     getLogger().log("Using DBCP pooling", LOG_CHANNEL, 
Logger.INFO);
-                    GenericObjectPool connectionPool = new 
GenericObjectPool(null);
-                    if (maxPooledConnections != -1) {
-                        connectionPool.setMaxActive(maxPooledConnections);
-                    }
-                    getLogger().log(
-                        "Number of connections set to " + 
connectionPool.getMaxActive(),
-                        LOG_CHANNEL,
-                        Logger.INFO);
-
-                    DriverManagerConnectionFactory connectionFactory =
-                        new DriverManagerConnectionFactory(url, user, 
password);
-                    new PoolableConnectionFactory(
-                        connectionFactory,
-                        connectionPool,
-                        // TODO switching on pooling of prepared statements 
causes problems with closing of connections
-                        // switched off for now
-//                  new StackKeyedObjectPoolFactory(),
-                        null, 
-                        null,
-                        false,
-                        false,
-                        isolationLevel);
-                    PoolingDriver driver = new PoolingDriver();
-                    driver.registerPool(dbcpPoolName, connectionPool);
-                    // already done when loding PoolingDriver class 
-                    //                DriverManager.registerDriver(driver);
                 } else {
+                    // Register Driver instance with JDBC DriverManager
+                    final Driver driverInstance = (Driver) 
driverClass.newInstance();
                     DriverManager.registerDriver(driverInstance);
                     getLogger().log("Not using DBCP pooling", LOG_CHANNEL, 
Logger.WARNING);
                 }
@@ -300,18 +309,68 @@
                 alreadyInitialized = true;
             }
         }
+    }
 
+    public void connect() throws ServiceConnectionFailedException {
+        super.connect();
+        if (useDbcpPooling) {
+            try {
+                dbcpDataSource = (BasicDataSource)
+                    BasicDataSourceFactory.createDataSource(dbcpProperties);
+
+                // The BasicDataSource has lazy initialization
+                // borrowing a connection will start the DataSource
+                // and make sure it is configured correctly.
+                final Connection conn = dbcpDataSource.getConnection();
+                conn.close();
+            } catch (Exception e) {
+                getLogger().log(
+                    "Initialization of connection pool failed ("
+                    + e.getMessage() + ")",
+                    LOG_CHANNEL, Logger.ERROR);
+                throw new ServiceConnectionFailedException(this, e);
+            } finally {
+                logConnectionPoolStatistics();
+            }
+        }
+    }
+
+    public boolean isConnected() {
+        if (useDbcpPooling) {
+            return dbcpDataSource != null;
+        }
+        return super.isConnected();
+    }
+
+    public void disconnect() throws ServiceDisconnectionFailedException {
+        if (useDbcpPooling) {
+            if (dbcpDataSource != null) {
+                try {
+                    dbcpDataSource.close();
+                } catch (SQLException e) {
+                    getLogger().log(
+                        "Decomissioning of connection pool failed ("
+                        + e.getMessage() + ")",
+                        LOG_CHANNEL, Logger.ERROR);
+                    throw new ServiceDisconnectionFailedException(this, e);
+                }
+                dbcpDataSource = null;
+            }
+        }
+        super.disconnect();
     }
 
     protected Connection getNewConnection() throws SQLException {
+        final Connection connection;
 
-        Connection connection;
         if (useDbcpPooling) {
             try {
-                connection = DriverManager.getConnection(DBCP_URL + ":" + 
dbcpPoolName);
+                connection = dbcpDataSource.getConnection();
             } catch (SQLException e) {
                 getLogger().log("Could not create connection. Reason: " + e, 
LOG_CHANNEL, Logger.EMERGENCY);
                 throw e;
+            } finally {
+                logConnectionPoolStatistics();
             }
         } else {
             try {
@@ -335,7 +394,6 @@
             if (connection.getAutoCommit()) {
                 connection.setAutoCommit(false);
             }
-
         }
 
         return connection;
@@ -344,4 +402,73 @@
     protected boolean includeBranchInXid() {
         return false;
     }
+
+    /**
+     * Returns properties to be used with Commons DBCP BasicDataSource.
+     *
+     * @param parameters the configuration parameters for this store
+     * @return properties to pass to the DBCP datasource, set up
+     * according to store configuration parameters (never null)
+     */
+    protected Properties getDbcpPoolProperties(Hashtable parameters) {
+        final Properties props = new Properties();
+
+        if (parameters == null) {
+            return props;
+        }
+
+        // Set all DBCP properties
+        final int prefixSkipchars = CONF_KEY_DBCP_PREFIX.length();
+        final Iterator keyIter = parameters.keySet().iterator();
+        while (keyIter.hasNext()) {
+            final String key = String.valueOf(keyIter.next());
+            if (key.startsWith(CONF_KEY_DBCP_PREFIX)) {
+                final String property = key.substring(prefixSkipchars);
+                final Object value = parameters.get(key);
+                if (value != null) {
+                    props.put(property, value.toString());
+                }
+            }
+        }
+
+        int intValue = -2; // use -2, since -1 and 0 are magic numbers already
+        // Old maxActive setting ("maxPooledConnections") have priority
+        final Object value = parameters.get("maxPooledConnections");
+        if (value != null) {
+            try {
+                intValue = Integer.parseInt(value.toString());
+            } catch (NumberFormatException e) {
+                getLogger().log("Could not parse configuration setting " +
+                    "maxPooledConnections, parameter must be integer",
+                    LOG_CHANNEL,
+                    Logger.WARNING);
+            }
+        }
+        if (intValue > -2) {
+            getLogger().log("The maxPooledConnections configuration " +
+                "attribute is deprecated, please use " +
+                CONF_KEY_DBCP_PREFIX + "maxActive instead.",
+                LOG_CHANNEL,
+                Logger.WARNING);
+            props.put("maxActive", value.toString());
+        }
+        return props;
+    }
+
+    /**
+     * Log statistics for Connection pool
+     * (when using Commons DBCP and log level DEBUG).
+     */
+    protected void logConnectionPoolStatistics() {
+        // Avoid String concatenation if message is not going to be logged
+        if (useDbcpPooling && getLogger().getLoggerLevel(LOG_CHANNEL) >= 
Logger.DEBUG) {
+            getLogger().log("Connection pool stats: active: " +
+                dbcpDataSource.getNumActive() + " (max: " +
+                dbcpDataSource.getMaxActive() + "), idle: " +
+                dbcpDataSource.getNumIdle() + "(max: " +
+                dbcpDataSource.getMaxIdle() + ")",
+                LOG_CHANNEL, Logger.DEBUG);
+        }
+    }
+
 }
Index: src/doc/howto-j2eestore.xml
===================================================================
RCS file: /home/cvspublic/jakarta-slide/src/doc/howto-j2eestore.xml,v
retrieving revision 1.9
diff -u -r1.9 howto-j2eestore.xml
--- src/doc/howto-j2eestore.xml 17 Sep 2004 08:05:23 -0000      1.9
+++ src/doc/howto-j2eestore.xml 27 Apr 2005 16:23:23 -0000
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
-
+<!-- Version: $Id$ -->
 <document>
 
-  <properties>
+    <properties>
         <author email="[EMAIL PROTECTED]">Colin Britton</author>
         <author email="[EMAIL PROTECTED]">Oliver Zeigermann</author>
+        <author email="[EMAIL PROTECTED]">Martin Kalén</author>
         <title>J2EE/JDBC Store Howto</title>
     </properties>
   
@@ -12,32 +13,32 @@
   
   <section name="Configuring Slide">
     <p>In order to use the J2EE stores, the Domain.xml file needs to contain 
the following configuration for the store:
-<pre>
-&lt;definition&gt;
-    &lt;store name="j2ee"&gt;
-        &lt;nodestore 
classname="org.apache.slide.store.impl.rdbms.J2EEStore"&gt;
-            &lt;parameter name="datasource"&gt;jdbc/mtx&lt;/parameter&gt;
-            &lt;parameter 
name="adapter">org.apache.slide.store.impl.rdbms.MySqlRDBMSAdapter&lt;/parameter>
-            &lt;parameter name="compress">false&lt;/parameter>
-        &lt;/nodestore&gt;
-        &lt;securitystore&gt;
-            &lt;reference store="nodestore"/&gt;
-        &lt;/securitystore&gt;
-        &lt;lockstore&gt;
-            &lt;reference store="nodestore"/&gt;
-        &lt;/lockstore&gt;
-        &lt;revisiondescriptorsstore&gt;
-            &lt;reference store="nodestore"/&gt;
-        &lt;/revisiondescriptorsstore&gt;
-        &lt;revisiondescriptorstore&gt;
-            &lt;reference store="nodestore"/&gt;
-        &lt;/revisiondescriptorstore&gt;
-        &lt;contentstore&gt;
-            &lt;reference store="nodestore"/&gt;
-        &lt;/contentstore&gt;
-    &lt;/store&gt;
-    &lt;scope match="/" store="j2ee"/&gt;
-&lt;/definition&gt;
+<pre><![CDATA[
+<definition>
+    <store name="j2ee">
+        <nodestore classname="org.apache.slide.store.impl.rdbms.J2EEStore">
+            <parameter name="datasource">jdbc/mtx</parameter>
+            <parameter 
name="adapter">org.apache.slide.store.impl.rdbms.MySqlRDBMSAdapter</parameter>
+            <parameter name="compress">false</parameter>
+        </nodestore>
+        <securitystore>
+            <reference store="nodestore"/>
+        </securitystore>
+        <lockstore>
+            <reference store="nodestore"/>
+        </lockstore>
+        <revisiondescriptorsstore>
+            <reference store="nodestore"/>
+        </revisiondescriptorsstore>
+        <revisiondescriptorstore>
+            <reference store="nodestore"/>
+        </revisiondescriptorstore>
+        <contentstore>
+            <reference store="nodestore"/>
+        </contentstore>
+    </store>
+    <scope match="/" store="j2ee"/>
+</definition>]]>
 </pre>
 where the adapter determines which database adapter you want to use. In this 
case you configured the MySQL adapter. Most adapters
 have a parameter to decide whether the content shall be compressed (zipped) 
before storing to the database. This <em>might</em>
@@ -49,53 +50,56 @@
 
     <p>If your store is not configured using a datasource looked up using JNDI 
you will have to provide more information to Slide
        like this for example:
-<pre>
-       
-&lt;definition&gt;
-&lt;store name="MySqlStore">
-  &lt;nodestore classname="org.apache.slide.store.impl.rdbms.JDBCStore">
-    &lt;parameter 
name="adapter">org.apache.slide.store.impl.rdbms.MySqlRDBMSAdapter&lt;/parameter>
-    &lt;parameter name="driver">com.mysql.jdbc.Driver&lt;/parameter>
-    &lt;parameter name="url">jdbc:mysql://localhost/Slide&lt;/parameter>
-    &lt;parameter name="user">root&lt;/parameter>
-    &lt;parameter name="dbcpPooling">true&lt;/parameter>
-    &lt;parameter name="maxPooledConnections">10&lt;/parameter>
-    &lt;parameter name="isolation">SERIALIZABLE&lt;/parameter>
-    &lt;parameter name="compress">false&lt;/parameter>
-  &lt;/nodestore>
-  &lt;contentstore>
-    &lt;reference store="nodestore" />
-  &lt;/contentstore>
-  &lt;securitystore>
-    &lt;reference store="nodestore" />
-  &lt;/securitystore>
-  &lt;lockstore>
-    &lt;reference store="nodestore" />
-  &lt;/lockstore>
-  &lt;revisiondescriptorsstore>
-    &lt;reference store="nodestore" />
-  &lt;/revisiondescriptorsstore>
-  &lt;revisiondescriptorstore>
-    &lt;reference store="nodestore" />
-  &lt;/revisiondescriptorstore>
- &lt;/store>
- &lt;scope match="/" store="MySqlStore"/&gt;
-&lt;/definition&gt;
+<pre><![CDATA[
+<definition>
+<store name="MySqlStore">
+  <nodestore classname="org.apache.slide.store.impl.rdbms.JDBCStore">
+    <parameter 
name="adapter">org.apache.slide.store.impl.rdbms.MySqlRDBMSAdapter</parameter>
+    <parameter name="driver">com.mysql.jdbc.Driver</parameter>
+    <parameter name="url">jdbc:mysql://localhost/Slide</parameter>
+    <parameter name="user">root</parameter>
+    <parameter name="isolation">SERIALIZABLE</parameter>
+    <parameter name="compress">false</parameter>
+    <parameter name="dbcpPooling">true</parameter>
+    <parameter name="dbcp.maxActive">10</parameter>
+    <parameter name="dbcp.validationQuery">SELECT 1</parameter>
+    <parameter name="dbcp.maxWait">5000</parameter>
+    <!-- Set arbitrary (semicolon-separated) properties for the JDBC-driver:
+        <parameter 
name="dbcp.connectionProperties">cachePrepStmts=true;prepStmtCacheSqlLimit=512</parameter>
 -->
+  </nodestore>
+  <contentstore>
+    <reference store="nodestore" />
+  </contentstore>
+  <securitystore>
+    <reference store="nodestore" />
+  </securitystore>
+  <lockstore>
+    <reference store="nodestore" />
+  </lockstore>
+  <revisiondescriptorsstore>
+    <reference store="nodestore" />
+  </revisiondescriptorsstore>
+  <revisiondescriptorstore>
+    <reference store="nodestore" />
+  </revisiondescriptorstore>
+ </store>
+ <scope match="/" store="MySqlStore"/>
+</definition>]]>
 </pre>
 You can see you will have to configure you driver, the connection url and the 
user for the database. You can optionally configure
 if connection pooling using DBCP is enabled or not and if enabled how many 
connections shall be pooled. If you want you can
-also choose the isolation level of your database. <code>SERIALIZABLE</code> is 
a safe choice, but - depending on you database - at least <code>READ 
COMMITTED</code> 
+also choose the isolation level of your database. <code>SERIALIZABLE</code> is 
a safe choice, but - depending on you database - at least <code>READ 
COMMITTED</code>
 is recommended.
   </p>
   </section>
 
   <section name="Configuring Tomcat 4.x">
-    <p>In order to use this with Tomcat you need to setup the datasource. 
-    Instructions for this are at 
+    <p>In order to use this with Tomcat you need to setup the datasource.
+    Instructions for this are at
     <a 
href="http://jakarta.apache.org/tomcat/tomcat-4.0-doc/jndi-resources-howto.html";>
     
http://jakarta.apache.org/tomcat/tomcat-4.0-doc/jndi-resources-howto.html</a>.
     </p>
-    <p>If you follow the above instructions you will make changes similar to 
the 
+    <p>If you follow the above instructions you will make changes similar to 
the
     following in web.xml and server.xml.</p>
 <p>
 <pre>
Index: docs/howto-j2eestore.html
===================================================================
RCS file: /home/cvspublic/jakarta-slide/docs/howto-j2eestore.html,v
retrieving revision 1.24
diff -u -r1.24 howto-j2eestore.html
--- docs/howto-j2eestore.html   31 Dec 2004 04:51:04 -0000      1.24
+++ docs/howto-j2eestore.html   27 Apr 2005 16:23:23 -0000
@@ -6,6 +6,8 @@
 <meta value="[EMAIL PROTECTED]" name="email">
 <meta value="Oliver Zeigermann" name="author">
 <meta value="[EMAIL PROTECTED]" name="email">
+<meta value="Martin Kal&eacute;n" name="author">
+<meta value="[EMAIL PROTECTED]" name="email">
 </head>
 <body vlink="#525D76" alink="#525D76" link="#525D76" text="#000000" 
bgcolor="#ffffff">
 <table cellspacing="4" width="100%" border="0">
@@ -191,7 +193,6 @@
 <p>If your store is not configured using a datasource looked up using JNDI you 
will have to provide more information to Slide
        like this for example:
 <pre>
-       
 &lt;definition&gt;
 &lt;store name="MySqlStore"&gt;
   &lt;nodestore classname="org.apache.slide.store.impl.rdbms.JDBCStore"&gt;
@@ -199,10 +200,14 @@
     &lt;parameter name="driver"&gt;com.mysql.jdbc.Driver&lt;/parameter&gt;
     &lt;parameter name="url"&gt;jdbc:mysql://localhost/Slide&lt;/parameter&gt;
     &lt;parameter name="user"&gt;root&lt;/parameter&gt;
-    &lt;parameter name="dbcpPooling"&gt;true&lt;/parameter&gt;
-    &lt;parameter name="maxPooledConnections"&gt;10&lt;/parameter&gt;
     &lt;parameter name="isolation"&gt;SERIALIZABLE&lt;/parameter&gt;
     &lt;parameter name="compress"&gt;false&lt;/parameter&gt;
+    &lt;parameter name="dbcpPooling"&gt;true&lt;/parameter&gt;
+    &lt;parameter name="dbcp.maxActive"&gt;10&lt;/parameter&gt;
+    &lt;parameter name="dbcp.validationQuery"&gt;SELECT 1&lt;/parameter&gt;
+    &lt;parameter name="dbcp.maxWait"&gt;5000&lt;/parameter&gt;
+    &lt;!-- Set arbitrary (semicolon-separated) properties for the JDBC-driver:
+        &lt;parameter 
name="dbcp.connectionProperties"&gt;cachePrepStmts=true;prepStmtCacheSqlLimit=512&lt;/parameter&gt;
 --&gt;
   &lt;/nodestore&gt;
   &lt;contentstore&gt;
     &lt;reference store="nodestore" /&gt;
@@ -225,7 +230,7 @@
 </pre>
 You can see you will have to configure you driver, the connection url and the 
user for the database. You can optionally configure
 if connection pooling using DBCP is enabled or not and if enabled how many 
connections shall be pooled. If you want you can
-also choose the isolation level of your database. <code>SERIALIZABLE</code> is 
a safe choice, but - depending on you database - at least <code>READ 
COMMITTED</code> 
+also choose the isolation level of your database. <code>SERIALIZABLE</code> is 
a safe choice, but - depending on you database - at least <code>READ 
COMMITTED</code>
 is recommended.
   </p>
   
@@ -243,13 +248,13 @@
 <td>
 <blockquote>
     
-<p>In order to use this with Tomcat you need to setup the datasource. 
-    Instructions for this are at 
+<p>In order to use this with Tomcat you need to setup the datasource.
+    Instructions for this are at
     <a 
href="http://jakarta.apache.org/tomcat/tomcat-4.0-doc/jndi-resources-howto.html";>
     
http://jakarta.apache.org/tomcat/tomcat-4.0-doc/jndi-resources-howto.html</a>.
     </p>
     
-<p>If you follow the above instructions you will make changes similar to the 
+<p>If you follow the above instructions you will make changes similar to the
     following in web.xml and server.xml.</p>
 
 <p>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to