unico 2005/06/13 05:55:20 Modified: src/stores/org/apache/slide/store/impl/rdbms JDBCStore.java . RELEASE-NOTES-2.2 docs howto-j2eestore.html src/doc howto-j2eestore.xml Log: Improved usage of Commons DBCP Connection-pooling in JDBCStore Patch applied from Martin Kalén <mkalen at apache dot org> see http://issues.apache.org/bugzilla/show_bug.cgi?id=35235 Revision Changes Path 1.24 +232 -105 jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/JDBCStore.java Index: JDBCStore.java =================================================================== RCS file: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/JDBCStore.java,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24 --- JDBCStore.java 1 Oct 2004 15:20:09 -0000 1.23 +++ JDBCStore.java 13 Jun 2005 12:55:20 -0000 1.24 @@ -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$ + * @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,61 +112,59 @@ } 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 /** * Initializes the data source with a set of parameters. * - * @param parameters a Hashtable containing the parameters' name and + * @param parameters a Hashtable containing the parameters' name and * associated value - * @exception ServiceParameterErrorException a service parameter holds an + * @exception ServiceParameterErrorException a service parameter holds an * invalid value - * @exception ServiceParameterMissingException a required parameter is + * @exception ServiceParameterMissingException a required parameter is * missing */ public void setParameters(Hashtable parameters) @@ -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/> + * 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/> - * 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 + * 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); - getLogger().log("Setting isolation level '" + levelString + "'", LOG_CHANNEL, Logger.INFO); + final ClassLoader cl = Thread.currentThread().getContextClassLoader(); + final Class driverClass = Class.forName(driver, true, cl); - // 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); + } + } + } 1.11 +78 -76 jakarta-slide/RELEASE-NOTES-2.2 Index: RELEASE-NOTES-2.2 =================================================================== RCS file: /home/cvs/jakarta-slide/RELEASE-NOTES-2.2,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- RELEASE-NOTES-2.2 21 Feb 2005 17:43:17 -0000 1.10 +++ RELEASE-NOTES-2.2 13 Jun 2005 12:55:20 -0000 1.11 @@ -1,76 +1,78 @@ -Jakarta-Slide Release 2.2 -------------------------- - -THIS IS WORK IN PROGRESS - -RELEASE NUMBER: 2.2 -RELEASE TAG / BRANCH: - -GENERAL NOTES -------------- - -TODO - -NEW FEATURES (since 2.1) ------------- - -WebDAV Layer: -- New option for a fine grained, deadlock-less locking scheme -- Capabilities of resources are now configurable depending on resource kind. - (Capabilities are properties, methods, reports) - Includes better support for user defined computed properties. -- new parameter allow-delete-of-versions enabled deletion of certain versions. - -Core: -- Information about changes to properties and children is now tracked in - ObjectNode and RevisionDescriptor -- Cache now supports time outs -- New option that allows to transparently repeat requests that failed due - to concurrency conflicts -- Support for Redirect References: http://www.greenbytes.de/tech/webdav/draft-ietf-webdav-redirectref-protocol-latest.html - -Stores: -- New file store that directly maps the file system -- MySQL store supports tuned way of storing only changed properties and children -- new marco store for compound copy/move/delete requests to be passed to the store level -- Lucene based properties indexer -- Lucene based content indexer - -Client: -- DASL Search Helper classes -- Ant tasks with proxy support - -Misc: -- support for properties in Domain.xml -- WebDAV Construction Kit (WCK) - -BUGFIXES (since 2.1) --------- - -WebDAV Layer: - -Core: -- Read-only resources can now be copied - -Stores: - -Client: -- URL Encoding related fixes in Ant tasks - -Misc: -- Sources are now compatible to Java 5.0 - -KNOWN ISSUES ------------- - -Core: -- Performance on large collections still not satisfactory -- Security checking performance still not satisfactory - -Stores: - -Client: - -Misc: -- Documentation needs to be improved - +Jakarta-Slide Release 2.2
+------------------------- + +THIS IS WORK IN PROGRESS + +RELEASE NUMBER: 2.2 +RELEASE TAG / BRANCH: + +GENERAL NOTES +------------- + +TODO + +NEW FEATURES (since 2.1) +------------ + +WebDAV Layer: +- New option for a fine grained, deadlock-less locking scheme +- Capabilities of resources are now configurable depending on resource kind. + (Capabilities are properties, methods, reports) + Includes better support for user defined computed properties. +- new parameter allow-delete-of-versions enabled deletion of certain versions. + +Core: +- Information about changes to properties and children is now tracked in + ObjectNode and RevisionDescriptor +- Cache now supports time outs +- New option that allows to transparently repeat requests that failed due + to concurrency conflicts +- Support for Redirect References: http://www.greenbytes.de/tech/webdav/draft-ietf-webdav-redirectref-protocol-latest.html + +Stores: +- JDBCStore supports tuning of all configurable DBCP- and JDBC-driver + properties when using Commons DBCP for connection pooling +- New file store that directly maps the file system +- MySQL store supports tuned way of storing only changed properties and children +- new marco store for compound copy/move/delete requests to be passed to the store level +- Lucene based properties indexer +- Lucene based content indexer + +Client: +- DASL Search Helper classes +- Ant tasks with proxy support + +Misc: +- support for properties in Domain.xml +- WebDAV Construction Kit (WCK) + +BUGFIXES (since 2.1) +-------- + +WebDAV Layer: + +Core: +- Read-only resources can now be copied + +Stores: + +Client: +- URL Encoding related fixes in Ant tasks + +Misc: +- Sources are now compatible to Java 5.0 + +KNOWN ISSUES +------------ + +Core: +- Performance on large collections still not satisfactory +- Security checking performance still not satisfactory + +Stores: + +Client: + +Misc: +- Documentation needs to be improved + 1.25 +12 -7 jakarta-slide/docs/howto-j2eestore.html Index: howto-j2eestore.html =================================================================== RCS file: /home/cvs/jakarta-slide/docs/howto-j2eestore.html,v retrieving revision 1.24 retrieving revision 1.25 diff -u -r1.24 -r1.25 --- howto-j2eestore.html 31 Dec 2004 04:51:04 -0000 1.24 +++ howto-j2eestore.html 13 Jun 2005 12:55:20 -0000 1.25 @@ -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é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> - <definition> <store name="MySqlStore"> <nodestore classname="org.apache.slide.store.impl.rdbms.JDBCStore"> @@ -199,10 +200,14 @@ <parameter name="driver">com.mysql.jdbc.Driver</parameter> <parameter name="url">jdbc:mysql://localhost/Slide</parameter> <parameter name="user">root</parameter> - <parameter name="dbcpPooling">true</parameter> - <parameter name="maxPooledConnections">10</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" /> @@ -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> 1.10 +68 -64 jakarta-slide/src/doc/howto-j2eestore.xml Index: howto-j2eestore.xml =================================================================== RCS file: /home/cvs/jakarta-slide/src/doc/howto-j2eestore.xml,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- howto-j2eestore.xml 17 Sep 2004 08:05:23 -0000 1.9 +++ howto-j2eestore.xml 13 Jun 2005 12:55:20 -0000 1.10 @@ -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> -<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><![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> - -<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="dbcpPooling">true</parameter> - <parameter name="maxPooledConnections">10</parameter> - <parameter name="isolation">SERIALIZABLE</parameter> - <parameter name="compress">false</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><![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> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]