JDBC Data Container Config
1 Introduction
eXo JCR persistent data container can work in two configuration modes:- Multi-database: one database for each workspace (used in standalone eXo JCR service mode)
- Single-database: all workspaces persisted in one database (used in embedded eXo JCR service mode, e.g. in eXo portal)
- MySQL (5.x including UTF8 support)
- PostgreSQL (8.x)
- Oracle Database (9i, 10g)
- Microsoft SQL Server (2005)
- Sybase ASE (15.0)
- Apache Derby/Java DB (10.1.x, 10.2.x)
- IBM DB2 (8.x, 9.x)
- HSQLDB (1.8.0.7)
2 Multi-database Configuration
You need to configure each workspace in a repository. You may have each one on different remote servers as far as you need. First of all configure the data containers in the org.exoplatform.services.naming.InitialContextInitializer service. It's the JNDI context initializer which registers (binds) naming resources (DataSources) for data containers. Example (standalone mode, two data containers jdbcjcr - local HSQLDB, jdbcjcr1 - remote MySQL):<component>
<key>org.exoplatform.services.naming.InitialContextInitializer</key>
<type>org.exoplatform.services.naming.InitialContextInitializer</type>
<component-plugins>
<component-plugin>
<name>bind.datasource</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
<init-params>
<value-param>
<name>bind-name</name>
<value>jdbcjcr</value>
</value-param>
<value-param>
<name>class-name</name>
<value>javax.sql.DataSource</value>
</value-param>
<value-param>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</value-param>
<properties-param>
<name>ref-addresses</name>
<description>ref-addresses</description>
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:file:target/temp/data/portal"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</properties-param>
</init-params>
</component-plugin>
<component-plugin>
<name>bind.datasource</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
<init-params>
<value-param>
<name>bind-name</name>
<value>jdbcjcr1</value>
</value-param>
<value-param>
<name>class-name</name>
<value>javax.sql.DataSource</value>
</value-param>
<value-param>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</value-param>
<properties-param>
<name>ref-addresses</name>
<description>ref-addresses</description>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://exoua.dnsalias.net/jcr"/>
<property name="username" value="exoadmin"/>
<property name="password" value="exo12321"/>
<property name="maxActive" value="50"/>
<property name="maxIdle" value="5"/>
<property name="initialSize" value="5"/>
</properties-param>
</init-params>
</component-plugin>
<component-plugins>
<init-params>
<value-param>
<name>default-context-factory</name>
<value>org.exoplatform.services.naming.SimpleContextFactory</value>
</value-param>
</init-params>
</component>- driverClassName, e.g. "org.hsqldb.jdbcDriver", "com.mysql.jdbc.Driver", "org.postgresql.Driver"
- url, e.g. "jdbc:hsqldb:file:target/temp/data/portal", "jdbc:mysql://exoua.dnsalias.net/jcr"
- username, e.g. "sa", "exoadmin"
- password, e.g. "", "exo12321"
- maxActive, e.g. 50
- maxIdle, e.g. 5
- initialSize, e.g. 5
- and other according to Apache DBCP configuration
<workspaces> <workspace name="ws" auto-init-root-nodetype="nt:unstructured"> <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer"> <properties> <property name="source-name" value="jdbcjcr"/> <property name="dialect" value="hsqldb"/> <property name="multi-db" value="true"/> <property name="max-buffer-size" value="200K"/> <property name="swap-directory" value="target/temp/swap/ws"/> </properties> </container> <cache enabled="true"> <properties> <property name="max-size" value="10K"/><!-- 10Kbytes --> <property name="live-time" value="30m"/><!-- 30 min --> </properties> </cache> <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"> <properties> <property name="index-dir" value="target/temp/index"/> </properties> </query-handler> <lock-manager> <time-out>15m</time-out><!-- 15 min --> <persister class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister"> <properties> <property name="path" value="target/temp/lock/ws"/> </properties> </persister> </lock-manager> </workspace> <workspace name="ws1" auto-init-root-nodetype="nt:unstructured"> <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer"> <properties> <property name="source-name" value="jdbcjcr1"/> <property name="dialect" value="mysql"/> <property name="multi-db" value="true"/> <property name="max-buffer-size" value="200K"/> <property name="swap-directory" value="target/temp/swap/ws1"/> </properties> </container> <cache enabled="true"> <properties> <property name="max-size" value="10K"/> <property name="live-time" value="5m"/> </properties> </cache> <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"> <properties> <property name="index-dir" value="target/temp/index"/> </properties> </query-handler> <lock-manager> <time-out>15m</time-out><!-- 15 min --> <persister class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister"> <properties> <property name="path" value="target/temp/lock/ws1"/> </properties> </persister> </lock-manager> </workspace> </workspaces>
- source-name - a javax.sql.DataSource name configured in InitialContextInitializer component (was sourceName prior JCR 1.9);
- dialect - a database dialect, one of "hsqldb", "mysql", "mysql-utf8", "pgsql", "oracle", "oracle-oci", "mssql", "sybase", "derby", "db2", "db2v8".
- multi-db - enable multi-database container with this parameter (set value "true");
- max-buffer-size - a threshold (in bytes) after which a javax.jcr.Value content will be swapped to a file in a temporary storage. I.e. swap for pending changes.
- swap-directory - a path in the file system used to swap the pending changes.
3 Single-database configuration
It's more simple to configure a single-database data container. We have to configure one naming resource. Example (embedded mode for jdbcjcr data container):<external-component-plugins>
<target-component>org.exoplatform.services.naming.InitialContextInitializer</target-component>
<component-plugin>
<name>bind.datasource</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
<init-params>
<value-param>
<name>bind-name</name>
<value>jdbcjcr</value>
</value-param>
<value-param>
<name>class-name</name>
<value>javax.sql.DataSource</value>
</value-param>
<value-param>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</value-param>
<properties-param>
<name>ref-addresses</name>
<description>ref-addresses</description>
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://exoua.dnsalias.net/portal"/>
<property name="username" value="exoadmin"/>
<property name="password" value="exo12321"/>
<property name="maxActive" value="50"/>
<property name="maxIdle" value="5"/>
<property name="initialSize" value="5"/>
</properties-param>
</init-params>
</component-plugin>
</external-component-plugins><workspaces> <workspace name="ws" auto-init-root-nodetype="nt:unstructured"> <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer"> <properties> <property name="source-name" value="jdbcjcr"/> <property name="dialect" value="pgsql"/> <property name="multi-db" value="false"/> <property name="max-buffer-size" value="200K"/> <property name="swap-directory" value="target/temp/swap/ws"/> </properties> </container> <cache enabled="true"> <properties> <property name="max-size" value="10K"/> <property name="live-time" value="30m"/> </properties> </cache> <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"> <properties> <property name="index-dir" value="../temp/index"/> </properties> </query-handler> <lock-manager> <time-out>15m</time-out> <persister class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister"> <properties> <property name="path" value="target/temp/lock/ws"/> </properties> </persister> </lock-manager> </workspace> <workspace name="ws1" auto-init-root-nodetype="nt:unstructured"> <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer"> <properties> <property name="source-name" value="jdbcjcr"/> <property name="dialect" value="pgsql"/> <property name="multi-db" value="false"/> <property name="max-buffer-size" value="200K"/> <property name="swap-directory" value="target/temp/swap/ws1"/> </properties> </container> <cache enabled="true"> <properties> <property name="max-size" value="10K"/> <property name="live-time" value="5m"/> </properties> </cache> <lock-manager> <time-out>15m</time-out> <persister class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister"> <properties> <property name="path" value="target/temp/lock/ws1"/> </properties> </persister> </lock-manager> </workspace> </workspaces>
3.1 Configuration without DataSource
Repository configuration without using of the javax.sql.DataSource bounded in JNDI. This case may be usable if you have a dedicated JDBC driver implementation with special features like XA transactions, statements/connections pooling etc:- You have to remove the configuration in InitialContextInitializer for your database and configure a new one directly in the workspace container.
- Remove parameter "source-name" and add next lines instead. Describe your values for a JDBC driver, database url and username.
<workspace name="ws" auto-init-root-nodetype="nt:unstructured"> <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer"> <properties> <property name="dialect" value="hsqldb"/> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> <property name="url" value="jdbc:hsqldb:file:target/temp/data/portal"/> <property name="username" value="su"/> <property name="password" value=""/> ......
3.2 Dynamic Workspace Creation
Workspaces can be added dynamically during runtime. This can be performed in two steps:- Firstly, ManageableRepository.configWorkspace(WorkspaceEntry wsConfig) - register a new configuration in RepositoryContainer and create a WorkspaceContainer.
- Secondly, the main step,ManageableRepository.createWorkspace(String workspaceName) - creation of a new workspace.
4 Notes for Microsoft Windows users
The current configuration of eXo JCR uses Apache DBCP connection pool (org.apache.commons.dbcp.BasicDataSourceFactory). It's possible to set a big value for maxActive parameter in configuration.xml. That means usage of lots of TCP/IP ports from a client machine inside the pool (i.e. JDBC driver). As a result the data container can throw exceptions like "Address already in use". To solve this problem you have to configure the client's machine networking software for the usage of shorter timeouts for opened TCP/IP ports. Microsoft Windows has MaxUserPort, TcpTimedWaitDelay registry keys in the node HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters, by default these keys are unset, set each one with values like these:- "TcpTimedWaitDelay"=dword:0000001e, sets TIME_WAIT parameter to 30 seconds, default is 240.
- "MaxUserPort"=dword:00001b58, sets the maximum of open ports to 7000 or higher, default is 5000.
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters] "MaxUserPort"=dword:00001b58 "TcpTimedWaitDelay"=dword:0000001e
on 09/12/2009 at 16:17