Author: sergiykarpenko
Date: 2010-08-23 06:23:16 -0400 (Mon, 23 Aug 2010)
New Revision: 2968
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/concepts/jcr-registry-service.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/data-container.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/kernel/service-configuration-in-detail.xml
Log:
EXOJCR-912: ids and xml injection fixed
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml 2010-08-23
07:45:14 UTC (rev 2967)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml 2010-08-23
10:23:16 UTC (rev 2968)
@@ -1,477 +1,477 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="JCR.BackupService">
- <?dbhtml filename="ch-exojcr-backup-service.html"?>
-
- <title>eXo JCR Backup Service</title>
-
- <section id="Concept">
- <title>Concept</title>
-
- <para>The main purpose of that feature is to restore data in case of
- system faults and repository crashes. Also the backup results may be used
- as a content history.</para>
-
- <para>The eXo JCR backup service was developed from the JCR 1.8
- implementation. It's an independent service available as an eXo JCR
- Extensions project.</para>
-
- <para>The concept is based on the export of a workspace unit in the Full,
- or Full + Incrementals model. A repository workspace can be backup and
- restored using a combination of these modes. In all cases, at least one
- Full (initial) backup must be executed to mark a starting point of the
- backup history. An Incremental backup is not a complete image of the
- workspace. It contains only changes for some period. So it is not possible
- to perform an Incremental backup without an initial Full backup.</para>
-
- <para>The Backup service may operate as a hot-backup process at runtime on
- an in-use workspace. It's a case when the Full + Incrementals model should
- be used to have a guaranty of data consistency during restoration. An
- Incremental will be run starting from the start point of the Full backup
- and will contain changes that have occured during the Full backup
- too.</para>
-
- <para>A <emphasis role="bold">restore</emphasis>
operation is a mirror of
- a backup one. At least one Full backup should be restored to obtain a
- workspace corresponding to some point in time. On the other hand,
- Incrementals may be restored in the order of creation to reach a required
- state of a content. If the Incremental contains the same data as the Full
- backup (hot-backup), the changes will be applied again as if they were
- made in a normal way via API calls.</para>
-
- <para>According to the model there are several modes for backup
- logic:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">Full backup
only</emphasis> : single
- operation, runs once</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">Full +
Incrementals</emphasis> : Start
- with an initial Full backup and then keep incrementals changes in one
- file. Runs until it is stopped.</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">Full +
Incrementals(periodic)</emphasis> :
- Start with an initial Full backup and then keep incrementals with
- periodic result file rotation. Runs until it is stopped.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>How it works</title>
-
- <section>
- <title>Implementation details</title>
-
- <para>Full backup/restore is implemented using the JCR SysView
- Export/Import. Workspace data will be exported into Sysview XML data
- from root node.</para>
-
- <para>Restore is implemented using the special eXo JCR API feature: a
- dynamic workspace creation. Restoring of the workspace Full backup will
- create one new workspace in the repository. Then the SysView XML data
- will be imported as the root node.</para>
-
- <para>Incremental backup is implemented using the eXo JCR ChangesLog
- API. This API allows to record each JCR API call as atomic entries in a
- changelog. Hence, the Incremental backup uses a listener that collects
- these logs and stores them in a file.</para>
-
- <para>Restoring an incremental backup consists in applying the collected
- set of ChangesLogs to a workspace in the correct order.</para>
- </section>
-
- <section>
- <title>Work basics</title>
-
- <para>The work of Backup is based on the BackupConfig configuration and
- the BackupChain logical unit.</para>
-
- <para>BackupConfig describes the backup operation chain that will be
- performed by the service. When you intend to work with it, the
- configuration should be prepared before the backup is started.</para>
-
- <para>The configuration contains such values as:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">types of full and
incremental
- backup</emphasis> - (fullBackupType, incrementalBackupType) Strings
- with full names of classes which will cover the type
- functional.</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">incremental
period</emphasis> - a period
- after that a current backup will be stopped and a new one will be
- started, in seconds (long).</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">target repository and
workspace
- names</emphasis> - Strings with described names</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">destination
directory</emphasis> for
- result files - String with a path to a folder where operation result
- files will be stored.</para>
- </listitem>
- </itemizedlist>
-
- <para>BackupChain is a unit performing the backup process and it covers
- the principle of initial Full backup execution and manages Incrementals
- operations. BackupChain is used as a key object for accessing current
- backups during runtime via BackupManager. Each BackupJob performs a
- single atomic operation - a Full or Incremental process. The result of
- that operation is data for a Restore. BackupChain can contain one or
- more BackupJobs. But at least the initial Full job is always there. Each
- BackupJobs has its own unique number which means its Job order in the
- chain, the initial Full job always has the number 0.</para>
-
- <para><emphasis role="bold">Backup process, result data and
file
- location</emphasis></para>
-
- <para>To start the backup process it's necessary to create the
- BackupConfig and call the BackupManager.startBackup(BackupConfig)
- method. This method will return BackupChain created according to the
- configuration. At the same time the chain creates a BackupChainLog which
- persists BackupConfig content and BackupChain operation states to the
- file in the service working directory (see Configuration).</para>
-
- <para>When the chain starts the work and the initial BackupJob starts,
- the job will create a result data file using the destination directory
- path from BackupConfig. The destination directory will contain a
- directory with an automatically created name using the pattern
- repository_workspace-timestamp where timestamp is current time in the
- format of yyyyMMdd_hhmmss (E.g. db1_ws1-20080306_055404). The directory
- will contain the results of all Jobs configured for execution. Each Job
- stores the backup result in its own file with the name
- repository_workspace-timestamp.jobNumber. BackupChain saves each state
- (STARTING, WAITING, WORKING, FINISHED) of its Jobs in the
- BackupChainLog, which has a current result full file path.</para>
-
- <para>BackupChain log file and job result files are a whole and
- consistent unit, that is a source for a Restore.</para>
-
- <note>
- <para>BackupChain log contains absolute paths to job result files.
- Don't move these files to another location.</para>
- </note>
-
- <para><emphasis role="bold">Restore
requirements</emphasis></para>
-
- <para>As mentioned before a Restore operation is a mirror of a Backup.
- The process is a Full restore of a root node with restoring an
- additional Incremental backup to reach a desired workspace state.
- Restoring of the workspace Full backup will create a new workspace in
- the repository using given RepositoyEntry of existing repository and
- given (preconfigured) WorkspaceEntry for a new target workspace. A
- Restore process will restore a root node there from the SysView XML
- data.</para>
-
- <note>
- <para>The target workspace should not be in the repository. Otherwise
- a BackupConfigurationException exception will be thrown.</para>
- </note>
-
- <para>Finally we may say that a Restore is a process of a new Workspace
- creation and filling it with a Backup content. In case you already have
- a target Workspace (with the same name) in a Repository, you have to
- configure a new name for it. If no target workspace exists in the
- Repository you may use the same name as the Backup one.</para>
- </section>
- </section>
-
- <section>
- <title>Configuration</title>
-
- <para>As an optional extension, the Backup service is not enabled by
- default. <emphasis role="bold">You need to enable it via
- configuration</emphasis>.</para>
-
- <para>Below is an example configuration compatible with JCR 1.9.3 and
- later :</para>
-
- <programlisting><component>
-
<key>org.exoplatform.services.jcr.ext.backup.BackupManager</key>
-
<type>org.exoplatform.services.jcr.ext.backup.impl.BackupManagerImpl</type>
- <init-params>
- <properties-param>
- <name>backup-properties</name>
- <property name="default-incremental-job-period"
value="3600" /> <!-- set default incremental period = 60 minutes
-->
- <property name="full-backup-type"
value="org.exoplatform.services.jcr.ext.backup.impl.fs.FullBackupJob" />
- <property name="incremental-backup-type"
value="org.exoplatform.services.jcr.ext.backup.impl.fs.IncrementalBackupJob"
/>
- <property name="backup-dir" value="target/backup"
/>
- </properties-param>
- </init-params>
-</component></programlisting>
-
- <para>Where:<itemizedlist>
- <listitem>
- <para><emphasis
role="bold">incremental-backup-type</emphasis>
- (since 1.9.3) : the FQN of incremental job class. Must implement
- org.exoplatform.services.jcr.ext.backup.BackupJob</para>
- </listitem>
-
- <listitem>
- <para><emphasis
role="bold">full-backup-type</emphasis> (since
- 1.9.3) : the FQN of the full backup job class; Must implement
- org.exoplatform.services.jcr.ext.backup.BackupJob</para>
- </listitem>
-
- <listitem>
- <para><emphasis
- role="bold">default-incremental-job-period</emphasis> (since
1.9.3)
- :the period between incremetal flushes (in seconds)</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">backup-dir</emphasis> :
the path to a
- working directory where the service will store internal files and
- chain logs.</para>
- </listitem>
- </itemizedlist></para>
- </section>
-
- <section>
- <title>Usage</title>
-
- <section>
- <title>Perform a Backup</title>
-
- <para>In following example we create a BackupConfig bean for the Full +
- Incrementals mode, then we ask the BackupManager to start the backup
- process.</para>
-
- <programlisting>// Obtaining the backup service from the eXo container.
-BackupManager backup = (BackupManager)
container.getComponentInstanceOfType(BackupManager.class);
-
-// And prepare the BackupConfig instance with custom parameters.
-// full backup & incremental
-File backDir = new File("/backup/ws1"); // the destination path for result
files
-backDir.mkdirs();
-
-BackupConfig config = new BackupConfig();
-config.setRepository(repository.getName());
-config.setWorkspace("ws1");
-config.setBackupDir(backDir);
-
-// Before 1.9.3, you also need to indicate the backupjobs class FDNs
-//
config.setFullBackupType("org.exoplatform.services.jcr.ext.backup.impl.fs.FullBackupJob");
-//
config.setIncrementalBackupType("org.exoplatform.services.jcr.ext.backup.impl.fs.IncrementalBackupJob");
-
-// start backup using the service manager
-BackupChain chain = backup.startBackup(config);</programlisting>
-
- <para>To stop the backup operation you have to use the BackupChain
- instance.</para>
-
- <programlisting>// stop backup
-backup.stopBackup(chain);</programlisting>
- </section>
-
- <section>
- <title>Perform a Restore</title>
-
- <para>Restoration involves the reloading the backup file into a
- BackupChainLog and applying appropriate workspace initialization. The
- following snippet shows the typical sequence for restoring a workspace
- :</para>
-
- <programlisting>// find BackupChain using the repository and workspace names
(return null if not found)
-BackupChain chain = backup.findBackup("db1", "ws1");
-
-// Get the RepositoryEntry and WorkspaceEntry
-ManageableRepository repo = repositoryService.getRepository(repository);
-RepositoryEntry repoconf = repo.getConfiguration();
-List<WorkspaceEntry> entries = repoconf.getWorkspaceEntries();
-WorkspaceEntry = getNewEntry(entries, workspace); // create a copy entry from an existing
one
-
-// restore backup log using ready RepositoryEntry and WorkspaceEntry
-File backLog = new File(chain.getLogFilePath());
-BackupChainLog bchLog = new BackupChainLog(backLog);
-
-// initialize the workspace
-repository.configWorkspace(workspaceEntry);
-
-// run restoration
-backup.restore(bchLog, repositoryEntry, workspaceEntry);</programlisting>
-
- <section>
- <title>Restoring into an existing workspace</title>
-
- <note>
- <para>These instructions only applies to regular workspace. Special
- instructions are provided for System workspace below.</para>
- </note>
-
- <para>To restore a backup over an existing workspace, you are required
- to clear its data. Your backup process should follow these steps :
- <itemizedlist>
- <listitem>
- <para>remove workspace<programlisting>ManageableRepository repo
= repositoryService.getRepository(repository);
-repo.removeWorkspace(workspace);</programlisting></para>
- </listitem>
-
- <listitem>
- <para>clean database, value storage, index</para>
- </listitem>
-
- <listitem>
- <para>restore (see snippet above)</para>
- </listitem>
- </itemizedlist></para>
- </section>
-
- <section>
- <title>System workspace</title>
-
- <note>
- <para>The BackupWorkspaceInitializer is available in JCR 1.9 and
- later.</para>
- </note>
-
- <para>Restoring the JCR System workspace requires to shutdown the
- system and use of a special initializer.</para>
-
- <para>Follow these steps (this will also work for normal workspaces) :
- <itemizedlist>
- <listitem>
- <para>Stop repository (or portal)</para>
- </listitem>
-
- <listitem>
- <para>clean database, value storage, index;</para>
- </listitem>
-
- <listitem>
- <para>In configuration the workspace set
- BackupWorkspaceInitializer to reference your backup.</para>
-
- <para>For example :<programlisting><workspaces>
- <workspace name="production" ... >
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- ...
- </container>
- <initializer
class="org.exoplatform.services.jcr.impl.core.BackupWorkspaceInitializer">
- <properties>
- <property name="restore-path"
value="D:\java\exo-working\backup\repository_production-20090527_030434"/>
- </properties>
- </initializer>
- ...
-</workspace></programlisting></para>
- </listitem>
-
- <listitem>
- <para>Start repository (or portal).</para>
- </listitem>
- </itemizedlist></para>
- </section>
- </section>
- </section>
-
- <section>
- <title>Scheduling (experimental)</title>
-
- <para>The Backup service has an additional feature that can be useful for
- a production level backup implementation. When you need to organize a
- backup of a repository it's necessary to have a tool which will be able to
- create and manage a cycle of Full and Incremental backups in periodic
- manner.</para>
-
- <para>The service has internal BackupScheduler which can run a
- configurable cycle of BackupChains as if they have been executed by a user
- during some period of time. I.e. BackupScheduler is a user-like daemon
- which asks the BackupManager to start or stop backup operations.</para>
-
- <para>For that purpose BackupScheduler has the method</para>
-
- <para>BackupScheduler.schedule(backupConfig, startDate, stopDate,
- chainPeriod, incrementalPeriod)</para>
-
- <para>where</para>
-
- <itemizedlist>
- <listitem>
- <para>backupConfig - a ready configuration which will be given to the
- BackupManager.startBackup() method</para>
- </listitem>
-
- <listitem>
- <para>startDate - a date and time of the backup start</para>
- </listitem>
-
- <listitem>
- <para>stopDate - a date and time of the backup stop</para>
- </listitem>
-
- <listitem>
- <para>chainPeriod - a period after which a current BackupChain will be
- stopped and a new one will be started, in seconds</para>
- </listitem>
-
- <listitem>
- <para>incrementalPeriod - if it is greater than 0 it will be used to
- override the same value in backupConfig.</para>
- </listitem>
- </itemizedlist>
-
- <programlisting>// geting the scheduler from the BackupManager
- BackupScheduler scheduler = backup.getScheduler();
-
-// schedule backup using a ready configuration (Full + Incrementals) to run from
startTime
-// to stopTime. Full backuop will be performed every 24 hours (BackupChain lifecycle),
-// incremental will rotate result files every 3 hours.
- scheduler.schedule(config, startTime, stopTime, 3600 * 24, 3600 * 3);
-
-// it's possible to run the scheduler for an uncertain period of time (i.e. without
stop time).
-// schedule backup to run from startTime till it will be stopped manually
-// also there, the incremental will rotate result files as it configured in BackupConfig
- scheduler.schedule(config, startTime, null, 3600 * 24, 0);
-
-// to unschedule backup simply call the scheduler with the configuration describing the
-// already planned backup cycle.
-// the scheduler will search in internal tasks list for task with repository and
-// workspace name from the configuration and will stop that task.
- scheduler.unschedule(config);</programlisting>
-
- <para>When the BackupScheduler starts the scheduling, it uses the internal
- Timer with startDate for the first (or just once) execution. If
- chainPeriod is greater than 0 then the task is repeated with this value
- used as a period starting from startDate. Otherwise the task will be
- executed once at startDate time. If the scheduler has stopDate it will
- stop the task ( the chain cycle) after stopDate. And the last parameter
- incrementalPeriod will be used instead of the same from BackupConfig if
- its values are greater than 0.</para>
-
- <para>Starting each task (BackupScheduler.schedule(...)), the scheduler
- creates a task file in the service working directory (see <emphasis
- role="bold">Configuration</emphasis>, backup-dir) which describes
the task
- backup configuration and periodic values. These files will be used at the
- backup service start (JVM start) to reinitialize BackupScheduler for
- continuous task scheduling. Only tasks that don't have a stopDate or a
- stopDate not expired will be reinitialized.</para>
-
- <para>There is one notice about BackupScheduler task reinitialization in
- the current implementation. It comes from the BackupScheduler nature and
- its implemented behaviour. As the scheduler is just a virtual user which
- asks the BackupManager to start or stop backup operations, it isn't able
- to reinitialize each existing BackupChain before the service (JVM) is
- stopped. But it's possible to start a new operation with the same
- configuration via BackupManager (that was configured before and stored in
- a task file).</para>
-
- <para>This is a main detail of the BackupScheduler which should be taken
- into suggestion of a backup operation design now. In case of
- reinitialization the task will have new time values for the backup
- operation cycle as the chainPeriod and incrementalPeriod will be applied
- again. That behaviour may be changed in the future.</para>
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.BackupService">
+ <?dbhtml filename="ch-exojcr-backup-service.html"?>
+
+ <title>eXo JCR Backup Service</title>
+
+ <section>
+ <title>Concept</title>
+
+ <para>The main purpose of that feature is to restore data in case of
+ system faults and repository crashes. Also the backup results may be used
+ as a content history.</para>
+
+ <para>The eXo JCR backup service was developed from the JCR 1.8
+ implementation. It's an independent service available as an eXo JCR
+ Extensions project.</para>
+
+ <para>The concept is based on the export of a workspace unit in the Full,
+ or Full + Incrementals model. A repository workspace can be backup and
+ restored using a combination of these modes. In all cases, at least one
+ Full (initial) backup must be executed to mark a starting point of the
+ backup history. An Incremental backup is not a complete image of the
+ workspace. It contains only changes for some period. So it is not possible
+ to perform an Incremental backup without an initial Full backup.</para>
+
+ <para>The Backup service may operate as a hot-backup process at runtime on
+ an in-use workspace. It's a case when the Full + Incrementals model should
+ be used to have a guaranty of data consistency during restoration. An
+ Incremental will be run starting from the start point of the Full backup
+ and will contain changes that have occured during the Full backup
+ too.</para>
+
+ <para>A <emphasis role="bold">restore</emphasis>
operation is a mirror of
+ a backup one. At least one Full backup should be restored to obtain a
+ workspace corresponding to some point in time. On the other hand,
+ Incrementals may be restored in the order of creation to reach a required
+ state of a content. If the Incremental contains the same data as the Full
+ backup (hot-backup), the changes will be applied again as if they were
+ made in a normal way via API calls.</para>
+
+ <para>According to the model there are several modes for backup
+ logic:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">Full backup
only</emphasis> : single
+ operation, runs once</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">Full +
Incrementals</emphasis> : Start
+ with an initial Full backup and then keep incrementals changes in one
+ file. Runs until it is stopped.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">Full +
Incrementals(periodic)</emphasis> :
+ Start with an initial Full backup and then keep incrementals with
+ periodic result file rotation. Runs until it is stopped.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>How it works</title>
+
+ <section>
+ <title>Implementation details</title>
+
+ <para>Full backup/restore is implemented using the JCR SysView
+ Export/Import. Workspace data will be exported into Sysview XML data
+ from root node.</para>
+
+ <para>Restore is implemented using the special eXo JCR API feature: a
+ dynamic workspace creation. Restoring of the workspace Full backup will
+ create one new workspace in the repository. Then the SysView XML data
+ will be imported as the root node.</para>
+
+ <para>Incremental backup is implemented using the eXo JCR ChangesLog
+ API. This API allows to record each JCR API call as atomic entries in a
+ changelog. Hence, the Incremental backup uses a listener that collects
+ these logs and stores them in a file.</para>
+
+ <para>Restoring an incremental backup consists in applying the collected
+ set of ChangesLogs to a workspace in the correct order.</para>
+ </section>
+
+ <section>
+ <title>Work basics</title>
+
+ <para>The work of Backup is based on the BackupConfig configuration and
+ the BackupChain logical unit.</para>
+
+ <para>BackupConfig describes the backup operation chain that will be
+ performed by the service. When you intend to work with it, the
+ configuration should be prepared before the backup is started.</para>
+
+ <para>The configuration contains such values as:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">types of full and
incremental
+ backup</emphasis> - (fullBackupType, incrementalBackupType) Strings
+ with full names of classes which will cover the type
+ functional.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">incremental
period</emphasis> - a period
+ after that a current backup will be stopped and a new one will be
+ started, in seconds (long).</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">target repository and
workspace
+ names</emphasis> - Strings with described names</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">destination
directory</emphasis> for
+ result files - String with a path to a folder where operation result
+ files will be stored.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>BackupChain is a unit performing the backup process and it covers
+ the principle of initial Full backup execution and manages Incrementals
+ operations. BackupChain is used as a key object for accessing current
+ backups during runtime via BackupManager. Each BackupJob performs a
+ single atomic operation - a Full or Incremental process. The result of
+ that operation is data for a Restore. BackupChain can contain one or
+ more BackupJobs. But at least the initial Full job is always there. Each
+ BackupJobs has its own unique number which means its Job order in the
+ chain, the initial Full job always has the number 0.</para>
+
+ <para><emphasis role="bold">Backup process, result data and
file
+ location</emphasis></para>
+
+ <para>To start the backup process it's necessary to create the
+ BackupConfig and call the BackupManager.startBackup(BackupConfig)
+ method. This method will return BackupChain created according to the
+ configuration. At the same time the chain creates a BackupChainLog which
+ persists BackupConfig content and BackupChain operation states to the
+ file in the service working directory (see Configuration).</para>
+
+ <para>When the chain starts the work and the initial BackupJob starts,
+ the job will create a result data file using the destination directory
+ path from BackupConfig. The destination directory will contain a
+ directory with an automatically created name using the pattern
+ repository_workspace-timestamp where timestamp is current time in the
+ format of yyyyMMdd_hhmmss (E.g. db1_ws1-20080306_055404). The directory
+ will contain the results of all Jobs configured for execution. Each Job
+ stores the backup result in its own file with the name
+ repository_workspace-timestamp.jobNumber. BackupChain saves each state
+ (STARTING, WAITING, WORKING, FINISHED) of its Jobs in the
+ BackupChainLog, which has a current result full file path.</para>
+
+ <para>BackupChain log file and job result files are a whole and
+ consistent unit, that is a source for a Restore.</para>
+
+ <note>
+ <para>BackupChain log contains absolute paths to job result files.
+ Don't move these files to another location.</para>
+ </note>
+
+ <para><emphasis role="bold">Restore
requirements</emphasis></para>
+
+ <para>As mentioned before a Restore operation is a mirror of a Backup.
+ The process is a Full restore of a root node with restoring an
+ additional Incremental backup to reach a desired workspace state.
+ Restoring of the workspace Full backup will create a new workspace in
+ the repository using given RepositoyEntry of existing repository and
+ given (preconfigured) WorkspaceEntry for a new target workspace. A
+ Restore process will restore a root node there from the SysView XML
+ data.</para>
+
+ <note>
+ <para>The target workspace should not be in the repository. Otherwise
+ a BackupConfigurationException exception will be thrown.</para>
+ </note>
+
+ <para>Finally we may say that a Restore is a process of a new Workspace
+ creation and filling it with a Backup content. In case you already have
+ a target Workspace (with the same name) in a Repository, you have to
+ configure a new name for it. If no target workspace exists in the
+ Repository you may use the same name as the Backup one.</para>
+ </section>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>As an optional extension, the Backup service is not enabled by
+ default. <emphasis role="bold">You need to enable it via
+ configuration</emphasis>.</para>
+
+ <para>Below is an example configuration compatible with JCR 1.9.3 and
+ later :</para>
+
+ <programlisting><component>
+
<key>org.exoplatform.services.jcr.ext.backup.BackupManager</key>
+
<type>org.exoplatform.services.jcr.ext.backup.impl.BackupManagerImpl</type>
+ <init-params>
+ <properties-param>
+ <name>backup-properties</name>
+ <property name="default-incremental-job-period"
value="3600" /> <!-- set default incremental period = 60 minutes
-->
+ <property name="full-backup-type"
value="org.exoplatform.services.jcr.ext.backup.impl.fs.FullBackupJob" />
+ <property name="incremental-backup-type"
value="org.exoplatform.services.jcr.ext.backup.impl.fs.IncrementalBackupJob"
/>
+ <property name="backup-dir" value="target/backup"
/>
+ </properties-param>
+ </init-params>
+</component></programlisting>
+
+ <para>Where:<itemizedlist>
+ <listitem>
+ <para><emphasis
role="bold">incremental-backup-type</emphasis>
+ (since 1.9.3) : the FQN of incremental job class. Must implement
+ org.exoplatform.services.jcr.ext.backup.BackupJob</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis
role="bold">full-backup-type</emphasis> (since
+ 1.9.3) : the FQN of the full backup job class; Must implement
+ org.exoplatform.services.jcr.ext.backup.BackupJob</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis
+ role="bold">default-incremental-job-period</emphasis> (since
1.9.3)
+ :the period between incremetal flushes (in seconds)</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">backup-dir</emphasis> :
the path to a
+ working directory where the service will store internal files and
+ chain logs.</para>
+ </listitem>
+ </itemizedlist></para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <section>
+ <title>Perform a Backup</title>
+
+ <para>In following example we create a BackupConfig bean for the Full +
+ Incrementals mode, then we ask the BackupManager to start the backup
+ process.</para>
+
+ <programlisting>// Obtaining the backup service from the eXo container.
+BackupManager backup = (BackupManager)
container.getComponentInstanceOfType(BackupManager.class);
+
+// And prepare the BackupConfig instance with custom parameters.
+// full backup & incremental
+File backDir = new File("/backup/ws1"); // the destination path for result
files
+backDir.mkdirs();
+
+BackupConfig config = new BackupConfig();
+config.setRepository(repository.getName());
+config.setWorkspace("ws1");
+config.setBackupDir(backDir);
+
+// Before 1.9.3, you also need to indicate the backupjobs class FDNs
+//
config.setFullBackupType("org.exoplatform.services.jcr.ext.backup.impl.fs.FullBackupJob");
+//
config.setIncrementalBackupType("org.exoplatform.services.jcr.ext.backup.impl.fs.IncrementalBackupJob");
+
+// start backup using the service manager
+BackupChain chain = backup.startBackup(config);</programlisting>
+
+ <para>To stop the backup operation you have to use the BackupChain
+ instance.</para>
+
+ <programlisting>// stop backup
+backup.stopBackup(chain);</programlisting>
+ </section>
+
+ <section>
+ <title>Perform a Restore</title>
+
+ <para>Restoration involves the reloading the backup file into a
+ BackupChainLog and applying appropriate workspace initialization. The
+ following snippet shows the typical sequence for restoring a workspace
+ :</para>
+
+ <programlisting>// find BackupChain using the repository and workspace names
(return null if not found)
+BackupChain chain = backup.findBackup("db1", "ws1");
+
+// Get the RepositoryEntry and WorkspaceEntry
+ManageableRepository repo = repositoryService.getRepository(repository);
+RepositoryEntry repoconf = repo.getConfiguration();
+List<WorkspaceEntry> entries = repoconf.getWorkspaceEntries();
+WorkspaceEntry = getNewEntry(entries, workspace); // create a copy entry from an existing
one
+
+// restore backup log using ready RepositoryEntry and WorkspaceEntry
+File backLog = new File(chain.getLogFilePath());
+BackupChainLog bchLog = new BackupChainLog(backLog);
+
+// initialize the workspace
+repository.configWorkspace(workspaceEntry);
+
+// run restoration
+backup.restore(bchLog, repositoryEntry, workspaceEntry);</programlisting>
+
+ <section>
+ <title>Restoring into an existing workspace</title>
+
+ <note>
+ <para>These instructions only applies to regular workspace. Special
+ instructions are provided for System workspace below.</para>
+ </note>
+
+ <para>To restore a backup over an existing workspace, you are required
+ to clear its data. Your backup process should follow these steps :
+ <itemizedlist>
+ <listitem>
+ <para>remove workspace<programlisting>ManageableRepository repo
= repositoryService.getRepository(repository);
+repo.removeWorkspace(workspace);</programlisting></para>
+ </listitem>
+
+ <listitem>
+ <para>clean database, value storage, index</para>
+ </listitem>
+
+ <listitem>
+ <para>restore (see snippet above)</para>
+ </listitem>
+ </itemizedlist></para>
+ </section>
+
+ <section>
+ <title>System workspace</title>
+
+ <note>
+ <para>The BackupWorkspaceInitializer is available in JCR 1.9 and
+ later.</para>
+ </note>
+
+ <para>Restoring the JCR System workspace requires to shutdown the
+ system and use of a special initializer.</para>
+
+ <para>Follow these steps (this will also work for normal workspaces) :
+ <itemizedlist>
+ <listitem>
+ <para>Stop repository (or portal)</para>
+ </listitem>
+
+ <listitem>
+ <para>clean database, value storage, index;</para>
+ </listitem>
+
+ <listitem>
+ <para>In configuration the workspace set
+ BackupWorkspaceInitializer to reference your backup.</para>
+
+ <para>For example :<programlisting><workspaces>
+ <workspace name="production" ... >
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ ...
+ </container>
+ <initializer
class="org.exoplatform.services.jcr.impl.core.BackupWorkspaceInitializer">
+ <properties>
+ <property name="restore-path"
value="D:\java\exo-working\backup\repository_production-20090527_030434"/>
+ </properties>
+ </initializer>
+ ...
+</workspace></programlisting></para>
+ </listitem>
+
+ <listitem>
+ <para>Start repository (or portal).</para>
+ </listitem>
+ </itemizedlist></para>
+ </section>
+ </section>
+ </section>
+
+ <section>
+ <title>Scheduling (experimental)</title>
+
+ <para>The Backup service has an additional feature that can be useful for
+ a production level backup implementation. When you need to organize a
+ backup of a repository it's necessary to have a tool which will be able to
+ create and manage a cycle of Full and Incremental backups in periodic
+ manner.</para>
+
+ <para>The service has internal BackupScheduler which can run a
+ configurable cycle of BackupChains as if they have been executed by a user
+ during some period of time. I.e. BackupScheduler is a user-like daemon
+ which asks the BackupManager to start or stop backup operations.</para>
+
+ <para>For that purpose BackupScheduler has the method</para>
+
+ <para>BackupScheduler.schedule(backupConfig, startDate, stopDate,
+ chainPeriod, incrementalPeriod)</para>
+
+ <para>where</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>backupConfig - a ready configuration which will be given to the
+ BackupManager.startBackup() method</para>
+ </listitem>
+
+ <listitem>
+ <para>startDate - a date and time of the backup start</para>
+ </listitem>
+
+ <listitem>
+ <para>stopDate - a date and time of the backup stop</para>
+ </listitem>
+
+ <listitem>
+ <para>chainPeriod - a period after which a current BackupChain will be
+ stopped and a new one will be started, in seconds</para>
+ </listitem>
+
+ <listitem>
+ <para>incrementalPeriod - if it is greater than 0 it will be used to
+ override the same value in backupConfig.</para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting>// geting the scheduler from the BackupManager
+ BackupScheduler scheduler = backup.getScheduler();
+
+// schedule backup using a ready configuration (Full + Incrementals) to run from
startTime
+// to stopTime. Full backuop will be performed every 24 hours (BackupChain lifecycle),
+// incremental will rotate result files every 3 hours.
+ scheduler.schedule(config, startTime, stopTime, 3600 * 24, 3600 * 3);
+
+// it's possible to run the scheduler for an uncertain period of time (i.e. without
stop time).
+// schedule backup to run from startTime till it will be stopped manually
+// also there, the incremental will rotate result files as it configured in BackupConfig
+ scheduler.schedule(config, startTime, null, 3600 * 24, 0);
+
+// to unschedule backup simply call the scheduler with the configuration describing the
+// already planned backup cycle.
+// the scheduler will search in internal tasks list for task with repository and
+// workspace name from the configuration and will stop that task.
+ scheduler.unschedule(config);</programlisting>
+
+ <para>When the BackupScheduler starts the scheduling, it uses the internal
+ Timer with startDate for the first (or just once) execution. If
+ chainPeriod is greater than 0 then the task is repeated with this value
+ used as a period starting from startDate. Otherwise the task will be
+ executed once at startDate time. If the scheduler has stopDate it will
+ stop the task ( the chain cycle) after stopDate. And the last parameter
+ incrementalPeriod will be used instead of the same from BackupConfig if
+ its values are greater than 0.</para>
+
+ <para>Starting each task (BackupScheduler.schedule(...)), the scheduler
+ creates a task file in the service working directory (see <emphasis
+ role="bold">Configuration</emphasis>, backup-dir) which describes
the task
+ backup configuration and periodic values. These files will be used at the
+ backup service start (JVM start) to reinitialize BackupScheduler for
+ continuous task scheduling. Only tasks that don't have a stopDate or a
+ stopDate not expired will be reinitialized.</para>
+
+ <para>There is one notice about BackupScheduler task reinitialization in
+ the current implementation. It comes from the BackupScheduler nature and
+ its implemented behaviour. As the scheduler is just a virtual user which
+ asks the BackupManager to start or stop backup operations, it isn't able
+ to reinitialize each existing BackupChain before the service (JVM) is
+ stopped. But it's possible to start a new operation with the same
+ configuration via BackupManager (that was configured before and stored in
+ a task file).</para>
+
+ <para>This is a main detail of the BackupScheduler which should be taken
+ into suggestion of a backup operation design now. In case of
+ reinitialization the task will have new time values for the backup
+ operation cycle as the chainPeriod and incrementalPeriod will be applied
+ again. That behaviour may be changed in the future.</para>
+ </section>
+</chapter>
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/concepts/jcr-registry-service.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/concepts/jcr-registry-service.xml 2010-08-23
07:45:14 UTC (rev 2967)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/concepts/jcr-registry-service.xml 2010-08-23
10:23:16 UTC (rev 2968)
@@ -1,141 +1,141 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="JCR.RegistryService">
- <?dbhtml filename="ch-jcr-registry-service.html"?>
-
- <title>Registry Service</title>
-
- <section id="Concept">
- <title>Concept</title>
-
- <para>The Registry Service is one of the key parts of the infrastructure
- built around eXo JCR. Each JCR based service, applications etc may have
- its own configuration and settings data and other data that have to be
- stored persistently and used by the approptiate service or application
- (let's call it <emphasis
role="bold">Consumer</emphasis>).</para>
-
- <para>The service acts as a centralized collector (Registry) for such
- data. Naturally, a registry storage is JCR based i.e. stored in some JCR
- workspace (one per Repository) as an Item tree under <emphasis
- role="bold">/exo:registry</emphasis> node.</para>
-
- <para>Despite the fact that the structure of the tree is well defined (see
- the scheme below), it is not recommended for other services to manipulate
- data using JCR API directly for better flexibility. So the Registry
- Service acts as a mediator between a Consumer and its settings.</para>
-
- <para>The proposed structure of the Registry Service storage.It is divided
- into 3 logical groups: services, applications and users:</para>
-
- <programlisting> exo:registry/ <-- registry "root"
(exo:registry)
- exo:services/ <-- service data storage (exo:registryGroup)
- service1/
- Consumer data (exo:registryEntry)
- ...
- exo:applications/ <-- application data storage (exo:registryGroup)
- app1/
- Consumer data (exo:registryEntry)
- ...
- exo:users/ <-- user personal data storage (exo:registryGroup)
- user1/
- Consumer data (exo:registryEntry)
- ...</programlisting>
-
- <para>Each upper level eXo Service may store its configuration in Exo
- Registry. First time start from xml-config (in jar etc). Each next will be
- from Registry. In configuration file you can add force-xml-configuration
- parameter to component to ignore reading parameters initialization from
- RegistryService and to use file instead:</para>
-
- <programlisting><value-param>
- <name>force-xml-configuration</name>
- <value>true</value>
-</value-param></programlisting>
- </section>
-
- <section>
- <title>The API</title>
-
- <para>The main functionality of the Registry Service is pretty simple and
- straightforward, it is described in the Registry abstract class as
- following:</para>
-
- <programlisting>public abstract class Registry {
-
- /**
- * Returns the Registry object which wraps the Node of the "exo:registry"
type
- */
- public abstract RegistryNode getRegistry(SessionProvider sessionProvider)
- throws RepositoryConfigurationException, RepositoryException;
-
- /**
- * Returns the existing RegistryEntry which wraps the Node of the
"exo:registryEntry" type
- */
- public abstract RegistryEntry getEntry(SessionProvider sessionProvider, String
groupName,
- String entryName) throws RepositoryException;
-
- /**
- * Creates a new RegistryEntry
- */
- public abstract void createEntry(SessionProvider sessionProvider,
- String groupName, RegistryEntry entry) throws RepositoryException;
-
- /**
- * Replaces a RegistryEntry
- */
- public abstract void recreateEntry(SessionProvider sessionProvider,
- String groupName, RegistryEntry entry) throws RepositoryException;
-
- /**
- * Removes a RegistryEntry
- */
- public abstract void removeEntry(SessionProvider sessionProvider,
- String groupName, String entryName) throws
RepositoryException;</programlisting>
-
- <para>As you can see it mainly looks like a simple CRUD interface for the
- RegistryEntry object which wraps registry data for some Consumer as a
- Registry Entry. The Registry Service itself knows nothing about the
- wrapping data, it is Consumer's responsibility to manage and use its data
- in its own way.</para>
-
- <para>To create an Entity Consumer you should have an idea how to
- serialize the data to some XML structure and then create a RegistryEntry
- from these data at once or populate them in a RegistryEntry object (using
- RegistryEntry(String entryName) constructor and then obtain and fill a DOM
- document).</para>
-
- <para>Example of RegistryService using:</para>
-
- <programlisting> RegistryService regService = (RegistryService) container
- .getComponentInstanceOfType(RegistryService.class);
-
- RegistryEntry registryEntry = regService.getEntry(sessionProvider,
- RegistryService.EXO_SERVICES, "my-service");
-
- Document doc = registryEntry.getDocument();
-
- String mySetting =
getElementsByTagName("tagname").item(index).getTextContent();
- .....</programlisting>
- </section>
-
- <section>
- <title>Configuration</title>
-
- <para>RegistryService has only one optional properties parameter <emphasis
- role="bold">locations</emphasis>. It is used to mention where
exo:registry
- is placed for each repository. The name of each property is interpreted as
- a repository name and its value as a workspace name (a system workspace by
- default).</para>
-
- <programlisting><component>
-
<type>org.exoplatform.services.jcr.ext.registry.RegistryService</type>
- <init-params>
- <properties-param>
- <name>locations</name>
- <property name="db1" value="ws2"/>
- </properties-param>
- </init-params>
-</component></programlisting>
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.RegistryService">
+ <?dbhtml filename="ch-jcr-registry-service.html"?>
+
+ <title>Registry Service</title>
+
+ <section>
+ <title>Concept</title>
+
+ <para>The Registry Service is one of the key parts of the infrastructure
+ built around eXo JCR. Each JCR based service, applications etc may have
+ its own configuration and settings data and other data that have to be
+ stored persistently and used by the approptiate service or application
+ (let's call it <emphasis
role="bold">Consumer</emphasis>).</para>
+
+ <para>The service acts as a centralized collector (Registry) for such
+ data. Naturally, a registry storage is JCR based i.e. stored in some JCR
+ workspace (one per Repository) as an Item tree under <emphasis
+ role="bold">/exo:registry</emphasis> node.</para>
+
+ <para>Despite the fact that the structure of the tree is well defined (see
+ the scheme below), it is not recommended for other services to manipulate
+ data using JCR API directly for better flexibility. So the Registry
+ Service acts as a mediator between a Consumer and its settings.</para>
+
+ <para>The proposed structure of the Registry Service storage.It is divided
+ into 3 logical groups: services, applications and users:</para>
+
+ <programlisting> exo:registry/ <-- registry "root"
(exo:registry)
+ exo:services/ <-- service data storage (exo:registryGroup)
+ service1/
+ Consumer data (exo:registryEntry)
+ ...
+ exo:applications/ <-- application data storage (exo:registryGroup)
+ app1/
+ Consumer data (exo:registryEntry)
+ ...
+ exo:users/ <-- user personal data storage (exo:registryGroup)
+ user1/
+ Consumer data (exo:registryEntry)
+ ...</programlisting>
+
+ <para>Each upper level eXo Service may store its configuration in Exo
+ Registry. First time start from xml-config (in jar etc). Each next will be
+ from Registry. In configuration file you can add force-xml-configuration
+ parameter to component to ignore reading parameters initialization from
+ RegistryService and to use file instead:</para>
+
+ <programlisting><value-param>
+ <name>force-xml-configuration</name>
+ <value>true</value>
+</value-param></programlisting>
+ </section>
+
+ <section>
+ <title>The API</title>
+
+ <para>The main functionality of the Registry Service is pretty simple and
+ straightforward, it is described in the Registry abstract class as
+ following:</para>
+
+ <programlisting>public abstract class Registry {
+
+ /**
+ * Returns the Registry object which wraps the Node of the "exo:registry"
type
+ */
+ public abstract RegistryNode getRegistry(SessionProvider sessionProvider)
+ throws RepositoryConfigurationException, RepositoryException;
+
+ /**
+ * Returns the existing RegistryEntry which wraps the Node of the
"exo:registryEntry" type
+ */
+ public abstract RegistryEntry getEntry(SessionProvider sessionProvider, String
groupName,
+ String entryName) throws RepositoryException;
+
+ /**
+ * Creates a new RegistryEntry
+ */
+ public abstract void createEntry(SessionProvider sessionProvider,
+ String groupName, RegistryEntry entry) throws RepositoryException;
+
+ /**
+ * Replaces a RegistryEntry
+ */
+ public abstract void recreateEntry(SessionProvider sessionProvider,
+ String groupName, RegistryEntry entry) throws RepositoryException;
+
+ /**
+ * Removes a RegistryEntry
+ */
+ public abstract void removeEntry(SessionProvider sessionProvider,
+ String groupName, String entryName) throws
RepositoryException;</programlisting>
+
+ <para>As you can see it mainly looks like a simple CRUD interface for the
+ RegistryEntry object which wraps registry data for some Consumer as a
+ Registry Entry. The Registry Service itself knows nothing about the
+ wrapping data, it is Consumer's responsibility to manage and use its data
+ in its own way.</para>
+
+ <para>To create an Entity Consumer you should have an idea how to
+ serialize the data to some XML structure and then create a RegistryEntry
+ from these data at once or populate them in a RegistryEntry object (using
+ RegistryEntry(String entryName) constructor and then obtain and fill a DOM
+ document).</para>
+
+ <para>Example of RegistryService using:</para>
+
+ <programlisting> RegistryService regService = (RegistryService) container
+ .getComponentInstanceOfType(RegistryService.class);
+
+ RegistryEntry registryEntry = regService.getEntry(sessionProvider,
+ RegistryService.EXO_SERVICES, "my-service");
+
+ Document doc = registryEntry.getDocument();
+
+ String mySetting =
getElementsByTagName("tagname").item(index).getTextContent();
+ .....</programlisting>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>RegistryService has only one optional properties parameter <emphasis
+ role="bold">locations</emphasis>. It is used to mention where
exo:registry
+ is placed for each repository. The name of each property is interpreted as
+ a repository name and its value as a workspace name (a system workspace by
+ default).</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.services.jcr.ext.registry.RegistryService</type>
+ <init-params>
+ <properties-param>
+ <name>locations</name>
+ <property name="db1" value="ws2"/>
+ </properties-param>
+ </init-params>
+</component></programlisting>
+ </section>
+</chapter>
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/data-container.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/data-container.xml 2010-08-23
07:45:14 UTC (rev 2967)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/data-container.xml 2010-08-23
10:23:16 UTC (rev 2968)
@@ -2,7 +2,7 @@
<chapter id="JCR.WorkspaceDataContainer">
<?dbhtml filename="ch-data-container.html"?>
<title>JCR Workspace Data Container (architecture contract)</title>
- <section id="Goals">
+ <section>
<title>Goals</title>
<itemizedlist>
<listitem>
@@ -16,9 +16,9 @@
</listitem>
</itemizedlist>
</section>
- <section id="Concepts">
+ <section>
<title>Concepts</title>
- <section id="Containerandconnection">
+ <section>
<title>Container and connection</title>
<para>Workspace Data Container (container) serves Repository Workspace
persistent storage.
WorkspacePersistentDataManager (data manager) uses container to perform CRUD
operation on the persistent
@@ -76,7 +76,7 @@
change parameters. Configuration consists of implementation class and set of
properties and Value Storages
configuration.</para>
</section>
- <section id="Valuestorages">
+ <section>
<title>Value storages</title>
<para>Container provides optional special mechanism for Value storing.
It's possible to configure external
Value Storages via container configuration (available only via
configuration).
@@ -90,7 +90,7 @@
of Value channels (ValueIOChannel). Channel provides all CRUD operation for
Value Storage respecting the
transaction manner of work (how it can be possible due to implementation
specifics of the storages).</para>
</section>
- <section id="Lifecycle">
+ <section>
<title>Lifecycle</title>
<para>Container used by data manager for read and write operations.
Read operations (getters) uses connection once and close it on the finally.
@@ -99,7 +99,7 @@
guaranties transaction support for write operations.
Commit or rollback should free/clean all resources consumed by the container
(connection).</para>
</section>
- <section id="Valuestoragelifecycle">
+ <section>
<title>Value storage lifecycle</title>
<para>Value storage used from the container inside. Reads are related to a
container reads. Writes are commit
related.
@@ -107,11 +107,11 @@
operations.</para>
</section>
</section>
- <section id="Requirements">
+ <section>
<title>Requirements</title>
<para>Connection create and reuse should be a thread safe operation.
Connection provides CRUD operations support on the storage.</para>
- <section id="Readoperations">
+ <section>
<title>Read operations</title>
<itemizedlist>
<listitem>
@@ -158,7 +158,7 @@
<programlisting>List<PropertyData> getReferencesData(String
nodeIdentifier) throws
RepositoryException,IllegalStateException,UnsupportedOperationException;
</programlisting>
</section>
- <section id="Writeoperations">
+ <section>
<title>Write operations</title>
<itemizedlist>
<listitem>
@@ -227,7 +227,7 @@
UnsupportedOperationException if the method is not supported (e.g. JCR Level 1
implementation etc).
RepositoryException if some error occurs during preparation, validation or
persistence.</para>
</section>
- <section id="Stateoperations">
+ <section>
<title>State operations</title>
<itemizedlist>
<listitem>
@@ -237,7 +237,7 @@
<programlisting>boolean isOpened();
</programlisting>
</section>
- <section id="Validationofwriteoperations">
+ <section>
<title>Validation of write operations</title>
<para>Container have to care about storage consistency (JCR constraints) on
write operations:
(InvalidItemStateException should be thrown according the spec)
@@ -285,7 +285,7 @@
</listitem>
</itemizedlist>
</section>
- <section id="Consistencyofsave">
+ <section>
<title>Consistency of save</title>
<para>The container (connection) should implement consistency of Commit
(Rollback) in
<emphasis role="bold">transaction manner</emphasis>.
@@ -298,9 +298,9 @@
</para>
</section>
</section>
- <section id="ValuestoragesAPI">
+ <section>
<title>Value storages API</title>
- <section id="Storagesprovider">
+ <section>
<title>Storages provider:</title>
<para>Container implementation obtains Values Storages option via
ValueStoragePluginProvider component. Provider acts as a factory of Value channels
(ValueIOChannel) and has two methods for this purpose:</para>
<itemizedlist>
@@ -319,7 +319,7 @@
</programlisting>
<para>There is also method for consistency check, but this method doesn't
used anywhere and storage implementations has it empty.</para>
</section>
- <section id="Valuestorageplugin">
+ <section>
<title>Value storage plugin</title>
<para>Provider implementation should use ValueStoragePlugin abstract class as a
base for all storage implementations.
Plugin provides support for provider implementation methods. Plugin's methods
should be implemented:</para>
@@ -345,7 +345,7 @@
<programlisting>public abstract boolean isSame(String valueDataDescriptor);
</programlisting>
</section>
- <section id="ValueIOchannel">
+ <section>
<title>Value I/O channel</title>
<para>Channel should implement ValueIOChannel interface. CRUD operation for
Value Storage:</para>
<itemizedlist>
@@ -370,7 +370,7 @@
<programlisting>void delete(String propertyId) throws IOException;
</programlisting>
</section>
- <section id="Transactionsupportviachannel">
+ <section>
<title>Transaction support via channel</title>
<para>Modification operations should be applied only on commit. Rollback is
required for data created cleanup.</para>
<itemizedlist>
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml 2010-08-23
07:45:14 UTC (rev 2967)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml 2010-08-23
10:23:16 UTC (rev 2968)
@@ -1,414 +1,405 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="JCR.QueryUsecases">
- <?dbhtml filename="ch-jcr-query-usecases.html"?>
-
- <title>JCR Query Usecases</title>
-
- <section>
- <title>Intro</title>
-
- <para>JCR supports two query languages - JCR and XPath. A query, whether
- XPath or SQL, specifies a subset of nodes within a workspace, called the
- result set. The result set constitutes all the nodes in the workspace that
- meet the constraints stated in the query.</para>
- </section>
-
- <section>
- <title>Query Lifecycle</title>
-
- <section>
- <title>Query Creation and Execution</title>
-
- <para><emphasis
role="bold">SQL</emphasis></para>
-
- <programlisting>// get QueryManager
-QueryManager queryManager = workspace.getQueryManager();
-// make SQL query
-Query query = queryManager.createQuery("SELECT * FROM nt:base ", Query.SQL);
-// execute query
-QueryResult result = query.execute();</programlisting>
-
- <para><emphasis
role="bold">XPath</emphasis></para>
-
- <programlisting>// get QueryManager
-QueryManager queryManager = workspace.getQueryManager();
-// make XPath query
-Query query = queryManager.createQuery("//element(*,nt:base)", Query.XPATH);
-// execute query
-QueryResult result = query.execute();</programlisting>
- </section>
-
- <section>
- <title>Query Result Processing</title>
-
- <programlisting>// fetch query result
-QueryResult result = query.execute();</programlisting>
-
- <para>Now we can get result in an iterator of nodes:</para>
-
- <programlisting>NodeIterator it = result.getNodes();</programlisting>
-
- <para>or we get the result in a table:</para>
-
- <programlisting>// get column names
-String[] columnNames = result.getColumnNames();
-// get column rows
-RowIterator rowIterator = result.getRows();
-while(rowIterator.hasNext()){
- // get next row
- Row row = rowIterator.nextRow();
- // get all values of row
- Value[] values = row.getValues();
-}</programlisting>
- </section>
-
- <section>
- <title>Scoring</title>
-
- <para>The result returns a score for each row in the result set. The
- score contains a value that indicates a rating of how well the result
- node matches the query. A high value means a better matching than a low
- value. This score can be used for ordering the result.</para>
-
- <para>eXo JCR Scoring is a mapping of Lucene scoring. For a more
- in-depth understanding, please study <ulink
-
url="http://lucene.apache.org/java/2_4_1/scoring.html">Lucene
- documentation</ulink>.</para>
-
- <para>jcr:score counted in next way - (lucene score)*1000f.</para>
-
- <para>Score may be increased for specified nodes, see <link
- linkend="JCR.IndexBoostRule">Index Boost
Value</link></para>
-
- <para>Also, see an example <link
linkend="JCR.OrderByScore">Order by
- Score</link></para>
- </section>
- </section>
-
- <section>
- <title>Query result settings</title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="JCR.SetOffsetandSetLimit">Set Offset
And
- Limit</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Type Constraints</title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="JCR.FindAllNodes">Find All
Nodes</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.FindNodesByPrimaryType">Find Nodes
by Primary
- Type</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.FindNodesByMixinType">Find Nodes
by Mixin
- Type</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Property Constraints</title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="JCR.PropertyComparison">Property
- Comparison</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.LIKEConstraint">LIKE
Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.EscapinginLIKEStatements">Escaping
in LIKE
- Statements</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.NOTConstraint">NOT
Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.ANDConstraint">AND
Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.ORConstraint">OR
Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link
linkend="JCR.PropertyExistenceConstraint">Property
- Existence Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.FindNodesCaseInsensitive">Upper
and Lower
- Case Constraints</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.DatePropertyComparison">Date
Property
- Comparison</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.NodeNameConstraint">Node Name
- Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link
linkend="JCR.MultivaluePropertyComparison">Multivalue
- Property Comparison</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Path Constraint</title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="JCR.ExactPathConstraint">Exact Path
- Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.ChildNodeConstraint">Child Node
- Constraint</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.FindAllDescendantNodes">Find All
Descendant
- Nodes</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Ordering specifing</title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="JCR.OrderByProperty">Order by
- Property</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.OrderByDescendant">Order by
Descendant Node
- Property</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.OrderByScore">Order by
Score</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.OrderByPathOrName">Order by Path
or
- Name</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title><link linkend="JCR.FulltextSearchAndSettings">Fulltext
- Search</link></title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="JCR.FulltextSearchByProperty">Fulltext
Search by
- Property</link></para>
- </listitem>
-
- <listitem>
- <para><link
linkend="JCR.FulltextSearchByAllProperties">Fulltext
- Search by All Properties</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.AggregationRule">Find nt:file
document by
- content of child jcr:content node</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.IgnoreAccentSymbols">How to set
new Analyzer.
- Accent symblos ignoring</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Indexing rules and additional features</title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="JCR.AggregationRule">Aggregation
- rule</link></para>
- </listitem>
-
- <listitem>
- <para><link
linkend="JCR.HiglightResultofFulltextSearch">Search Result
- Highlighting</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.IndexBoostRule">Index Boost
- Value</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.NodeScopeIndex">Exclusion from the
Node Scope
- Index</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.RegexpIndexingRule">Regular
expressions as
- property name in indexing rule</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.SynonimProvider">Synonim
- Provider</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.SpellChecker">Spell
Checking</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="JCR.FindSimilarNodes">Find Similar
- Nodes</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Query Examples</title>
-
- <xi:include href="offset-and-limit.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="find-all-nodes.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="find-nodes-by-primary-type.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="find-nodes-by-mixin-type.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="property-comparison.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="like-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="escaping-like-statements.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="not-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="and-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="or-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="property-existance-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="find-nodes-case-insensitive.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="date-property-comparison.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="node-name-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="multivalue-property-comparison.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="exact-path-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="child-node-constraint.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="find-all-descendant-nodes.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="order-by-property.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="order-by-descendant.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="order-by-score.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="order-by-path-or-name.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="fulltext-search-by-property.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="fulltext-search-by-all-properties.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="ignore-accent-symbols.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="aggregation-rule.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="index-boost-value.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="node-scope-index.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="regexp-indexing-rule.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="higlight.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="synonim-provider.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="regexp-indexing-rule.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="spell-checker.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="find-similar-nodes.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
- </section>
-
- <section>
- <title>Tips and tricks</title>
-
- <xi:include href="tip-nodename-with-number.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <!--itemizedlist>
- <listitem>
- <para><link linkend="JCR.TipNodeNameWithNumber">Xpath and
numbers in
- node names</link></para>
- </listitem>
- </itemizedlist-->
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.QueryUsecases">
+ <?dbhtml filename="ch-jcr-query-usecases.html"?>
+
+ <title>JCR Query Usecases</title>
+
+ <section>
+ <title>Intro</title>
+
+ <para>JCR supports two query languages - JCR and XPath. A query, whether
+ XPath or SQL, specifies a subset of nodes within a workspace, called the
+ result set. The result set constitutes all the nodes in the workspace that
+ meet the constraints stated in the query.</para>
+ </section>
+
+ <section>
+ <title>Query Lifecycle</title>
+
+ <section>
+ <title>Query Creation and Execution</title>
+
+ <para><emphasis
role="bold">SQL</emphasis></para>
+
+ <programlisting>// get QueryManager
+QueryManager queryManager = workspace.getQueryManager();
+// make SQL query
+Query query = queryManager.createQuery("SELECT * FROM nt:base ", Query.SQL);
+// execute query
+QueryResult result = query.execute();</programlisting>
+
+ <para><emphasis
role="bold">XPath</emphasis></para>
+
+ <programlisting>// get QueryManager
+QueryManager queryManager = workspace.getQueryManager();
+// make XPath query
+Query query = queryManager.createQuery("//element(*,nt:base)", Query.XPATH);
+// execute query
+QueryResult result = query.execute();</programlisting>
+ </section>
+
+ <section>
+ <title>Query Result Processing</title>
+
+ <programlisting>// fetch query result
+QueryResult result = query.execute();</programlisting>
+
+ <para>Now we can get result in an iterator of nodes:</para>
+
+ <programlisting>NodeIterator it = result.getNodes();</programlisting>
+
+ <para>or we get the result in a table:</para>
+
+ <programlisting>// get column names
+String[] columnNames = result.getColumnNames();
+// get column rows
+RowIterator rowIterator = result.getRows();
+while(rowIterator.hasNext()){
+ // get next row
+ Row row = rowIterator.nextRow();
+ // get all values of row
+ Value[] values = row.getValues();
+}</programlisting>
+ </section>
+
+ <section>
+ <title>Scoring</title>
+
+ <para>The result returns a score for each row in the result set. The
+ score contains a value that indicates a rating of how well the result
+ node matches the query. A high value means a better matching than a low
+ value. This score can be used for ordering the result.</para>
+
+ <para>eXo JCR Scoring is a mapping of Lucene scoring. For a more
+ in-depth understanding, please study <ulink
+
url="http://lucene.apache.org/java/2_4_1/scoring.html">Lucene
+ documentation</ulink>.</para>
+
+ <para>jcr:score counted in next way - (lucene score)*1000f.</para>
+
+ <para>Score may be increased for specified nodes, see <link
+ linkend="JCR.IndexBoostRule">Index Boost
Value</link></para>
+
+ <para>Also, see an example <link
linkend="JCR.OrderByScore">Order by
+ Score</link></para>
+ </section>
+ </section>
+
+ <section>
+ <title>Query result settings</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.SetOffsetandSetLimit">Set Offset
And
+ Limit</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Type Constraints</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.FindAllNodes">Find All
Nodes</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.FindNodesByPrimaryType">Find Nodes
by Primary
+ Type</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.FindNodesByMixinType">Find Nodes
by Mixin
+ Type</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Property Constraints</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.PropertyComparison">Property
+ Comparison</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.LIKEConstraint">LIKE
Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.EscapinginLIKEStatements">Escaping
in LIKE
+ Statements</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.NOTConstraint">NOT
Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.ANDConstraint">AND
Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.ORConstraint">OR
Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link
linkend="JCR.PropertyExistenceConstraint">Property
+ Existence Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.FindNodesCaseInsensitive">Upper
and Lower
+ Case Constraints</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.DatePropertyComparison">Date
Property
+ Comparison</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.NodeNameConstraint">Node Name
+ Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link
linkend="JCR.MultivaluePropertyComparison">Multivalue
+ Property Comparison</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Path Constraint</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.ExactPathConstraint">Exact Path
+ Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.ChildNodeConstraint">Child Node
+ Constraint</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.FindAllDescendantNodes">Find All
Descendant
+ Nodes</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Ordering specifing</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.OrderByProperty">Order by
+ Property</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.OrderByDescendant">Order by
Descendant Node
+ Property</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.OrderByScore">Order by
Score</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.OrderByPathOrName">Order by Path
or
+ Name</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title><link linkend="JCR.FulltextSearchAndSettings">Fulltext
+ Search</link></title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.FulltextSearchByProperty">Fulltext
Search by
+ Property</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link
linkend="JCR.FulltextSearchByAllProperties">Fulltext
+ Search by All Properties</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.AggregationRule">Find nt:file
document by
+ content of child jcr:content node</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.IgnoreAccentSymbols">How to set
new Analyzer.
+ Accent symblos ignoring</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Indexing rules and additional features</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.AggregationRule">Aggregation
+ rule</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link
linkend="JCR.HiglightResultofFulltextSearch">Search Result
+ Highlighting</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.IndexBoostRule">Index Boost
+ Value</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.NodeScopeIndex">Exclusion from the
Node Scope
+ Index</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.RegexpIndexingRule">Regular
expressions as
+ property name in indexing rule</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.SynonimProvider">Synonim
+ Provider</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.SpellChecker">Spell
Checking</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.FindSimilarNodes">Find Similar
+ Nodes</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Query Examples</title>
+
+ <xi:include href="offset-and-limit.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="find-all-nodes.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="find-nodes-by-primary-type.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="find-nodes-by-mixin-type.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="property-comparison.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="like-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="escaping-like-statements.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="not-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="and-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="or-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="property-existance-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="find-nodes-case-insensitive.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="date-property-comparison.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="node-name-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="multivalue-property-comparison.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="exact-path-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="child-node-constraint.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="find-all-descendant-nodes.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="order-by-property.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="order-by-descendant.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="order-by-score.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="order-by-path-or-name.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="fulltext-search-by-property.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="fulltext-search-by-all-properties.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ignore-accent-symbols.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="aggregation-rule.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="index-boost-value.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="node-scope-index.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="regexp-indexing-rule.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="higlight.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="synonim-provider.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="spell-checker.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="find-similar-nodes.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </section>
+
+ <section>
+ <title>Tips and tricks</title>
+
+ <xi:include href="tip-nodename-with-number.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ </section>
+</chapter>
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/kernel/service-configuration-in-detail.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/kernel/service-configuration-in-detail.xml 2010-08-23
07:45:14 UTC (rev 2967)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/kernel/service-configuration-in-detail.xml 2010-08-23
10:23:16 UTC (rev 2968)
@@ -1,704 +1,704 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="Kernel.ServiceConfigurationinDetail">
- <?dbhtml filename="ch-service-configuration-in-detail.html"?>
-
- <title>Service Configuration in Detail</title>
-
- <para><emphasis role="bold">Related
documents</emphasis></para>
-
- <itemizedlist>
- <listitem>
- <para><link
linkend="Kernel.ServiceConfigurationforBeginners">Service
- Configuration for Beginners</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="Kernel.ServicesWiring">Services
- Wiring</link></para>
- </listitem>
-
- <listitem>
- <para><link
- linkend="Kernel.ContainerConfiguration.ConfigurationNamespace">Kernel
- Configuration File</link></para>
- </listitem>
- </itemizedlist>
-
- <section id="Objectives">
- <title>Objectives</title>
-
- <para>This article shows in the first chapters how to setup a sample
- service with some configurations and how to access to the configuration
- parameters. The later chapters describe all details of the configuration
- file (parameters, object-params, plugins, imports, etc.) it also shows how
- to access the configuration values. You may consider this article as a
- <emphasis role="bold">reference</emphasis>, but you can also
use this
- article as a <emphasis role="bold">tutorial</emphasis> and read
it from
- the beginning to the end.</para>
- </section>
-
- <section id="Requirements">
- <title>Requirements</title>
-
- <para>You should have read and understood <link
- linkend="Kernel.ServiceConfigurationforBeginners">Service Configuration
- for Beginners</link>. Obviously you should know java and xml. We are
- working with examples that are created for teaching reasons only and you
- will see extracts from the eXo Products default installation. When reading
- do not forget that the terms service and component are interchangeable in
- eXo Products.</para>
- </section>
-
- <section id="SampleService">
- <title>Sample Service</title>
-
- <section id="JavaClass">
- <title>Java Class</title>
-
- <para>Imagine you are working for a publishing company called "La
- Verdad" that is going to use eXo platform. Your boss asks you be able to
- calculate the number of sentences of an article.</para>
-
- <para>You remember in eXo product everything is a <emphasis
- role="bold">service</emphasis> so you decide to create a simple
class.
- In future you want to be able to plug different implementations of your
- service, so that you should define an <emphasis
- role="bold">interface</emphasis> that defines your
service.</para>
-
- <programlisting>package com.laverdad.services;
-public interface ArticleStatsService {
- public abstract int calcSentences(String article);
-}</programlisting>
-
- <para>A very simple implementation:</para>
-
- <programlisting>public class ArticleStatsServiceImpl implements
ArticleStatsService {
- public int calcSentences(String article) {
- throw new RuntimeException("Not implemented");
- }
-}</programlisting>
-
- <para>That's it! You see there are no special prerequisites for a
- service.</para>
-
- <para>You should already have prepared your working environment, where
- you have a base folder (let's call it our service base folder). If you
- wish to try out this example create this class in the
- com/laverdad/services/ArticleStatsService subfolder.</para>
- </section>
-
- <section id="Firstconfigurationfile">
- <title>First configuration file</title>
-
- <para>When creating a service you also should declare its existence to
- the <emphasis role="bold">Container</emphasis>, therefore you
create a
- first simple configuration file. Copy the following code to a file that
- is called "configuration.xml" and place this file in a /conf
- subdirectory of your service base folder. As you already know the
- container looks for a "/conf/configuration.xml" file in each
- jar-file.</para>
-
- <programlisting><?xml version="1.0"
encoding="UTF8"?>
-<configuration
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd
http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
-
xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
- <component>
- <key>com.laverdad.services.ArticleStatsService</key>
-
<type>com.laverdad.services.ArticleStatsServiceImpl</type>
- </component>
-</configuration></programlisting>
-
- <note>
- <para>You are correctly using the namespace of the configuration
- schema (
<
uri>http://www.exoplaform.org/xml/ns/kernel_1_1.xsd</uri>).
- Most of the configuration schema is explained in this
- articles,therefore you do not need to open and understand the schema.
- For backward compatibility it is not necessary to declare the
- schema.</para>
-
- <para>When eXo kernel reads a configuration it loads the file from the
- kernel jar using the classloader and does not use an internet
- connection to resolve the file.</para>
- </note>
- </section>
-
- <section id="InitParameters">
- <title>Init Parameters</title>
-
- <para>You see your service has a configuration file, but you wonder how
- the file could possibly access to its configuration. Imagine you are
- asked to implement two different calculation methods: fast and
- exact.</para>
-
- <para>You create one init parameter containing the calculation methods.
- For the exact method you wish to configure more details for the service.
- Let's enhance the word service configuration file:</para>
-
- <programlisting> <component>
- <key>com.laverdad.services.ArticleStatsService</key>
-
<type>com.laverdad.services.ArticleStatsServiceImpl</type>
- <init-params>
- <value-param>
- <name>calc-method</name>
- <description>calculation method: fast,
exact</description>
- <value>fast</value>
- </value-param>
- <properties-param>
- <name>details-for-exact-method</name>
- <description>details for exact phrase
counting</description>
- <property name="language" value="English" />
- <property name="variant" value="us" />
- </properties-param>
- </init-params>
- </component></programlisting>
-
- <note>
- <para>When configuring your service, you are <emphasis
- role="bold">totally free</emphasis>. You can provide as many
<emphasis
- role="bold">value-param</emphasis>, <emphasis
- role="bold">property-param</emphasis>, and <emphasis
- role="bold">properties</emphasis> you wish and you can give
them any
- names or values. You only must respect the xml structure.</para>
- </note>
-
- <para>Now let's see how our service can read this configuration. The
- implementation of the calcSentences() method serves just as a simple
- example. It's up to your imagination to implement the exact
- method.</para>
-
- <programlisting>public class ArticleStatsServiceImpl implements
ArticleStatsService {
-
- private String calcMethod = "fast";
- private String variant = "French";
- private String language = "France";
-
- public ArticleStatsServiceImpl(InitParams initParams) {
- super();
- calcMethod = initParams.getValueParam("calc-method").getValue();
- PropertiesParam detailsForExactMethod =
initParams.getPropertiesParam("details-for-exact-method");
- if ( detailsForExactMethod != null) {
- language = detailsForExactMethod.getProperty("language");
- variant = detailsForExactMethod.getProperty("variant");
- }
- }
-
- public int calcSentences(String article) {
- if (calcMethod == "fast") {
- // just count the number of periods "."
- int res = 0;
- int period = article.indexOf('.');
- while (period != -1) {
- res++;
- article = article.substring(period+1);
- period = article.indexOf('.');
- }
- return res;
- }
- throw new RuntimeException("Not implemented");
- }
-}</programlisting>
-
- <para>You see you just have to declare a parameter of
- org.exoplatform.container.xml.InitParams in your constructor. The
- container provides an InitParams object that correspond to the xml tree
- of init-param.</para>
- </section>
-
- <section id="ServiceAccess">
- <title>Service Access</title>
-
- <para>As you want to follow the principle of <emphasis
- role="bold">Inversion of Control</emphasis> you <emphasis
- role="bold">must not</emphasis> access the service directly. You
need a
- <emphasis role="bold">Container</emphasis> to access the
service.</para>
-
- <para>With this command you get your current container:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">ExoContainer myContainer =
- ExoContainerContext.getCurrentContainer();</emphasis></para>
- </listitem>
- </itemizedlist>
-
- <para>This might be a PortalContainer or a StandaloneContainer,
- dependant on the <link
-
linkend="Kernel.ServiceConfigurationinDetail.ExecutionModes">execution
- mode</link> in which you are running your application.</para>
-
- <para>Whenever you need one of the services that you have configured use
- the method:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis
-
role="bold">myContainer.getComponentInstance(class)</emphasis></para>
- </listitem>
- </itemizedlist>
-
- <para>In our case:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">ArticleStatsService
statsService =
- (ArticleStatsService)
-
myContainer.getComponentInstance(ArticleStatsService.class);</emphasis></para>
- </listitem>
- </itemizedlist>
-
- <para>Recapitulation:</para>
-
- <programlisting>package com.laverdad.common;
-
-import org.exoplatform.container.ExoContainer;
-import org.exoplatform.container.ExoContainerContext;
-import com.laverdad.services.*;
-
-public class Statistics {
-
- public int makeStatistics(String articleText) {
- ExoContainer myContainer = ExoContainerContext.getCurrentContainer();
- ArticleStatsService statsService = (ArticleStatsService)
- myContainer.getComponentInstance(ArticleStatsService.class);
- int numberOfSentences = statsService.calcSentences(articleText);
- return numberOfSentences;
- }
-
- public static void main( String args[]) {
- Statistics stats = new Statistics();
- String newText = "This is a normal text. The method only counts the number of
periods. "
- + "You can implement your own implementation with a more exact counting. "
- + "Let`s make a last sentence.";
- System.out.println("Number of sentences: " + stats.makeStatistics(newText));
- }
-}</programlisting>
-
- <para>If you test this sample in standalone mode, you need to put all
- jars of eXo Kernel in your buildpath, furthermore picoContainer is
- needed.</para>
- </section>
- </section>
-
- <section id="Parameters">
- <title>Parameters</title>
-
- <section id="ValueParam">
- <title>Value-Param</title>
-
- <para>There is an value-param example:</para>
-
- <programlisting> <component>
- <key>org.exoplatform.portal.config.UserACL</key>
- <type>org.exoplatform.portal.config.UserACL</type>
- <init-params>
-...
- <value-param>
- <name>access.control.workspace</name>
- <description>groups with memberships that have the right to access
the User Control Workspace</description>
-
<value>*:/platform/administrators,*:/organization/management/executive-board</value>
- </value-param>
-...
- </component></programlisting>
-
- <para>The UserACL class accesses to the <emphasis
- role="bold">value-param</emphasis> in its
constructor.</para>
-
- <programlisting>package org.exoplatform.portal.config;
-public class UserACL {
-
- public UserACL(InitParams params) {
- UserACLMetaData md = new UserACLMetaData();
- ValueParam accessControlWorkspaceParam =
params.getValueParam("access.control.workspace");
- if(accessControlWorkspaceParam != null)
md.setAccessControlWorkspace(accessControlWorkspaceParam.getValue());
-...</programlisting>
- </section>
-
- <section id="PropertiesParam">
- <title>Properties-Param</title>
-
- <para>Properties are name-value pairs. Both the name and the value are
- Java Strings.</para>
-
- <para>Here you see the hibernate configuration example:</para>
-
- <programlisting> <component>
-
<key>org.exoplatform.services.database.HibernateService</key>
-
<type>org.exoplatform.services.database.impl.HibernateServiceImpl</type>
- <init-params>
- <properties-param>
- <name>hibernate.properties</name>
- <description>Default Hibernate Service</description>
- <property name="hibernate.show_sql"
value="false"/>
- <property name="hibernate.cglib.use_reflection_optimizer"
value="true"/>
- <property name="hibernate.connection.url"
value="jdbc:hsqldb:file:../temp/data/exodb"/>
- <property name="hibernate.connection.driver_class"
value="org.hsqldb.jdbcDriver"/>
-...
- </properties-param>
- </init-params>
- </component></programlisting>
-
- <para>In the org.exoplatform.services.database.impl.HibernateServiceImpl
- you will find that the name "hibernate.properties" of the
- properties-param is used to access the properties.</para>
-
- <programlisting>package org.exoplatform.services.database.impl;
-
-public class HibernateServiceImpl implements HibernateService, ComponentRequestLifecycle
{
- public HibernateServiceImpl(InitParams initParams, CacheService cacheService) {
- PropertiesParam param =
initParams.getPropertiesParam("hibernate.properties");
-...
-}</programlisting>
- </section>
-
- <section id="ObjectParam">
- <title>Object-Param</title>
-
- <para>Let's have a look at the configuration of the LDAPService.
It's
- not important to know LDAP, we only discuss the parameters.</para>
-
- <programlisting><component>
- <key>org.exoplatform.services.ldap.LDAPService</key>
-
<type>org.exoplatform.services.ldap.impl.LDAPServiceImpl</type>
- <init-params>
- <object-param>
- <name>ldap.config</name>
- <description>Default ldap config</description>
- <object
type="org.exoplatform.services.ldap.impl.LDAPConnectionConfig">
- <field
name="providerURL"><string>ldaps://10.0.0.3:636</string></field>
- <field
name="rootdn"><string>CN=Administrator,CN=Users,DC=exoplatform,DC=org</string></field>
- <field
name="password"><string>exo</string></field>
- <field
name="version"><string>3</string></field>
- <field
name="minConnection"><int>5</int></field>
- <field
name="maxConnection"><int>10</int></field>
- <field
name="referralMode"><string>ignore</string></field>
- <field
name="serverName"><string>active.directory</string></field>
- </object>
- </object-param>
- </init-params>
-</component></programlisting>
-
- <para>You see here an <emphasis
role="bold">object-param</emphasis> is
- being used to pass the parameters inside an object (actually a java
- bean). It consists of a <emphasis
role="bold">name</emphasis>, a
- <emphasis role="bold">description</emphasis> and exactly one
<emphasis
- role="bold">object</emphasis>. The object defines the
<emphasis
- role="bold">type</emphasis> and a number of <emphasis
- role="bold">fields</emphasis>.</para>
-
- <para>Here you see how the service accesses the object:</para>
-
- <programlisting>package org.exoplatform.services.ldap.impl;
-
-public class LDAPServiceImpl implements LDAPService {
-...
- public LDAPServiceImpl(InitParams params) {
- LDAPConnectionConfig config = (LDAPConnectionConfig)
params.getObjectParam("ldap.config")
- .getObject();
-...</programlisting>
-
- <para>The passed object is LDAPConnectionConfig which is a classic
- <emphasis role="bold">java bean</emphasis>. It contains all
fields and
- also the appropriate getters and setters (not listed here). You also can
- provide default values. The container creates a new instance of your
- bean and calls all setters whose values are configured in the
- configuration file.</para>
-
- <programlisting>package org.exoplatform.services.ldap.impl;
-
-public class LDAPConnectionConfig {
- private String providerURL = "ldap://127.0.0.1:389";
- private String rootdn;
- private String password;
- private String version;
- private String authenticationType = "simple";
- private String serverName = "default";
- private int minConnection;
- private int maxConnection;
- private String referralMode = "follow";
-...</programlisting>
-
- <para>You see that the types (String, int) of the fields in the
- configuration correspond with the bean. A short glance in the
- kernel_1_0.xsd file let us discover more simple types:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">string, int, long, boolean,
date,
- double</emphasis></para>
- </listitem>
- </itemizedlist>
-
- <para>Have a look on this type test xml file: <ulink
-
url="https://anonsvn.jboss.org/repos/exo-jcr/kernel/trunk/exo.kernel...
- </section>
-
- <section id="Collection">
- <title>Collection</title>
-
- <para>You also can use java collections to configure your service. In
- order to see an example let's open the
- database-organization-configuration.xml file. This file defines a
- default user organization (users, groups, memberships/roles) of your
- portal. They use component-plugins which are explained later. You wil
- see that object-param is used again.</para>
-
- <para>There are two collections: The first collection is an <emphasis
- role="bold">ArrayList</emphasis>. This ArrayList contains only
one
- value, but there could be more. The only value is an object which
- defines the field of the NewUserConfig$JoinGroup bean.</para>
-
- <para>The second collection is a <emphasis
- role="bold">HashSet</emphasis> that is a set of
strings.</para>
-
- <programlisting> <component-plugin>
- <name>new.user.event.listener</name>
- <set-method>addListenerPlugin</set-method>
-
<type>org.exoplatform.services.organization.impl.NewUserEventListener</type>
- <description>this listener assign group and membership to a new
created user</description>
- <init-params>
- <object-param>
- <name>configuration</name>
- <description>description</description>
- <object
type="org.exoplatform.services.organization.impl.NewUserConfig">
- <field name="group">
- <collection type="java.util.ArrayList">
- <value>
- <object
type="org.exoplatform.services.organization.impl.NewUserConfig$JoinGroup">
- <field
name="groupId"><string>/platform/users</string></field>
- <field
name="membership"><string>member</string></field>
- </object>
- </value>
- </collection>
- </field>
- <field name="ignoredUser">
- <collection type="java.util.HashSet">
-
<value><string>root</string></value>
-
<value><string>john</string></value>
-
<value><string>marry</string></value>
-
<value><string>demo</string></value>
-
<value><string>james</string></value>
- </collection>
- </field>
- </object>
- </object-param>
- </init-params>
- </component-plugin></programlisting>
-
- <para>Let's look at the
- org.exoplatform.services.organization.impl.NewUserConfig bean:</para>
-
- <programlisting>public class NewUserConfig {
- private List role;
- private List group;
- private HashSet ignoredUser;
-
- ...
-
- public void setIgnoredUser(String user) {
- ignoredUser.add(user);
-
- ...
-
- static public class JoinGroup {
- public String groupId;
- public String membership;
- ...
-}</programlisting>
-
- <para>You see the values of the HashSet are set one by one by the
- container, and it's the responsibility of the bean to add these values
- to its HashSet.</para>
-
- <para>The JoinGroup object is just an inner class and implements a bean
- of its own. It can be accessed like any other inner class using
- NewUserConfig.JoinGroup.</para>
- </section>
- </section>
-
- <section id="ExternalPlugin">
- <title>External Plugin</title>
-
- <para>The External Plugin allows you to add configuration on the
- fly.</para>
-
- <para>As you have carefully read <link
- linkend="Kernel.ServiceConfigurationforBeginners">Service Configuration
- for Beginners</link> you know that <emphasis
- role="bold">normally</emphasis> newer configurations always
<emphasis
- role="bold">replaces</emphasis> previous configurations. An
external
- plugin allows you to <emphasis role="bold">add</emphasis>
configuration
- without replacing previous configurations.</para>
-
- <para>That can be interesting if you adapt a service configuration for
- your project-specific needs (country, language, branch, project,
- etc.).</para>
-
- <para>Let's have a look at the configuration of the TaxonomyPlugin of the
- CategoriesService:</para>
-
- <programlisting> <external-component-plugins>
-
<target-component>org.exoplatform.services.cms.categories.CategoriesService</target-component>
- <component-plugin>
- <name>predefinedTaxonomyPlugin</name>
- <set-method>addTaxonomyPlugin</set-method>
-
<type>org.exoplatform.services.cms.categories.impl.TaxonomyPlugin</type>
- <init-params>
- <value-param>
- <name>autoCreateInNewRepository</name>
- <value>true</value>
- </value-param>
- <value-param>
- <name>repository</name>
- <value>repository</value>
- </value-param>
- <object-param>
- <name>taxonomy.configuration</name>
- <description>configuration predefined taxonomies to inject in
jcr</description>
- <object
type="org.exoplatform.services.cms.categories.impl.TaxonomyConfig">
- <field name="taxonomies">
- <collection type="java.util.ArrayList">
- <!-- cms taxonomy -->
- <value>
- <object
type="org.exoplatform.services.cms.categories.impl.TaxonomyConfig$Taxonomy">
- <field
name="name"><string>cmsTaxonomy</string></field>
- <field
name="path"><string>/cms</string></field>
- </object>
- </value>
- <value>
- <object
type="org.exoplatform.services.cms.categories.impl.TaxonomyConfig$Taxonomy">
- <field
name="name"><string>newsTaxonomy</string></field>
- <field
name="path"><string>/cms/news</string></field>
- </object>
- </value>
- </field>
- </object>
- </object-param>
- </init-params>
- </component-plugin>
-<external-component-plugins></programlisting>
-
- <para>The <emphasis
role="bold"><target-component></emphasis>
- defines the service for which the plugin is defined. The configuration is
- injected by the container using a method that is defined in <emphasis
- role="bold"><set-method></emphasis>. The method has
exactly one
- argument of the type
- org.exoplatform.services.cms.categories.impl.TaxonomyPlugin:</para>
-
- <itemizedlist>
- <listitem>
-
<para>addTaxonomyPlugin(org.exoplatform.services.cms.categories.impl.TaxonomyPlugin
- plugin)</para>
- </listitem>
- </itemizedlist>
-
- <para>The content of <emphasis
role="bold"><init-params></emphasis>
- corresponds to the structure of the TaxonomyPlugin object.</para>
-
- <note>
- <para>You can configure the component CategoriesService using the
- addTaxonomyPlugin as often as you wish, you can also call
- addTaxonomyPlugin in different configuration files. The method
- addTaxonomyPlugin is then called several times, everything else depends
- on the implementation of the method</para>
- </note>
- </section>
-
- <section id="Import">
- <title>Import</title>
-
- <para>The import tag allows to link to other configuration files. These
- imported files can be placed anywhere. If you write a default
- configuration which is part of your jar file you should not import files
- from outside your jar.</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">war</emphasis>: Imports
from <emphasis
- role="bold">portal.war/WEB-INF</emphasis></para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">jar</emphasis> or
<emphasis
- role="bold">classpath</emphasis>: Uses the <emphasis
- role="bold">classloader</emphasis>, you can use this prefix in
the
- default configuration for importing an other configuration file which
- is accessible by the classloader.</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">file</emphasis>: Uses an
<emphasis
- role="bold">absolute path</emphasis>, you also can put a
<emphasis
- role="bold">URL</emphasis>.</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">without any
prefix</emphasis>:</para>
-
- <itemizedlist>
- <listitem>
- <para>Standalone mode: <emphasis role="bold">user
- directory</emphasis></para>
- </listitem>
-
- <listitem>
- <para>Portal mode: $AS-HOME, that means the application server
- home, for example " <emphasis
- role="bold">exo-tomcat</emphasis>".</para>
- </listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
-
- <para>If you open the
- "portal/trunk/web/portal/src/main/webapp/WEB-INF/conf.configuration.xml"
- you will see that it consists only of imports:
<programlisting><import>war:/conf/common/common-configuration.xml</import>
-<import>war:/conf/common/logs-configuration.xml</import>
-<import>war:/conf/database/database-configuration.xml</import>
-<import>war:/conf/jcr/jcr-configuration.xml</import>
-<import>war:/conf/common/portlet-container-configuration.xml</import>
-... </programlisting></para>
- </section>
-
- <section id="Systemproperties">
- <title>System properties</title>
-
- <para>Since kernel 2.0.7 and 2.1, it is possible to use system properties
- in literal values of component configuration meta data. This makes it
- possible to resolve properties at runtime instead of providing a value at
- packaging time.</para>
-
- <para>In
-
portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/database/database-configuration.tmpl.xml
- you find an example for system properties:</para>
-
- <programlisting> <component>
-
<key>org.exoplatform.services.database.HibernateService</key>
- <jmx-name>database:type=HibernateService</jmx-name>
-
<type>org.exoplatform.services.database.impl.HibernateServiceImpl</type>
- <init-params>
- <properties-param>
- <name>hibernate.properties</name>
- <description>Default Hibernate Service</description>
-...
- <property name="hibernate.connection.url"
value="${connectionUrl}"/>
- <property name="hibernate.connection.driver_class"
value="${driverClass}"/>
- <property name="hibernate.connection.username"
value="${username}"/>
- <property name="hibernate.connection.password"
value="${password}"/>
- <property name="hibernate.dialect"
value="${dialect}"/>
-...
- </properties-param>
- </init-params>
- </component></programlisting>
-
- <para>As these are system properties you use the -D command: <emphasis
- role="bold">java -DconnectionUrl=jdbc:hsqldb:file:../temp/data/exodb
- -DdriverClass=org.hsqldb.jdbcDriver</emphasis> Or better use the
- parameters of eXo.bat / eXo.sh when you start eXo Portal: <emphasis
- role="bold">set
- EXO_OPTS="-DconnectionUrl=jdbc:hsqldb:file:../temp/data/exodb
- -DdriverClass=org.hsqldb.jdbcDriver"</emphasis></para>
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="Kernel.ServiceConfigurationinDetail">
+ <?dbhtml filename="ch-service-configuration-in-detail.html"?>
+
+ <title>Service Configuration in Detail</title>
+
+ <para><emphasis role="bold">Related
documents</emphasis></para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link
linkend="Kernel.ServiceConfigurationforBeginners">Service
+ Configuration for Beginners</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="Kernel.ServicesWiring">Services
+ Wiring</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link
+ linkend="Kernel.ContainerConfiguration.ConfigurationNamespace">Kernel
+ Configuration File</link></para>
+ </listitem>
+ </itemizedlist>
+
+ <section>
+ <title>Objectives</title>
+
+ <para>This article shows in the first chapters how to setup a sample
+ service with some configurations and how to access to the configuration
+ parameters. The later chapters describe all details of the configuration
+ file (parameters, object-params, plugins, imports, etc.) it also shows how
+ to access the configuration values. You may consider this article as a
+ <emphasis role="bold">reference</emphasis>, but you can also
use this
+ article as a <emphasis role="bold">tutorial</emphasis> and read
it from
+ the beginning to the end.</para>
+ </section>
+
+ <section>
+ <title>Requirements</title>
+
+ <para>You should have read and understood <link
+ linkend="Kernel.ServiceConfigurationforBeginners">Service Configuration
+ for Beginners</link>. Obviously you should know java and xml. We are
+ working with examples that are created for teaching reasons only and you
+ will see extracts from the eXo Products default installation. When reading
+ do not forget that the terms service and component are interchangeable in
+ eXo Products.</para>
+ </section>
+
+ <section>
+ <title>Sample Service</title>
+
+ <section id="JavaClass">
+ <title>Java Class</title>
+
+ <para>Imagine you are working for a publishing company called "La
+ Verdad" that is going to use eXo platform. Your boss asks you be able to
+ calculate the number of sentences of an article.</para>
+
+ <para>You remember in eXo product everything is a <emphasis
+ role="bold">service</emphasis> so you decide to create a simple
class.
+ In future you want to be able to plug different implementations of your
+ service, so that you should define an <emphasis
+ role="bold">interface</emphasis> that defines your
service.</para>
+
+ <programlisting>package com.laverdad.services;
+public interface ArticleStatsService {
+ public abstract int calcSentences(String article);
+}</programlisting>
+
+ <para>A very simple implementation:</para>
+
+ <programlisting>public class ArticleStatsServiceImpl implements
ArticleStatsService {
+ public int calcSentences(String article) {
+ throw new RuntimeException("Not implemented");
+ }
+}</programlisting>
+
+ <para>That's it! You see there are no special prerequisites for a
+ service.</para>
+
+ <para>You should already have prepared your working environment, where
+ you have a base folder (let's call it our service base folder). If you
+ wish to try out this example create this class in the
+ com/laverdad/services/ArticleStatsService subfolder.</para>
+ </section>
+
+ <section>
+ <title>First configuration file</title>
+
+ <para>When creating a service you also should declare its existence to
+ the <emphasis role="bold">Container</emphasis>, therefore you
create a
+ first simple configuration file. Copy the following code to a file that
+ is called "configuration.xml" and place this file in a /conf
+ subdirectory of your service base folder. As you already know the
+ container looks for a "/conf/configuration.xml" file in each
+ jar-file.</para>
+
+ <programlisting><?xml version="1.0"
encoding="UTF8"?>
+<configuration
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd
http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+
xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <component>
+ <key>com.laverdad.services.ArticleStatsService</key>
+
<type>com.laverdad.services.ArticleStatsServiceImpl</type>
+ </component>
+</configuration></programlisting>
+
+ <note>
+ <para>You are correctly using the namespace of the configuration
+ schema (
<
uri>http://www.exoplaform.org/xml/ns/kernel_1_1.xsd</uri>).
+ Most of the configuration schema is explained in this
+ articles,therefore you do not need to open and understand the schema.
+ For backward compatibility it is not necessary to declare the
+ schema.</para>
+
+ <para>When eXo kernel reads a configuration it loads the file from the
+ kernel jar using the classloader and does not use an internet
+ connection to resolve the file.</para>
+ </note>
+ </section>
+
+ <section>
+ <title>Init Parameters</title>
+
+ <para>You see your service has a configuration file, but you wonder how
+ the file could possibly access to its configuration. Imagine you are
+ asked to implement two different calculation methods: fast and
+ exact.</para>
+
+ <para>You create one init parameter containing the calculation methods.
+ For the exact method you wish to configure more details for the service.
+ Let's enhance the word service configuration file:</para>
+
+ <programlisting> <component>
+ <key>com.laverdad.services.ArticleStatsService</key>
+
<type>com.laverdad.services.ArticleStatsServiceImpl</type>
+ <init-params>
+ <value-param>
+ <name>calc-method</name>
+ <description>calculation method: fast,
exact</description>
+ <value>fast</value>
+ </value-param>
+ <properties-param>
+ <name>details-for-exact-method</name>
+ <description>details for exact phrase
counting</description>
+ <property name="language" value="English" />
+ <property name="variant" value="us" />
+ </properties-param>
+ </init-params>
+ </component></programlisting>
+
+ <note>
+ <para>When configuring your service, you are <emphasis
+ role="bold">totally free</emphasis>. You can provide as many
<emphasis
+ role="bold">value-param</emphasis>, <emphasis
+ role="bold">property-param</emphasis>, and <emphasis
+ role="bold">properties</emphasis> you wish and you can give
them any
+ names or values. You only must respect the xml structure.</para>
+ </note>
+
+ <para>Now let's see how our service can read this configuration. The
+ implementation of the calcSentences() method serves just as a simple
+ example. It's up to your imagination to implement the exact
+ method.</para>
+
+ <programlisting>public class ArticleStatsServiceImpl implements
ArticleStatsService {
+
+ private String calcMethod = "fast";
+ private String variant = "French";
+ private String language = "France";
+
+ public ArticleStatsServiceImpl(InitParams initParams) {
+ super();
+ calcMethod = initParams.getValueParam("calc-method").getValue();
+ PropertiesParam detailsForExactMethod =
initParams.getPropertiesParam("details-for-exact-method");
+ if ( detailsForExactMethod != null) {
+ language = detailsForExactMethod.getProperty("language");
+ variant = detailsForExactMethod.getProperty("variant");
+ }
+ }
+
+ public int calcSentences(String article) {
+ if (calcMethod == "fast") {
+ // just count the number of periods "."
+ int res = 0;
+ int period = article.indexOf('.');
+ while (period != -1) {
+ res++;
+ article = article.substring(period+1);
+ period = article.indexOf('.');
+ }
+ return res;
+ }
+ throw new RuntimeException("Not implemented");
+ }
+}</programlisting>
+
+ <para>You see you just have to declare a parameter of
+ org.exoplatform.container.xml.InitParams in your constructor. The
+ container provides an InitParams object that correspond to the xml tree
+ of init-param.</para>
+ </section>
+
+ <section>
+ <title>Service Access</title>
+
+ <para>As you want to follow the principle of <emphasis
+ role="bold">Inversion of Control</emphasis> you <emphasis
+ role="bold">must not</emphasis> access the service directly. You
need a
+ <emphasis role="bold">Container</emphasis> to access the
service.</para>
+
+ <para>With this command you get your current container:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">ExoContainer myContainer =
+ ExoContainerContext.getCurrentContainer();</emphasis></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>This might be a PortalContainer or a StandaloneContainer,
+ dependant on the <link
+
linkend="Kernel.ServiceConfigurationinDetail.ExecutionModes">execution
+ mode</link> in which you are running your application.</para>
+
+ <para>Whenever you need one of the services that you have configured use
+ the method:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis
+
role="bold">myContainer.getComponentInstance(class)</emphasis></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>In our case:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">ArticleStatsService
statsService =
+ (ArticleStatsService)
+
myContainer.getComponentInstance(ArticleStatsService.class);</emphasis></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Recapitulation:</para>
+
+ <programlisting>package com.laverdad.common;
+
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import com.laverdad.services.*;
+
+public class Statistics {
+
+ public int makeStatistics(String articleText) {
+ ExoContainer myContainer = ExoContainerContext.getCurrentContainer();
+ ArticleStatsService statsService = (ArticleStatsService)
+ myContainer.getComponentInstance(ArticleStatsService.class);
+ int numberOfSentences = statsService.calcSentences(articleText);
+ return numberOfSentences;
+ }
+
+ public static void main( String args[]) {
+ Statistics stats = new Statistics();
+ String newText = "This is a normal text. The method only counts the number of
periods. "
+ + "You can implement your own implementation with a more exact counting. "
+ + "Let`s make a last sentence.";
+ System.out.println("Number of sentences: " + stats.makeStatistics(newText));
+ }
+}</programlisting>
+
+ <para>If you test this sample in standalone mode, you need to put all
+ jars of eXo Kernel in your buildpath, furthermore picoContainer is
+ needed.</para>
+ </section>
+ </section>
+
+ <section>
+ <title>Parameters</title>
+
+ <section>
+ <title>Value-Param</title>
+
+ <para>There is an value-param example:</para>
+
+ <programlisting> <component>
+ <key>org.exoplatform.portal.config.UserACL</key>
+ <type>org.exoplatform.portal.config.UserACL</type>
+ <init-params>
+...
+ <value-param>
+ <name>access.control.workspace</name>
+ <description>groups with memberships that have the right to access
the User Control Workspace</description>
+
<value>*:/platform/administrators,*:/organization/management/executive-board</value>
+ </value-param>
+...
+ </component></programlisting>
+
+ <para>The UserACL class accesses to the <emphasis
+ role="bold">value-param</emphasis> in its
constructor.</para>
+
+ <programlisting>package org.exoplatform.portal.config;
+public class UserACL {
+
+ public UserACL(InitParams params) {
+ UserACLMetaData md = new UserACLMetaData();
+ ValueParam accessControlWorkspaceParam =
params.getValueParam("access.control.workspace");
+ if(accessControlWorkspaceParam != null)
md.setAccessControlWorkspace(accessControlWorkspaceParam.getValue());
+...</programlisting>
+ </section>
+
+ <section>
+ <title>Properties-Param</title>
+
+ <para>Properties are name-value pairs. Both the name and the value are
+ Java Strings.</para>
+
+ <para>Here you see the hibernate configuration example:</para>
+
+ <programlisting> <component>
+
<key>org.exoplatform.services.database.HibernateService</key>
+
<type>org.exoplatform.services.database.impl.HibernateServiceImpl</type>
+ <init-params>
+ <properties-param>
+ <name>hibernate.properties</name>
+ <description>Default Hibernate Service</description>
+ <property name="hibernate.show_sql"
value="false"/>
+ <property name="hibernate.cglib.use_reflection_optimizer"
value="true"/>
+ <property name="hibernate.connection.url"
value="jdbc:hsqldb:file:../temp/data/exodb"/>
+ <property name="hibernate.connection.driver_class"
value="org.hsqldb.jdbcDriver"/>
+...
+ </properties-param>
+ </init-params>
+ </component></programlisting>
+
+ <para>In the org.exoplatform.services.database.impl.HibernateServiceImpl
+ you will find that the name "hibernate.properties" of the
+ properties-param is used to access the properties.</para>
+
+ <programlisting>package org.exoplatform.services.database.impl;
+
+public class HibernateServiceImpl implements HibernateService, ComponentRequestLifecycle
{
+ public HibernateServiceImpl(InitParams initParams, CacheService cacheService) {
+ PropertiesParam param =
initParams.getPropertiesParam("hibernate.properties");
+...
+}</programlisting>
+ </section>
+
+ <section>
+ <title>Object-Param</title>
+
+ <para>Let's have a look at the configuration of the LDAPService.
It's
+ not important to know LDAP, we only discuss the parameters.</para>
+
+ <programlisting><component>
+ <key>org.exoplatform.services.ldap.LDAPService</key>
+
<type>org.exoplatform.services.ldap.impl.LDAPServiceImpl</type>
+ <init-params>
+ <object-param>
+ <name>ldap.config</name>
+ <description>Default ldap config</description>
+ <object
type="org.exoplatform.services.ldap.impl.LDAPConnectionConfig">
+ <field
name="providerURL"><string>ldaps://10.0.0.3:636</string></field>
+ <field
name="rootdn"><string>CN=Administrator,CN=Users,DC=exoplatform,DC=org</string></field>
+ <field
name="password"><string>exo</string></field>
+ <field
name="version"><string>3</string></field>
+ <field
name="minConnection"><int>5</int></field>
+ <field
name="maxConnection"><int>10</int></field>
+ <field
name="referralMode"><string>ignore</string></field>
+ <field
name="serverName"><string>active.directory</string></field>
+ </object>
+ </object-param>
+ </init-params>
+</component></programlisting>
+
+ <para>You see here an <emphasis
role="bold">object-param</emphasis> is
+ being used to pass the parameters inside an object (actually a java
+ bean). It consists of a <emphasis
role="bold">name</emphasis>, a
+ <emphasis role="bold">description</emphasis> and exactly one
<emphasis
+ role="bold">object</emphasis>. The object defines the
<emphasis
+ role="bold">type</emphasis> and a number of <emphasis
+ role="bold">fields</emphasis>.</para>
+
+ <para>Here you see how the service accesses the object:</para>
+
+ <programlisting>package org.exoplatform.services.ldap.impl;
+
+public class LDAPServiceImpl implements LDAPService {
+...
+ public LDAPServiceImpl(InitParams params) {
+ LDAPConnectionConfig config = (LDAPConnectionConfig)
params.getObjectParam("ldap.config")
+ .getObject();
+...</programlisting>
+
+ <para>The passed object is LDAPConnectionConfig which is a classic
+ <emphasis role="bold">java bean</emphasis>. It contains all
fields and
+ also the appropriate getters and setters (not listed here). You also can
+ provide default values. The container creates a new instance of your
+ bean and calls all setters whose values are configured in the
+ configuration file.</para>
+
+ <programlisting>package org.exoplatform.services.ldap.impl;
+
+public class LDAPConnectionConfig {
+ private String providerURL = "ldap://127.0.0.1:389";
+ private String rootdn;
+ private String password;
+ private String version;
+ private String authenticationType = "simple";
+ private String serverName = "default";
+ private int minConnection;
+ private int maxConnection;
+ private String referralMode = "follow";
+...</programlisting>
+
+ <para>You see that the types (String, int) of the fields in the
+ configuration correspond with the bean. A short glance in the
+ kernel_1_0.xsd file let us discover more simple types:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">string, int, long, boolean,
date,
+ double</emphasis></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Have a look on this type test xml file: <ulink
+
url="https://anonsvn.jboss.org/repos/exo-jcr/kernel/trunk/exo.kernel...
+ </section>
+
+ <section>
+ <title>Collection</title>
+
+ <para>You also can use java collections to configure your service. In
+ order to see an example let's open the
+ database-organization-configuration.xml file. This file defines a
+ default user organization (users, groups, memberships/roles) of your
+ portal. They use component-plugins which are explained later. You wil
+ see that object-param is used again.</para>
+
+ <para>There are two collections: The first collection is an <emphasis
+ role="bold">ArrayList</emphasis>. This ArrayList contains only
one
+ value, but there could be more. The only value is an object which
+ defines the field of the NewUserConfig$JoinGroup bean.</para>
+
+ <para>The second collection is a <emphasis
+ role="bold">HashSet</emphasis> that is a set of
strings.</para>
+
+ <programlisting> <component-plugin>
+ <name>new.user.event.listener</name>
+ <set-method>addListenerPlugin</set-method>
+
<type>org.exoplatform.services.organization.impl.NewUserEventListener</type>
+ <description>this listener assign group and membership to a new
created user</description>
+ <init-params>
+ <object-param>
+ <name>configuration</name>
+ <description>description</description>
+ <object
type="org.exoplatform.services.organization.impl.NewUserConfig">
+ <field name="group">
+ <collection type="java.util.ArrayList">
+ <value>
+ <object
type="org.exoplatform.services.organization.impl.NewUserConfig$JoinGroup">
+ <field
name="groupId"><string>/platform/users</string></field>
+ <field
name="membership"><string>member</string></field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ <field name="ignoredUser">
+ <collection type="java.util.HashSet">
+
<value><string>root</string></value>
+
<value><string>john</string></value>
+
<value><string>marry</string></value>
+
<value><string>demo</string></value>
+
<value><string>james</string></value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin></programlisting>
+
+ <para>Let's look at the
+ org.exoplatform.services.organization.impl.NewUserConfig bean:</para>
+
+ <programlisting>public class NewUserConfig {
+ private List role;
+ private List group;
+ private HashSet ignoredUser;
+
+ ...
+
+ public void setIgnoredUser(String user) {
+ ignoredUser.add(user);
+
+ ...
+
+ static public class JoinGroup {
+ public String groupId;
+ public String membership;
+ ...
+}</programlisting>
+
+ <para>You see the values of the HashSet are set one by one by the
+ container, and it's the responsibility of the bean to add these values
+ to its HashSet.</para>
+
+ <para>The JoinGroup object is just an inner class and implements a bean
+ of its own. It can be accessed like any other inner class using
+ NewUserConfig.JoinGroup.</para>
+ </section>
+ </section>
+
+ <section>
+ <title>External Plugin</title>
+
+ <para>The External Plugin allows you to add configuration on the
+ fly.</para>
+
+ <para>As you have carefully read <link
+ linkend="Kernel.ServiceConfigurationforBeginners">Service Configuration
+ for Beginners</link> you know that <emphasis
+ role="bold">normally</emphasis> newer configurations always
<emphasis
+ role="bold">replaces</emphasis> previous configurations. An
external
+ plugin allows you to <emphasis role="bold">add</emphasis>
configuration
+ without replacing previous configurations.</para>
+
+ <para>That can be interesting if you adapt a service configuration for
+ your project-specific needs (country, language, branch, project,
+ etc.).</para>
+
+ <para>Let's have a look at the configuration of the TaxonomyPlugin of the
+ CategoriesService:</para>
+
+ <programlisting> <external-component-plugins>
+
<target-component>org.exoplatform.services.cms.categories.CategoriesService</target-component>
+ <component-plugin>
+ <name>predefinedTaxonomyPlugin</name>
+ <set-method>addTaxonomyPlugin</set-method>
+
<type>org.exoplatform.services.cms.categories.impl.TaxonomyPlugin</type>
+ <init-params>
+ <value-param>
+ <name>autoCreateInNewRepository</name>
+ <value>true</value>
+ </value-param>
+ <value-param>
+ <name>repository</name>
+ <value>repository</value>
+ </value-param>
+ <object-param>
+ <name>taxonomy.configuration</name>
+ <description>configuration predefined taxonomies to inject in
jcr</description>
+ <object
type="org.exoplatform.services.cms.categories.impl.TaxonomyConfig">
+ <field name="taxonomies">
+ <collection type="java.util.ArrayList">
+ <!-- cms taxonomy -->
+ <value>
+ <object
type="org.exoplatform.services.cms.categories.impl.TaxonomyConfig$Taxonomy">
+ <field
name="name"><string>cmsTaxonomy</string></field>
+ <field
name="path"><string>/cms</string></field>
+ </object>
+ </value>
+ <value>
+ <object
type="org.exoplatform.services.cms.categories.impl.TaxonomyConfig$Taxonomy">
+ <field
name="name"><string>newsTaxonomy</string></field>
+ <field
name="path"><string>/cms/news</string></field>
+ </object>
+ </value>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin>
+<external-component-plugins></programlisting>
+
+ <para>The <emphasis
role="bold"><target-component></emphasis>
+ defines the service for which the plugin is defined. The configuration is
+ injected by the container using a method that is defined in <emphasis
+ role="bold"><set-method></emphasis>. The method has
exactly one
+ argument of the type
+ org.exoplatform.services.cms.categories.impl.TaxonomyPlugin:</para>
+
+ <itemizedlist>
+ <listitem>
+
<para>addTaxonomyPlugin(org.exoplatform.services.cms.categories.impl.TaxonomyPlugin
+ plugin)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The content of <emphasis
role="bold"><init-params></emphasis>
+ corresponds to the structure of the TaxonomyPlugin object.</para>
+
+ <note>
+ <para>You can configure the component CategoriesService using the
+ addTaxonomyPlugin as often as you wish, you can also call
+ addTaxonomyPlugin in different configuration files. The method
+ addTaxonomyPlugin is then called several times, everything else depends
+ on the implementation of the method</para>
+ </note>
+ </section>
+
+ <section>
+ <title>Import</title>
+
+ <para>The import tag allows to link to other configuration files. These
+ imported files can be placed anywhere. If you write a default
+ configuration which is part of your jar file you should not import files
+ from outside your jar.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">war</emphasis>: Imports
from <emphasis
+ role="bold">portal.war/WEB-INF</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">jar</emphasis> or
<emphasis
+ role="bold">classpath</emphasis>: Uses the <emphasis
+ role="bold">classloader</emphasis>, you can use this prefix in
the
+ default configuration for importing an other configuration file which
+ is accessible by the classloader.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">file</emphasis>: Uses an
<emphasis
+ role="bold">absolute path</emphasis>, you also can put a
<emphasis
+ role="bold">URL</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">without any
prefix</emphasis>:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Standalone mode: <emphasis role="bold">user
+ directory</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>Portal mode: $AS-HOME, that means the application server
+ home, for example " <emphasis
+ role="bold">exo-tomcat</emphasis>".</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+
+ <para>If you open the
+ "portal/trunk/web/portal/src/main/webapp/WEB-INF/conf.configuration.xml"
+ you will see that it consists only of imports:
<programlisting><import>war:/conf/common/common-configuration.xml</import>
+<import>war:/conf/common/logs-configuration.xml</import>
+<import>war:/conf/database/database-configuration.xml</import>
+<import>war:/conf/jcr/jcr-configuration.xml</import>
+<import>war:/conf/common/portlet-container-configuration.xml</import>
+... </programlisting></para>
+ </section>
+
+ <section>
+ <title>System properties</title>
+
+ <para>Since kernel 2.0.7 and 2.1, it is possible to use system properties
+ in literal values of component configuration meta data. This makes it
+ possible to resolve properties at runtime instead of providing a value at
+ packaging time.</para>
+
+ <para>In
+
portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/database/database-configuration.tmpl.xml
+ you find an example for system properties:</para>
+
+ <programlisting> <component>
+
<key>org.exoplatform.services.database.HibernateService</key>
+ <jmx-name>database:type=HibernateService</jmx-name>
+
<type>org.exoplatform.services.database.impl.HibernateServiceImpl</type>
+ <init-params>
+ <properties-param>
+ <name>hibernate.properties</name>
+ <description>Default Hibernate Service</description>
+...
+ <property name="hibernate.connection.url"
value="${connectionUrl}"/>
+ <property name="hibernate.connection.driver_class"
value="${driverClass}"/>
+ <property name="hibernate.connection.username"
value="${username}"/>
+ <property name="hibernate.connection.password"
value="${password}"/>
+ <property name="hibernate.dialect"
value="${dialect}"/>
+...
+ </properties-param>
+ </init-params>
+ </component></programlisting>
+
+ <para>As these are system properties you use the -D command: <emphasis
+ role="bold">java -DconnectionUrl=jdbc:hsqldb:file:../temp/data/exodb
+ -DdriverClass=org.hsqldb.jdbcDriver</emphasis> Or better use the
+ parameters of eXo.bat / eXo.sh when you start eXo Portal: <emphasis
+ role="bold">set
+ EXO_OPTS="-DconnectionUrl=jdbc:hsqldb:file:../temp/data/exodb
+ -DdriverClass=org.hsqldb.jdbcDriver"</emphasis></para>
+ </section>
+</chapter>