Table of Contents
To run Nuxeo EP for real-world application, you need to get rid of the default embedded database and set up a real RDBMS server (such as PostgreSQL, MySQL, Oracle, etc.) to store Nuxeo EP's data.
In order to define a SQL DB as repository back-end you have to :
install the JDBC driver for your DBMS,
configure the Nuxeo Core storage, modifying the default repository configuration,
configure your database.
Eventually, configure storage for other Nuxeo services.
You may also add a new repository configuration (and optionally disable the old one).
Nuxeo EP manages several types of data: Documents, relations, audit trail, users, groups ...
Each type of data has its own storage engine and can be configured separately. All storages can use RDBMS but some of them can also use the filesystem.
This means you can have a RDBMS only configuration or a mixed configuration using RDBMS and filesystem. You can even use several RDBMS if you find a use case for that.
For a lot of services, RDBMS access are encapsulated by JPA or hibernate calls, so the storage should be RDBMS agnostic as long as there is a hibernate dialect for the DB.
To enable the connection to the database, you first need to install
the JDBC driver into
$JBOSS_HOME/server/default/lib/
.
Here are some drivers download locations:
Nuxeo Core stores data for the documents themselves: the hierarchy of documents, their metadata and security, and the attached files. There are two main Nuxeo Core Storage backends: the recent (available in Nuxeo 5.2) Visible Contents Store (VCS), based on a mapper to native RDBMS tables, and the previous JCR-based backend, using Jackrabbit.
This section will show you how to configure each backend, using PostgreSQL 8.3 as an example underlying storage. The setup for other RDBMS should be very similar.
To set up VCS, you first need create a datasource for it. The
datasource is not a standard JDBC datasource, so
has different syntax, even though it contains information about JDBC
connection parameters. This file is usually named
$JBOSS_HOME/server/default/deploy/nuxeo.ear/datasources/default-repository-ds.xml
.
<?xml version="1.0"?> <connection-factories> <tx-connection-factory> <jndi-name>NXRepository/default</jndi-name> <xa-transaction/> <track-connection-by-tx/> <adapter-display-name>Nuxeo SQL Repository DataSource</adapter-display-name> <rar-name>nuxeo.ear#nuxeo-core-storage-sql-ra-1.5-SNAPSHOT.rar</rar-name> <connection-definition>org.nuxeo.ecm.core.storage.sql.Repository</connection-definition> <config-property name="name">default</config-property> <config-property name="xaDataSource" type="java.lang.String">org.postgresql.xa.PGXADataSource</config-property> <config-property name="property" type="java.lang.String">ServerName=localhost</config-property> <config-property name="property" type="java.lang.String">PortNumber/Integer=5432</config-property> <config-property name="property" type="java.lang.String">DatabaseName=nuxeo</config-property> <config-property name="property" type="java.lang.String">User=nuxeo</config-property> <config-property name="property" type="java.lang.String">Password=password</config-property> <max-pool-size>20</max-pool-size> </tx-connection-factory> </connection-factories>
Example 43.1. Datasource for VCS using PostgreSQL
You will then need to specify the actual repository configuration,
usually store in a file named
$JBOSS_HOME/server/default/deploy/nuxeo.ear/config/default-repository-config.xml
<?xml version="1.0"?> <component name="default-repository-config"> <extension target="org.nuxeo.ecm.core.repository.RepositoryService" point="repository"> <repository name="default" factory="org.nuxeo.ecm.core.storage.sql.coremodel.SQLRepositoryFactory"> <repository name="default"> <indexing> <!-- example configuration for H2 <fulltext analyzer="org.apache.lucene.analysis.fr.FrenchAnalyzer"/> --> <!-- example configuration for PostgreSQL <fulltext analyzer="french"/> --> <!-- example configuration for Microsoft SQL Server <fulltext catalog="nuxeo" analyzer="french"/> --> </indexing> <!-- uncomment this to enable clustering delay is in milliseconds default delay is 0 (no delay before processing invalidations) <clustering enabled="true" delay="1000" /> --> </repository> </repository> </extension> </component>
Example 43.2. Repository Configuration for VCS
First you have to specify a datasource in
$JBOSS_HOME/server/default/deploy/nuxeo.ear/datasources/default-repository-ds.xml
.
<?xml version="1.0"?> <!DOCTYPE connection-factories PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN" "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd"> <connection-factories> <mbean code="org.nuxeo.ecm.core.repository.JBossRepository" name="nx:type=repository,name=default"> <constructor> <arg type="java.lang.String" value="default"/> </constructor> </mbean> <tx-connection-factory> <jndi-name>NXRepository/default</jndi-name> <adapter-display-name>NX Repository Adapter</adapter-display-name> <rar-name>nuxeo.ear#nuxeo-core-jca-${project.version}.rar</rar-name> <connection-definition>org.nuxeo.ecm.core.model.Repository</connection-definition> <xa-transaction/> <!-- Configuration properties. --> <config-property name="name">default</config-property> </tx-connection-factory> </connection-factories>
Example 43.3. Datasource for JCR backend
Then edit
$JBOSS_HOME/server/default/deploy/nuxeo.ear/config/default-repository-config.xml
.
<?xml version="1.0"?> <component name="default-repository-config"> <documentation> Defines the default JackRabbit repository used for development and testing. </documentation> <extension target="org.nuxeo.ecm.core.repository.RepositoryService" point="repository"> <documentation> Declare a JackRabbit repository to be used for development and tests. The extension content is the Jackrabbit XML configuration of the repository. </documentation> <repository name="default" factory="org.nuxeo.ecm.core.repository.jcr.JCRRepositoryFactory" securityManager="org.nuxeo.ecm.core.repository.jcr.JCRSecurityManager" forceReloadTypes="false"> <Repository> <!-- virtual file system where the repository stores global state (e.g. registered namespaces, custom node types, etc.) --> <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem"> <param name="path" value="${rep.home}/repository" /> </FileSystem> <!-- security configuration --> <Security appName="Jackrabbit"> <!-- access manager: class: FQN of class implementing the AccessManager interface --> <AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager"> <!-- <param name="config" value="${rep.home}/access.xml"/> --> </AccessManager> <LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule"> <!-- anonymous user name ('anonymous' is the default value) --> <param name="anonymousId" value="anonymous" /> <!-- default user name to be used instead of the anonymous user when no login credentials are provided (unset by default) --> <!-- <param name="defaultUserId" value="superuser"/> --> </LoginModule> </Security> <!-- location of workspaces root directory and name of default workspace --> <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default" /> <!-- workspace configuration template: used to create the initial workspace if there's no workspace yet --> <Workspace name="${wsp.name}"> <!-- virtual file system of the workspace: class: FQN of class implementing the FileSystem interface --> <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem"> <param name="path" value="${wsp.home}" /> </FileSystem> <!-- persistence manager of the workspace: class: FQN of class implementing the PersistenceManager interface --> <PersistenceManager class="org.apache.jackrabbit.core.state.obj.ObjectPersistenceManager"> </PersistenceManager> <!-- Search index and the file system it uses. class: FQN of class implementing the QueryHandler interface --> <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex"> <param name="path" value="${wsp.home}/index" /> </SearchIndex> </Workspace> <!-- Configures the versioning --> <Versioning rootPath="${rep.home}/version"> <!-- Configures the filesystem to use for versioning for the respective persistence manager --> <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem"> <param name="path" value="${rep.home}/version" /> </FileSystem> <!-- Configures the persistence manager to be used for persisting version state. Please note that the current versioning implementation is based on a 'normal' persistence manager, but this could change in future implementations. --> <PersistenceManager class="org.apache.jackrabbit.core.state.obj.ObjectPersistenceManager"> </PersistenceManager> </Versioning> <!-- Search index for content that is shared repository wide (/jcr:system tree, contains mainly versions) --> <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex"> <param name="path" value="${rep.home}/repository/index" /> </SearchIndex> </Repository> </repository> </extension> </component>
Example 43.4. Default repository configuration
Change the two PersistenceManager
sections
defining various database connection settings.
Refer to the Jackrabbit documentation for more information, and to the Jackrabbit Javadoc for details about configuring the PersistenceManager.
In particular, decide if you want the binary blobs stored inside
the database or in the filesystem (change externalBLOBs
to
true
if you want them outside the database, in the
filesystem).
Using externalized Blobs can provide a performance improvement in particular if you need to store a lot of big files. Depending on the RDBMS used, there may also be a max size limit for blob if you store them in the RDBMS (for PostgeSQL 8.2 blobs are limited to 1 GB).
Here are some examples:
<!-- Workspaces configuration. Nuxeo only uses the default workspace. --> (...) <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.PostgreSQLPersistenceManager"> <param name="driver" value="org.postgresql.Driver"/> <param name="url" value="jdbc:postgresql://localhost/nuxeo"/> <param name="user" value="postgres"/> <param name="password" value="password"/> <param name="schema" value="postgresql"/> <param name="schemaObjectPrefix" value="jcr_${wsp.name}_"/> <param name="externalBLOBs" value="false"/> </PersistenceManager> (...) <!-- Versioning configuration. --> (...) <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.PostgreSQLPersistenceManager"> <param name="driver" value="org.postgresql.Driver"/> <param name="url" value="jdbc:postgresql://localhost/nuxeo"/> <param name="user" value="postgres"/> <param name="password" value="password"/> <param name="schema" value="postgresql"/> <param name="schemaObjectPrefix" value="jcr_ver_"/> <param name="externalBLOBs" value="false"/> </PersistenceManager>
Example 43.5. Sample configuration for a PostgreSQL Jackrabbit repository
<!-- Workspaces configuration. Nuxeo only uses the default workspace. --> (...) <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.MySqlPersistenceManager"> <param name="driver" value="com.mysql.jdbc.Driver"/> <param name="url" value="jdbc:mysql://localhost/nuxeo"/> <param name="user" value="mysql"/> <param name="password" value="password"/> <param name="schema" value="mysql"/> <param name="schemaObjectPrefix" value="jcr_${wsp.name}_"/> <param name="externalBLOBs" value="true"/> </PersistenceManager> (...) <!-- Versioning configuration. --> (...) <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.MySqlPersistenceManager"> <param name="driver" value="com.mysql.jdbc.Driver"/> <param name="url" value="jdbc:mysql://localhost/nuxeo"/> <param name="user" value="mysql"/> <param name="password" value="password"/> <param name="schema" value="mysql"/> <param name="schemaObjectPrefix" value="jcr_ver_"/> <param name="externalBLOBs" value="true"/> </PersistenceManager>
Example 43.6. Sample configuration for a MySQL Jackrabbit repository
Note: "schemaObjectPrefix" must have different values in workspace & versioning configuration
For JackRabbit, there are some persistence manager specific to each RDBMS :
for PostgreSQL: you may use org.apache.jackrabbit.core.persistence.bundle.PostgreSQLPersistenceManager
for MySQL: you may use org.apache.jackrabbit.core.persistence.bundle.MySqlPersistenceManager
for Oracle 10: you may use org.apache.jackrabbit.core.persistence.bundle.OraclePersistenceManager
for MSSQL2005 you may use : org.apache.jackrabbit.core.persistence.bundle.MSSqlPersistenceManager
Create the database in the database server, enable IP connection, setup permissions and test the connection.
Many services beyond Nuxeo Core Repository are using an SQL database to persist their data, such as:
Relations Service: RDF data is stored in SQL,
Audit Service: Audit logs are stored via JPA,
Tag Service: the tagging entities are stored in a table in the default Nuxeo DB via JPA,
Directories: entries can be stored into an SQL database.
By default, all these services use the JBoss AS's embedded HSQLDB.
Each service can use a dedicated datasource to define the database connection. However, to simplify configuration, all datasources are JNDI NamingAlias pointing to a single datasource (NuxeoDS). If you want to change the default database, you can simply do the following:
deploy the needed JDBC Driver in
$JBOSS_HOME/server/default/lib
,
modify the datasource definition file in
$JBOSS_HOME/server/default/deploy/nuxeo.ear/datasources/unified-nuxeo-ds.xml
.
The default configuration has a commented out PostgresSQL configuration.
To use a dedicated datasource for a service, you need to modify
its configuration file. If you would like to store audit logs in
PostgreSQL using its own datasource, remove the NamingAlias in
nxaudit-logs-ds.xml
and replace it with the
datasource configuration example:
<?xml version="1.0"?> <datasources> <local-tx-datasource> <jndi-name>nxaudit-logs</jndi-name> <connection-url>jdbc:postgresql://localhost/logs</connection-url> <driver-class>org.postgresql.Driver</driver-class> <user-name>username</user-name> <password>password</password> </local-tx-datasource> </datasources>
Example 43.7. Datasource for the Audit Service using PostgreSQL
We recommend to enable XA transactions if your database server support it (for PostgreSQL, you have to use 8.x versions). The following datasource definition example enables XA transaction for the Audit Service using PostgreSQL.
<?xml version="1.0"?> <datasources> <xa-datasource> <jndi-name>nxaudit-logs</jndi-name> <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class> <xa-datasource-property name="ServerName">localhost</xa-datasource-property> <xa-datasource-property name="PortNumber">5432</xa-datasource-property> <xa-datasource-property name="DatabaseName">logs</xa-datasource-property> <xa-datasource-property name="User">postgres</xa-datasource-property> <xa-datasource-property name="Password">password</xa-datasource-property> <track-connection-by-tx/> </xa-datasource> </datasources>
Example 43.8. Datasource for the Audit Service using PostgreSQL with XA transactions
See Datasources Configuration on the JBoss wiki for more examples of datasources.
This method works for most services:
Audit: nxaudit-logs-ds.xml
Placeful Configuration Service & Subscriptions:
nxplaceful-ds.xml
UID generator:
nxuidsequencer-ds.xml
jBPM engine:
nxworkflow-jbpm-ds.xml
Workflow Document Service:
nxworkflow-documents-ds.xml
Archive management:
nxarchive-records-ds.xml
Relations:
nxrelations-default-jena-ds.xml
Compass search engine:
nxsearch-compass-ds.xml
MySQL is a quirky database which sometimes needs very specific options to function properly.
The datasources used by Jena
(nxrelations-default-jena-ds.xml
and
nxcomment-jena-ds.xml
) need to use a "relax
autocommit" mode. To enable that, change the
connection-url
in the datasources to something
like:
<connection-url> jdbc:mysql://localhost/nuxeo?relaxAutoCommit=true </connection-url>
The datasource used by Compass
(nxsearch-compass-ds.xml
) needs to be put in
"relax autocommit" too, and in addition it needs an "emulate locators"
option:
<connection-url> jdbc:mysql://localhost/nuxeo?relaxAutoCommit=true&emulateLocators=true </connection-url>
This is documented at http://static.compassframework.org/docs/latest/jdbcdirectory.html .
Note the &
syntax for the URL parameters
instead of just &
because the URL is embedded in an
XML file.
The Relation Service uses a datasource to define the data storage. However modifying the datasource is not enough, you also have to tell to the Jena engine which database dialect is used, as it doesn't auto-detect it.
To do that, edit the sql.properties
file in
$JBOSS_HOME/server/default/deploy/nuxeo.ear/config/
and change the definition of the
org.nuxeo.ecm.sql.jena.databaseType
property. The possible
values are:
Derby
HSQL
MsSQL
MySQL
Oracle
PostgreSQL
In the same file, the property
org.nuxeo.ecm.sql.jena.databaseTransactionEnabled
is
false
by default, but must be set to true
for
Oracle.
Please refer to the Jena Site for more information about database support.
The value of the above properties are used as variables by the extension point defining the Jena configuration, so that they only have to be changed in one place.
The Tag Service uses a property file to define the data storage. The tagservice-db.properties file needs to be complaint with whatever is set in the default-repository-ds.xml file, as the service is using the same DB.
Also, the tag service allows initialization with through API supplied properties.
Note that this section is obsolete in Nuxeo 5.2, and should not be used anymore.
The Compass plugin is configured using a datasource, but at the
time of this writing it still needs some additional configuration in a
file embedded in its Jar. You should go to
$JBOSS_HOME/server/default/deploy/nuxeo.ear/system/
and inside the directory
nuxeo-platform-search-compass-plugin-5.1-SNAPSHOT.jar
(the version number may be different) then edit the file
compass.cfg.xml
. You will find a section
like:
<connection> <jdbc managed="true" dialectClass="org.apache.lucene.store.jdbc.dialect.HSQLDialect" deleteMarkDeletedDelta="3600000"> <dataSourceProvider> <jndi lookup="java:/nxsearch-compass" /> </dataSourceProvider> </jdbc> </connection>
The dialectClass
has to be changed according to your
datasource configuration. The possible values end with
MySQLDialect
, PostgreSQLDialect
, etc. They
are documented in the
Compass documention about SQL dialects .
If you just want to change the default
repository name
appearing in the url http://.../nuxeo/nxdoc/default/
, modify
the repository name value in:
default-repository-config.xml
platform-config.xml
TODO: Nuxeo configuration has changed, the two above sections need to be updated.
Create a repository definition as a contribution to the extension
point
org.nuxeo.ecm.core.repository.RepositoryService
(for example: MyRepo-repositoy-config.xml
) in
$JBOSS_HOME/server/default/deploy/nuxeo.ear/config/
.
You can take example on the default repository definition $JBOSS_HOME/server/default/deploy/nuxeo.ear/config/default-repository-config.xml.
You have to properly configure the following aspects:
the name of the component
(name="org.nuxeo.project.sample.repository.MyRepo"
),
which must be unique among component names,
the name of the repository (<repository
name="MyRepo">
), which is used to refer to it from your
application and must also be unique among repository names,
the various database connection settings (driver, user, password, schema, etc.),
decide if you want the binary blobs stored inside the
database or in the filesystem (change externalBLOBs
to true
if you want them outside the
database).
Refer to the Jackrabbit
documentation for more information, and to the Jackrabbit
Javadoc for details about configuring the
BundleDbPersistenceManager
.
<?xml version="1.0"?> <component name="org.nuxeo.project.sample.repository.MyRepo"> <extension target="org.nuxeo.ecm.core.repository.RepositoryService" point="repository"> <repository name="MyRepo" factory="org.nuxeo.ecm.core.repository.jcr.JCRRepositoryFactory" securityManager="org.nuxeo.ecm.core.repository.jcr.JCRSecurityManager" forceReloadTypes="false"> <Repository> <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem"> <param name="path" value="${rep.home}/repository"/> </FileSystem> <Security appName="Jackrabbit"> <AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager"> </AccessManager> <LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule"> <param name="anonymousId" value="anonymous"/> </LoginModule> </Security> <!-- Workspaces configuration. Nuxeo only uses the default workspace. --> <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default"/> <Workspace name="${wsp.name}"> <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem"> <param name="path" value="${wsp.home}"/> </FileSystem> <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.PostgreSQLPersistenceManager"> <param name="driver" value="org.postgresql.Driver"/> <param name="url" value="jdbc:postgresql://localhost/nuxeo"/> <param name="user" value="postgres"/> <param name="password" value="password"/> <param name="schema" value="postgresql"/> <param name="schemaObjectPrefix" value="jcr_${wsp.name}_"/> <param name="externalBLOBs" value="false"/> </PersistenceManager> <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex"> <param name="path" value="${wsp.home}/index"/> </SearchIndex> </Workspace> <!-- Versioning configuration. --> <Versioning rootPath="${rep.home}/version"> <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem"> <param name="path" value="${rep.home}/version"/> </FileSystem> <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.PostgreSQLPersistenceManager"> <param name="driver" value="org.postgresql.Driver"/> <param name="url" value="jdbc:postgresql://localhost/nuxeo"/> <param name="user" value="postgres"/> <param name="password" value="password"/> <param name="schema" value="postgresql"/> <param name="schemaObjectPrefix" value="jcr_ver_"/> <param name="externalBLOBs" value="false"/> </PersistenceManager> </Versioning> <!-- Index for repository-wide information, mainly versions. --> <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex"> <param name="path" value="${rep.home}/repository/index"/> </SearchIndex> </Repository> </repository> </extension> </component>
Example 43.9. Sample configuration for a PostgreSQL Jackrabbit repository
TODO: this should be moved to a different section as it doesn't pertain to the SQL configuration itself.
You have now replaced the default repository
(demo
) with your newly defined one
(MyRepo
). To actually use it, create or edit the file
MyPlatform-Layout-config.xml
in
$JBOSS_HOME/server/default/deploy/nuxeo.ear/config/
and configure the parameters as shown in the following example.
<?xml version="1.0"?> <component name="MyPlatformLayout"> <require>org.nuxeo.ecm.platform.api.DefaultPlatform</require> <extension target="org.nuxeo.ecm.platform.util.LocationManagerService" point="location"> <locationManagerPlugin> <!-- This disable the default (demo) repository --> <locationEnabled>false</locationEnabled> <locationName>demo</locationName> </locationManagerPlugin> <locationManagerPlugin> <!-- This enable your new repository --> <locationEnabled>true</locationEnabled> <locationName>MyRepo</locationName> <!-- Use the name of your repository --> </locationManagerPlugin> </extension> <extension target="org.nuxeo.ecm.core.api.repository.RepositoryManager" point="repositories"> <documentation>The default repository</documentation> <repository name="MyRepo" label="My Repository"/> </extension> <extension target="org.nuxeo.runtime.api.ServiceManagement" point="services"> <service class="org.nuxeo.ecm.core.api.CoreSession" name="MyRepo" group="core"> <locator>%DocumentManagerBean</locator> </service> </extension> </component>
This sample configuration creates a new repository in the
core
Group that will be assigned to the default
server. If you want to have it located on an other server you can
use:
<extension target="org.nuxeo.runtime.api.ServiceManagement" point="servers"> <!-- define new locator for group MyGroup --> <server class="org.nuxeo.runtime.api.JBossServiceLocator"> <group>MyGroup</group> <property name="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</property> <property name="java.naming.provider.url">jnp://MyServer:1099</property> <property name="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</property> </server> <!-- bind MyRepo to MyGroup --> <extension target="org.nuxeo.runtime.api.ServiceManagement" point="services"> <service class="org.nuxeo.ecm.core.api.CoreSession" name="MyRepo" group="MyGroup"> <locator>%DocumentManagerBean</locator> </service> </extension> </extension>