Author: sergiykarpenko
Date: 2010-08-03 03:16:23 -0400 (Tue, 03 Aug 2010)
New Revision: 2856
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/configuration-persister.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/exo-jcr-configuration.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/external-value-storages.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/multilanguage-support.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/rest-services-on-groovy.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/search-configuration.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/workspace-persistence-storage.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/offset-and-limit.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/searching-repository-content.xml
Removed:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration-persister.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/external-value-storages.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/jdbc-data-container-config.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/multilanguage-support.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/search-configuration.xml
Modified:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
Log:
EXOJCR-869: configuration and search documents ported
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/configuration-persister.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/configuration-persister.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/configuration-persister.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.ConfigurationPersister">
+ <?dbhtml filename="ch-jcr-configuration-persister.html"?>
+ <title>JCR Configuration persister</title>
+
+ <section>
+ <title>Idea</title>
+
+ <para>JCR Repository Service uses
+
<classname>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</classname>
+ component to read its configuration.</para>
+
+ <programlisting><component>
+
<key>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</key>
+
<type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationImpl</type>
+ <init-params>
+ <value-param>
+ <name>conf-path</name>
+ <description>JCR configuration file</description>
+ <value>/conf/standalone/exo-jcr-config.xml</value>
+ </value-param>
+ </init-params>
+ </component></programlisting>
+
+ <para>In the example Repository Service will read the configuration from
+ the file
<filename>/conf/standalone/exo-jcr-config.xml</filename>.</para>
+
+ <para>But in some cases it's required to change the configuration on the
+ fly. And know that the new one will be used. Additionally we wish not to
+ modify the original file.</para>
+
+ <para>In this case we have to use the configuration persister feature
+ which allows to store the configuration in different locations.</para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <para>On startup
<classname>RepositoryServiceConfiguration</classname>
+ component checks if a configuration persister was configured. In that case
+ it uses the provided <classname>ConfigurationPersister</classname>
+ implementation class to instantiate the persister object.</para>
+
+ <para>Configuration with
persister:<programlisting><component>
+
<key>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</key>
+
<type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationImpl</type>
+ <init-params>
+ <value-param>
+ <name>conf-path</name>
+ <description>JCR configuration file</description>
+ <value>/conf/standalone/exo-jcr-config.xml</value>
+ </value-param>
+ <properties-param>
+ <name>working-conf</name>
+ <description>working-conf</description>
+ <property name="source-name" value="jdbcjcr"
/>
+ <property name="dialect" value="mysql" />
+ <property name="persister-class-name"
value="org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister"
/>
+ </properties-param>
+ </init-params>
+ </component></programlisting></para>
+
+ <para>Where:<itemizedlist>
+ <listitem>
+ <para><parameter>source-name</parameter> - JNDI source name
+ configured in <classname>InitialContextInitializer</classname>
+ component. (<parameter>sourceName</parameter> prior v.1.9.) Find
+ more in <link linkend="ch_configuration">database
+ configuration</link>.</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>dialect</parameter> - SQL dialect which will
be
+ used with database from <parameter>source-name</parameter>. Find
+ more in <link linkend="ch_configuration">database
+ configuration</link>.</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>persister-class-name</parameter> - class
name of
+ <classname>ConfigurationPersister</classname> interface
+ implementation. (<parameter>persisterClassName</parameter> prior
+ v.1.9.)</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>ConfigurationPersister interface:<programlisting>/**
+ * Init persister.
+ * Used by RepositoryServiceConfiguration on init.
+ * @return - config data stream
+ */
+ void init(PropertiesParam params) throws RepositoryConfigurationException;
+
+ /**
+ * Read config data.
+ * @return - config data stream
+ */
+ InputStream read() throws RepositoryConfigurationException;
+
+ /**
+ * Create table, write data.
+ * @param confData - config data stream
+ */
+ void write(InputStream confData) throws RepositoryConfigurationException;
+
+ /**
+ * Tell if the config exists.
+ * @return - flag
+ */
+ boolean hasConfig() throws
RepositoryConfigurationException;</programlisting></para>
+
+ <para>JCR Core implementation contains a persister which stores the
+ repository configuration in the relational database using JDBC calls -
+
<classname>org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister</classname>.</para>
+
+ <para>The implementation will crate and use table JCR_CONFIG in the
+ provided database.</para>
+
+ <para>But the developer can implement his own persister for his particular
+ usecase.</para>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/exo-jcr-configuration.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/exo-jcr-configuration.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/exo-jcr-configuration.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,415 @@
+<?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.eXoJCRconfiguration">
+ <?dbhtml filename="ch-jcr-configuration.html"?>
+ <title>eXo JCR configuration</title>
+ <section>
+ <title>Related documents</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link
linkend="JCR.ConfigurationPersister">Configuration
+ persister</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.SearchConfiguration">Search
+ Configuration</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="ch_jdbc_data_container">JDBC Data
Container
+ config</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="ch_external_value_storages">External
Value
+ Storages</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="none">Workspace SimpleDB
storage</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="none">Workspace Persistence
Storage</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Portal and Standalone configuration</title>
+
+ <para>Like other eXo services eXo JCR can be configured and used in portal
+ or embedded mode (as a service embedded in eXo Portal) and in standalone
+ mode.</para>
+
+ <para>In Embedded mode, JCR services are registered in the Portal
+ container and the second option is to use a Standalone container. The main
+ difference between these container types is that the first one is intended
+ to be used in a Portal (Web) environment, while the second one can be used
+ standalone (see the comprehensive page <link
+ linkend="Kernel.ServiceConfigurationForBeginners">Service Configuration
+ for Beginners</link> for more details).</para>
+
+ <para>The following setup procedure is used to obtain a Standalone
+ configuration (find more in <link
+ linkend="Kernel.ContainerConfiguration">Container
+ configuration</link>):</para>
+
+ <para>* Configuration that is set explicitly using
+ StandaloneContainer.addConfigurationURL(String url) or
+ StandaloneContainer.addConfigurationPath(String path) before
+ getInstance()</para>
+
+ <para>* Configuration from $base:directory/exo-configuration.xml or
+ $base:directory/conf/exo-configuration.xml file. Where $base:directory is
+ either AS's home directory in case of J2EE AS environment or just the
+ current directory in case of a standalone application.</para>
+
+ <para>* /conf/exo-configuration.xml in the current classloader (e.g. war,
+ ear archive)</para>
+
+ <para>* Configuration from
+ $service_jar_file/conf/portal/configuration.xml. WARNING: do not rely on
+ some concrete jar's configuration if you have more than one jar containing
+ conf/portal/configuration.xml file. In this case choosing a configuration
+ is unpredictable.</para>
+
+ <para>JCR service configuration looks like:</para>
+
+ <programlisting><component>
+ <key>org.exoplatform.services.jcr.RepositoryService</key>
+
<type>org.exoplatform.services.jcr.impl.RepositoryServiceImpl</type>
+</component>
+<component>
+
<key>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</key>
+
<type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationImpl</type>
+ <init-params>
+ <value-param>
+ <name>conf-path</name>
+ <description>JCR repositories configuration
file</description>
+ <value>jar:/conf/standalone/exo-jcr-config.xml</value>
+ </value-param>
+ <properties-param>
+ <name>working-conf</name>
+ <description>working-conf</description>
+ <property name="source-name" value="jdbcjcr" />
+ <property name="dialect" value="hsqldb" />
+ <property name="persister-class-name"
value="org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister"
/>
+ </properties-param>
+ </init-params>
+</component></programlisting>
+
+ <para><emphasis role="bold">conf-path</emphasis> : a path
to a
+ RepositoryService JCR Configuration.</para>
+
+ <para><emphasis role="bold">working-conf</emphasis> :
optional; <link
+ linkend="JCR.ConfigurationPersister">JCR configuration
persister</link>
+ configuration. If there isn't a working-conf the persister will be
+ disabled.</para>
+ </section>
+
+ <section>
+ <title>JCR Configuration</title>
+
+ <para>The Configuration is defined in an XML file (see DTD below)</para>
+
+ <para>JCR Service can use multiple <emphasis
+ role="bold">Repositories</emphasis> and each repository can have
multiple
+ <emphasis role="bold">Workspaces</emphasis>.</para>
+
+ <para>From v.1.9 JCR repositories configuration parameters support
+ human-readable formats of values. They are all case-insensitive:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Numbers formats: K,KB - kilobytes, M,MB - megabytes, G,GB -
+ gigabytes, T,TB - terabytes. Examples: 100.5 - digit 100.5, 200k - 200
+ Kbytes, 4m - 4 Mbytes, 1.4G - 1.4 Gbytes, 10T - 10 Tbytes</para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>Time format endings: ms - milliseconds, m - minutes, h - hours,
+ d - days, w - weeks, if no ending - seconds. Examples: 500ms - 500
+ milliseconds, 20 - 20 seconds, 30m - 30 minutes, 12h - 12 hours, 5d -
+ 5 days, 4w - 4 weeks.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Repository service configuration (JCR repositories
+ configuration)</title>
+
+ <para>Service configuration may be placed in
+ jar:/conf/standalone/exo-jcr-config.xml for standalone mode. For portal
+ mode it is located in the portal web application
+ portal/WEB-INF/conf/jcr/repository-configuration.xml</para>
+
+ <para><emphasis role="bold">default-repository</emphasis>
- the name of a
+ default repository (one returned by
+ RepositoryService.getRepository())</para>
+
+ <para><emphasis role="bold">repositories</emphasis> - the
list of
+ repositories</para>
+ </section>
+
+ <section>
+ <title>Repository configuration:</title>
+
+ <para><emphasis role="bold">name</emphasis> - the name of
a
+ repository</para>
+
+ <para><emphasis role="bold">default-workspace</emphasis>
- the name of a
+ workspace obtained using Session's login() or login(Credentials) methods
+ (ones without an explicit workspace name)</para>
+
+ <para><emphasis role="bold">system-workspace</emphasis> -
name of
+ workspace where <emphasis role="bold">/jcr:system</emphasis>
node is
+ placed</para>
+
+ <para><emphasis role="bold">security-domain</emphasis> -
the name of a
+ security domain for JAAS authentication</para>
+
+ <para><emphasis role="bold">access-control</emphasis> -
the name of an
+ access control policy. There can be 3 types: optional - ACL is created
+ on-demand(default), disable - no access control, mandatory - an ACL is
+ created for each added node(not supported yet)</para>
+
+ <para><emphasis
role="bold">authentication-policy</emphasis> - the name of
+ an authentication policy class</para>
+
+ <para><emphasis role="bold">workspaces</emphasis> - the
list of
+ workspaces</para>
+
+ <para><emphasis role="bold">session-max-age</emphasis> -
the time after
+ which an idle session will be removed (called logout). If not set, the
+ idle session will never be removed.</para>
+ </section>
+
+ <section>
+ <title>Workspace configuration:</title>
+
+ <para><emphasis role="bold">name</emphasis> - the name of
a
+ workspace</para>
+
+ <para><emphasis
role="bold">auto-init-root-nodetype</emphasis> -
+ DEPRECATED in JCR 1.9 (use initializer). The node type for root node
+ initialization</para>
+
+ <para><emphasis role="bold">container</emphasis> -
workspace data
+ container (physical storage) configuration</para>
+
+ <para><emphasis role="bold">initializer</emphasis> -
workspace initializer
+ configuration</para>
+
+ <para><emphasis role="bold">cache</emphasis> - workspace
storage cache
+ configuration</para>
+
+ <para><emphasis role="bold">query-handler</emphasis> -
query handler
+ configuration</para>
+
+ <para><emphasis
role="bold">auto-init-permissions</emphasis> - DEPRECATED
+ in JCR 1.9 (use initializer). Default permissions of the root node. It is
+ defined as a set of semicolon-delimited permissions containing a group of
+ space-delimited identities (user, group etc, see Organization service
+ documentation for details) and the type of permission. For example any
+ read; <emphasis role="bold">:/admin read;</emphasis>:/admin
add_node;
+ <emphasis role="bold">:/admin set_property;</emphasis>:/admin
remove means
+ that users from group <emphasis role="bold">admin</emphasis>
have all
+ permissions and other users have only a 'read' permission.</para>
+ </section>
+
+ <section>
+ <title>Workspace data container configuration:</title>
+
+ <para><emphasis role="bold">class</emphasis> - A
workspace data container
+ class name</para>
+
+ <para><emphasis role="bold">properties</emphasis> - the
list of properties
+ (name-value pairs) for the concrete Workspace data container</para>
+
+ <para><emphasis role="bold">value-storages</emphasis> -
the list of value
+ storage plugins</para>
+ </section>
+
+ <section id="JCR.ConfigurationPersister.ValueStoragePlugin">
+ <title>Value Storage plugin configuration (for data container):</title>
+
+ <note>
+ <para>The value-storage element is optional. If you don't include it,
+ the values will be stored as BLOBs inside the database.</para>
+ </note>
+
+ <para><emphasis role="bold">value-storage</emphasis> -
Optional value
+ Storage plugin definition:</para>
+
+ <para><emphasis role="bold">class</emphasis>- a value
storage plugin class
+ name (attribute)</para>
+
+ <para><emphasis role="bold">properties</emphasis> - the
list of properties
+ (name-value pairs) for a concrete Value Storage plugin</para>
+
+ <para><emphasis role="bold">filters</emphasis> - the list
of filters
+ defining conditions when this plugin is applicable</para>
+ </section>
+
+ <section>
+ <title>Initializer configuration (optional):</title>
+
+ <para><emphasis role="bold">class</emphasis> -
initializer implementation
+ class.</para>
+
+ <para><emphasis role="bold">properties</emphasis> - the
list of properties
+ (name-value pairs). Properties are supported:</para>
+
+ <para><emphasis role="bold">root-nodetype</emphasis> -
The node type for
+ root node initialization</para>
+
+ <para><emphasis role="bold">root-permissions</emphasis> -
Default
+ permissions of the root node. It is defined as a set of
+ semicolon-delimited permissions containing a group of space-delimited
+ identities (user, group etc, see Organization service documentation for
+ details) and the type of permission. For example any read; <emphasis
+ role="bold">:/admin read;</emphasis>:/admin add_node;
<emphasis
+ role="bold">:/admin set_property;</emphasis>:/admin remove means
that
+ users from group <emphasis role="bold">admin</emphasis> have
all
+ permissions and other users have only a 'read' permission.</para>
+
+ <para>Configurable initializer adds a capability to override workspace
+ initial startup procedure (used for Clustering). Also it replaces
+ workspace element parameters auto-init-root-nodetype and
+ auto-init-permissions with root-nodetype and root-permissions.</para>
+ </section>
+
+ <section>
+ <title>Cache configuration:</title>
+
+ <para><emphasis role="bold">enabled</emphasis> - if
workspace cache is
+ enabled</para>
+
+ <para><emphasis role="bold">class</emphasis> - cache
implementation class,
+ optional from 1.9. Default value is
+
org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl.</para>
+
+ <para>Cache can be configured to use concrete implementation of
+ WorkspaceStorageCache interface. JCR core has two implementation to
+ use:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>LinkedWorkspaceStorageCacheImpl - default, with configurable
+ read behavior and statistic.</para>
+ </listitem>
+
+ <listitem>
+ <para>WorkspaceStorageCacheImpl - pre 1.9, still can be used.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><emphasis role="bold">properties</emphasis> - the
list of properties
+ (name-value pairs) for Workspace cache:</para>
+
+ <para><emphasis role="bold">max-size</emphasis> - cache
maximum size
+ (maxSize prior to v.1.9).</para>
+
+ <para><emphasis role="bold">live-time</emphasis> - cached
item live time
+ (liveTime prior to v.1.9).</para>
+
+ <para>From 1.9 LinkedWorkspaceStorageCacheImpl supports additional
+ optional parameters.</para>
+
+ <para><emphasis role="bold">statistic-period</emphasis> -
period (time
+ format) of cache statistic thread execution, 5 minutes by default.</para>
+
+ <para><emphasis role="bold">statistic-log</emphasis> - if
true cache
+ statistic will be printed to default logger (log.info), false by
+ default.</para>
+
+ <para><emphasis role="bold">statistic-clean</emphasis> -
if true cache
+ statistic will be cleaned after was gathered, false by default.</para>
+
+ <para><emphasis role="bold">cleaner-period</emphasis> -
period of eldest
+ items remover execution, 20 minutes by default.</para>
+
+ <para><emphasis
role="bold">blocking-users-count</emphasis> - number of
+ concurrent users allowed to read cache storage, 0 - unlimited by
+ default.</para>
+ </section>
+
+ <section>
+ <title>Query Handler configuration:</title>
+
+ <para><emphasis role="bold">class</emphasis> - A Query
Handler class
+ name</para>
+
+ <para><emphasis role="bold">properties</emphasis> - the
list of properties
+ (name-value pairs) for a Query Handler (indexDir)</para>
+
+ <para>Properties and advanced features described in <link
+ linkend="JCR.SearchConfiguration">Search
Configuration</link>.</para>
+ </section>
+
+ <section>
+ <title>Lock Manager configuration:</title>
+
+ <para><emphasis role="bold">time-out</emphasis> - time
after which the
+ unused global lock will be removed.</para>
+
+ <para><emphasis role="bold">persister</emphasis> - a
class for storing
+ lock information for future use. For example, remove lock after jcr
+ restart.</para>
+
+ <para><emphasis role="bold">path</emphasis> - a lock
folder, each
+ workspace has its own.</para>
+
+ <para>Additional information about the configuration of the lock you can
+ see in <link linkend="TODO.JCR.Locking">JCR Locks Implementation
+ Specification</link>.</para>
+
+ <programlisting><!ELEMENT repository-service (repositories)>
+<!ATTLIST repository-service default-repository NMTOKEN #REQUIRED>
+<!ELEMENT repositories (repository)>
+<!ELEMENT repository
(security-domain,access-control,session-max-age,authentication-policy,workspaces)>
+<!ATTLIST repository
+ default-workspace NMTOKEN #REQUIRED
+ name NMTOKEN #REQUIRED
+ system-workspace NMTOKEN #REQUIRED
+>
+<!ELEMENT security-domain (#PCDATA)>
+<!ELEMENT access-control (#PCDATA)>
+<!ELEMENT session-max-age (#PCDATA)>
+<!ELEMENT authentication-policy (#PCDATA)>
+<!ELEMENT workspaces (workspace+)>
+<!ELEMENT workspace (container,initializer,cache,query-handler)>
+<!ATTLIST workspace name NMTOKEN #REQUIRED>
+<!ELEMENT container (properties,value-storages)>
+<!ATTLIST container class NMTOKEN #REQUIRED>
+<!ELEMENT value-storages (value-storage+)>
+<!ELEMENT value-storage (properties,filters)>
+<!ATTLIST value-storage class NMTOKEN #REQUIRED>
+<!ELEMENT filters (filter+)>
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter property-type NMTOKEN #REQUIRED>
+<!ELEMENT initializer (properties)>
+<!ATTLIST initializer class NMTOKEN #REQUIRED>
+<!ELEMENT cache (properties)>
+<!ATTLIST cache
+ enabled NMTOKEN #REQUIRED
+ class NMTOKEN #REQUIRED
+>
+<!ELEMENT query-handler (properties)>
+<!ATTLIST query-handler class NMTOKEN #REQUIRED>
+<!ELEMENT access-manager (properties)>
+<!ATTLIST access-manager class NMTOKEN #REQUIRED>
+<!ELEMENT lock-manager (time-out,persister)>
+<!ELEMENT time-out (#PCDATA)>
+<!ELEMENT persister (properties)>
+<!ELEMENT properties (property+)>
+<!ELEMENT property EMPTY></programlisting>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/external-value-storages.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/external-value-storages.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/external-value-storages.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.ExternalValueStorages">
+ <?dbhtml filename="ch-jcr-external-value-storages.html"?>
+
+ <title>External Value Storages</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>By default JCR Values are stored in the Workspace Data container
+ along with the JCR structure (i.e. Nodes and Properties). eXo JCR offers
+ an additional option of storing JCR Values separately from Workspace Data
+ container, which can be extremely helpful to keep Binary Large Objects
+ (BLOBs) for example (see [TODO<link linkend="TODO"> Binary values
+ processing</link>]).</para>
+
+ <para>Value storage configuration is a part of Repository configuration,
+ find more details <link
+
linkend="JCR.ConfigurationPersister.ValueStoragePlugin">there</link>.</para>
+
+ <para>Tree-based storage is recommended for most of cases. If you run an
+ application on Amazon EC2 - the S3 option may be interesting for
+ architecture. Simple 'flat' storage is good in speed of creation/deletion
+ of values, it might be a compromise for a small storages.</para>
+ </section>
+
+ <section>
+ <title>Tree File Value Storage</title>
+
+ <para>Holds Values in tree-like FileSystem files.
+ <property>path</property> property points to the root directory to store
+ the files.</para>
+
+ <para>This is a recommended type of external storage, it can contain large
+ amount of files limited only by disk/volume free space.</para>
+
+ <para>A disadvantage it's a higher time on Value deletion due to unused
+ tree-nodes remove.</para>
+
+ <programlisting><value-storage id="Storage #1"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+ <properties>
+ <property name="path" value="data/values"/>
+ </properties>
+ <filters>
+ <filter property-type="Binary"
min-value-size="1M"/>
+ </filters></programlisting>
+
+ <para>Where :<simplelist>
+ <member><parameter>id</parameter> - the value storage unique
+ identifier, used for linking with properties stored in workspace
+ container</member>
+
+ <member><parameter>path</parameter> - a location where value
files
+ will be stored</member>
+ </simplelist></para>
+
+ <para>Each file value storage can have the
<function>filter(s)</function>
+ for incoming values. A filter can match values by property type
+ (<property>property-type</property>), property name
+ (<property>property-name</property>), ancestor path
+ (<property>ancestor-path</property>) and/or size of values stored
+ (<property>min-value-size</property>, in bytes). In code sample we use a
+ filter with property-type and min-value-size only. I.e. storage for binary
+ values with size greater of 1MB. It's recommended to store properties with
+ large values in file value storage only.</para>
+
+ <para>Another example shows a value storage with different locations for
+ large files (<property>min-value-size</property> a 20Mb-sized filter). A
+ value storage uses ORed logic in the process of filter selection. That
+ means the first filter in the list will be asked first and if not matched
+ the next will be called etc. Here a value matches the 20 MB-sized filter
+ <property>min-value-size</property> and will be stored in the path
+ "data/20Mvalues", all other in "data/values".</para>
+
+ <programlisting><value-storages>
+ <value-storage id="Storage #1"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+ <properties>
+ <property name="path" value="data/20Mvalues"/>
+ </properties>
+ <filters>
+ <filter property-type="Binary"
min-value-size="20M"/>
+ </filters>
+ <value-storage>
+ <value-storage id="Storage #2"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+ <properties>
+ <property name="path" value="data/values"/>
+ </properties>
+ <filters>
+ <filter property-type="Binary"
min-value-size="1M"/>
+ </filters>
+ <value-storage>
+<value-storages></programlisting>
+ </section>
+
+ <section>
+ <title>Simple File Value Storage</title>
+
+ <note>
+ <para>Not recommended to use in production due to low capacity
+ capabilities on most file systems.</para>
+
+ <para>But if you're sure in your file-system or data amount is small it
+ may be useful for you as haves a faster speed of Value removal.</para>
+ </note>
+
+ <para>Holds Values in flat FileSystem files.
<property>path</property>
+ property points to root directory in order to store files</para>
+
+ <programlisting><value-storage id="Storage #1"
class="org.exoplatform.services.jcr.impl.storage.value.fs.SimpleFileValueStorage">
+ <properties>
+ <property name="path" value="data/values"/>
+ </properties>
+ <filters>
+ <filter property-type="Binary"
min-value-size="1M"/>
+ </filters></programlisting>
+ </section>
+
+ <section>
+ <title>Content Addressable Value storage (CAS) support</title>
+
+ <para>eXo JCR supports <phrase>Content-addressable
storage</phrase>
+ feature for <phrase>Values</phrase> storing.</para>
+
+ <note>
+ <para>Content-addressable storage, also referred to as associative
+ storage and abbreviated CAS, is a mechanism for storing information that
+ can be retrieved based on its content, not its storage location. It is
+ typically used for high-speed storage and retrieval of fixed content,
+ such as documents stored for compliance with government
+ regulations.</para>
+ </note>
+
+ <para>Content Addressable Value storage stores unique content once.
+ Different properties (values) with same content will be stored as one data
+ file shared between those values. We can tell the Value content will be
+ shared across some Values in storage and will be stored on one physical
+ file.</para>
+
+ <para>Storage size will be decreased for application which governs
+ potentially same data in the content.</para>
+
+ <note>
+ <para>For example: if you have 100 different properties containing the
+ same data (e.g. mail attachment) the storage stores only one single
+ file. The file will be shared with all referencing properties.</para>
+ </note>
+
+ <para>If property Value changes it is stored in an additional file.
+ Alternatively the file is shared with other values, pointing to the same
+ content.</para>
+
+ <para>The storage calculates Value content address each time the property
+ was changed. CAS write operations are much more expensive compared to the
+ non-CAS storages.</para>
+
+ <para>Content address calculation based on java.security.MessageDigest
+ hash computation and tested with <abbrev>MD5</abbrev> and
+ <abbrev>SHA1</abbrev> algorithms.</para>
+
+ <note>
+ <para>CAS storage works most efficiently on data that does not change
+ often. For data that changes frequently, CAS is not as efficient as
+ location-based addressing.</para>
+ </note>
+
+ <para>CAS support can be enabled for <phrase>Tree</phrase> and
+ <phrase>Simple File Value Storage</phrase> types.</para>
+
+ <para>To enable CAS support just configure it in JCR Repositories
+ configuration like we do for other Value Storages.</para>
+
+ <programlisting><workspaces>
+ <workspace name="ws">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name"
value="jdbcjcr"/>
+ <property name="dialect"
value="oracle"/>
+ <property name="multi-db"
value="false"/>
+ <property name="update-storage"
value="false"/>
+ <property name="max-buffer-size"
value="200k"/>
+ <property name="swap-directory"
value="target/temp/swap/ws"/>
+ </properties>
+ <value-storages>
+<!------------------- here ----------------------->
+ <value-storage id="ws"
class="org.exoplatform.services.jcr.impl.storage.value.fs.CASableTreeFileValueStorage">
+ <properties>
+ <property name="path"
value="target/temp/values/ws"/>
+ <property name="digest-algo"
value="MD5"/>
+ <property name="vcas-type"
value="org.exoplatform.services.jcr.impl.storage.value.cas.JDBCValueContentAddressStorageImpl"/>
+ <property name="jdbc-source-name"
value="jdbcjcr"/>
+ <property name="jdbc-dialect"
value="oracle"/>
+ </properties>
+ <filters>
+ <filter property-type="Binary"/>
+ </filters>
+ </value-storage>
+ </value-storages></programlisting>
+
+ <para>Properties:<simplelist>
+ <member><parameter>digest-algo</parameter> - digest hash
algorithm
+ (MD5 and SHA1 were tested);</member>
+
+ <member><parameter>vcas-type</parameter> - Value CAS internal
data
+ type, JDBC backed is currently implemented
+
org.exoplatform.services.jcr.impl.storage.value.cas.JDBCValueContentAddressStorageImp;l</member>
+
+ <member><parameter>jdbc-source-name</parameter> -
+ JDBCValueContentAddressStorageImpl specific parameter, database will
+ be used to save CAS metadata. It's simple to use same as in workspace
+ container;</member>
+
+ <member><parameter>jdbc-dialect</parameter> -
+ JDBCValueContentAddressStorageImpl specific parameter, database
+ dialect. It's simple to use same as in workspace container;</member>
+ </simplelist></para>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,592 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="ch_jdbc_data_container">
+ <?dbhtml filename="ch-jdbc-data-container-config.html"?>
+
+ <title>JDBC Data Container Config</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>eXo JCR persistent data container can work in two configuration
+ modes:<itemizedlist>
+ <listitem>
+ <para><phrase>Multi-database</phrase>: one database for each
+ workspace (used in standalone eXo JCR service mode)</para>
+ </listitem>
+
+ <listitem>
+ <para><phrase>Single-database</phrase>: all workspaces
persisted in
+ one database (used in embedded eXo JCR service mode, e.g. in eXo
+ portal)</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>The data container uses the JDBC driver to communicate with the
+ actual database software, i.e. any JDBC-enabled data storage can be used
+ with eXo JCR implementation.</para>
+
+ <para>Currently the data container is tested with the following
+ RDBMS:<itemizedlist>
+ <listitem>
+ <para>MySQL (5.x including UTF8 support)</para>
+ </listitem>
+
+ <listitem>
+ <para>PostgreSQL (8.x)</para>
+ </listitem>
+
+ <listitem>
+ <para>Oracle Database (9i, 10g)</para>
+ </listitem>
+
+ <listitem>
+ <para>Microsoft SQL Server (2005)</para>
+ </listitem>
+
+ <listitem>
+ <para>Sybase ASE (15.0)</para>
+ </listitem>
+
+ <listitem>
+ <para>Apache Derby/Java DB (10.1.x, 10.2.x)</para>
+ </listitem>
+
+ <listitem>
+ <para>IBM DB2 (8.x, 9.x)</para>
+ </listitem>
+
+ <listitem>
+ <para>HSQLDB (1.8.0.7)</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>Each database software supports ANSI SQL standards but has its own
+ specifics too. So, each database has its own configuration in eXo JCR as a
+ database dialect parameter. If you need a more detailed configuration of
+ the database it's possible to do that by editing the metadata SQL-script
+ files.</para>
+
+ <para>In case the non-ANSI node name is used it's necessary to use a
+ database with MultiLanguage support[TODO link to MultiLanguage]. Some JDBC
+ drivers need additional parameters for establishing a Unicode friendly
+ connection. E.g. under mysql it's necessary to add an additional parameter
+ for the JDBC driver at the end of JDBC URL. For instance:
+
<
code>jdbc:mysql://exoua.dnsalias.net/portal?characterEncoding=utf8<...
+
+ <para>There are preconfigured configuration files for HSQLDB. Look for
+ these files in /conf/portal and /conf/standalone folders of the jar-file
+ <package>exo.jcr.component.core-XXX.XXX.jar</package> or
+ source-distribution of eXo JCR implementation.</para>
+
+ <para>By default the configuration files are located in service jars
+ <filename>/conf/portal/configuration.xml</filename> (eXo services
+ including JCR Repository Service) and
+ <filename>exo-jcr-config.xml</filename> (repositories configuration). In
+ eXo portal product JCR is configured in portal web application
+ <filename>portal/WEB-INF/conf/jcr/jcr-configuration.xml</filename> (JCR
+ Repository Service and related serivces) and repository-configuration.xml
+ (repositories configuration).</para>
+
+ <para>Read more about <link
linkend="ch_configuration">Repository
+ configuration</link>.</para>
+ </section>
+
+ <section>
+ <title>Multi-database Configuration</title>
+
+ <para>You need to configure each workspace in a repository. You may have
+ each one on different remote servers as far as you need.</para>
+
+ <para>First of all configure the data containers in the
+
<classname>org.exoplatform.services.naming.InitialContextInitializer</classname>
+ service. It's the JNDI context initializer which registers (binds) naming
+ resources (DataSources) for data containers.</para>
+
+ <para>Example (standalone mode, two data containers
+ <parameter>jdbcjcr</parameter> - local HSQLDB,
+ <parameter>jdbcjcr1</parameter> - remote
MySQL):<programlisting><component>
+
<key>org.exoplatform.services.naming.InitialContextInitializer</key>
+
<type>org.exoplatform.services.naming.InitialContextInitializer</type>
+ <component-plugins>
+ <component-plugin>
+ <name>bind.datasource</name>
+ <set-method>addPlugin</set-method>
+
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
+ <init-params>
+ <value-param>
+ <name>bind-name</name>
+ <value>jdbcjcr</value>
+ </value-param>
+ <value-param>
+ <name>class-name</name>
+ <value>javax.sql.DataSource</value>
+ </value-param>
+ <value-param>
+ <name>factory</name>
+
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
+ </value-param>
+ <properties-param>
+ <name>ref-addresses</name>
+ <description>ref-addresses</description>
+ <property name="driverClassName"
value="org.hsqldb.jdbcDriver"/>
+ <property name="url"
value="jdbc:hsqldb:file:target/temp/data/portal"/>
+ <property name="username" value="sa"/>
+ <property name="password" value=""/>
+ </properties-param>
+ </init-params>
+ </component-plugin>
+ <component-plugin>
+ <name>bind.datasource</name>
+ <set-method>addPlugin</set-method>
+
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
+ <init-params>
+ <value-param>
+ <name>bind-name</name>
+ <value>jdbcjcr1</value>
+ </value-param>
+ <value-param>
+ <name>class-name</name>
+ <value>javax.sql.DataSource</value>
+ </value-param>
+ <value-param>
+ <name>factory</name>
+
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
+ </value-param>
+ <properties-param>
+ <name>ref-addresses</name>
+ <description>ref-addresses</description>
+ <property name="driverClassName"
value="com.mysql.jdbc.Driver"/>
+ <property name="url"
value="jdbc:mysql://exoua.dnsalias.net/jcr"/>
+ <property name="username"
value="exoadmin"/>
+ <property name="password"
value="exo12321"/>
+ <property name="maxActive" value="50"/>
+ <property name="maxIdle" value="5"/>
+ <property name="initialSize" value="5"/>
+ </properties-param>
+ </init-params>
+ </component-plugin>
+ <component-plugins>
+ <init-params>
+ <value-param>
+ <name>default-context-factory</name>
+
<value>org.exoplatform.services.naming.SimpleContextFactory</value>
+ </value-param>
+ </init-params>
+ </component></programlisting></para>
+
+ <para>We configure the database connection parameters:<itemizedlist>
+ <listitem>
+ <para><parameter>driverClassName</parameter>, e.g.
+ "org.hsqldb.jdbcDriver", "com.mysql.jdbc.Driver",
+ "org.postgresql.Driver"</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>url</parameter>, e.g.
+ "jdbc:hsqldb:file:target/temp/data/portal",
+ "jdbc:mysql://exoua.dnsalias.net/jcr"</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>username</parameter>, e.g. "sa",
"exoadmin"</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>password</parameter>, e.g. "",
"exo12321"</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>There can be connection pool configuration parameters
+ (org.apache.commons.dbcp.BasicDataSourceFactory):<itemizedlist>
+ <listitem>
+ <para><parameter>maxActive</parameter>, e.g. 50</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>maxIdle</parameter>, e.g. 5</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>initialSize</parameter>, e.g.
5</para>
+ </listitem>
+
+ <listitem>
+ <para>and other according to <ulink
+
url="http://jakarta.apache.org/commons/dbcp/configuration.html"...
+ DBCP configuration</ulink></para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>When the data container configuration is done we can configure the
+ repository service. Each workspace will be configured for its own data
+ container.</para>
+
+ <para>Example (two workspaces <parameter>ws</parameter> - jdbcjcr,
+ <parameter>ws1</parameter> -
jdbcjcr1):<programlisting><workspaces>
+ <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr"/>
+ <property name="dialect" value="hsqldb"/>
+ <property name="multi-db" value="true"/>
+ <property name="max-buffer-size" value="200K"/>
+ <property name="swap-directory"
value="target/temp/swap/ws"/>
+ </properties>
+ </container>
+ <cache enabled="true">
+ <properties>
+ <property name="max-size"
value="10K"/><!-- 10Kbytes -->
+ <property name="live-time"
value="30m"/><!-- 30 min -->
+ </properties>
+ </cache>
+ <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+ <properties>
+ <property name="index-dir"
value="target/temp/index"/>
+ </properties>
+ </query-handler>
+ <lock-manager>
+ <time-out>15m</time-out><!-- 15 min -->
+ <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
+ <properties>
+ <property name="path"
value="target/temp/lock/ws"/>
+ </properties>
+ </persister>
+ </lock-manager>
+ </workspace>
+ <workspace name="ws1"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr1"/>
+ <property name="dialect" value="mysql"/>
+ <property name="multi-db" value="true"/>
+ <property name="max-buffer-size" value="200K"/>
+ <property name="swap-directory"
value="target/temp/swap/ws1"/>
+ </properties>
+ </container>
+ <cache enabled="true">
+ <properties>
+ <property name="max-size" value="10K"/>
+ <property name="live-time" value="5m"/>
+ </properties>
+ </cache>
+ <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+ <properties>
+ <property name="index-dir"
value="target/temp/index"/>
+ </properties>
+ </query-handler>
+ <lock-manager>
+ <time-out>15m</time-out><!-- 15 min -->
+ <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
+ <properties>
+ <property name="path"
value="target/temp/lock/ws1"/>
+ </properties>
+ </persister>
+ </lock-manager>
+ </workspace>
+</workspaces></programlisting><itemizedlist>
+ <listitem>
+ <para><parameter>source-name</parameter> - a
javax.sql.DataSource
+ name configured in InitialContextInitializer component (was
+ <parameter>sourceName</parameter> prior JCR 1.9);</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>dialect</parameter> - a database dialect,
one of
+ "hsqldb", "mysql", "mysql-utf8",
"pgsql", "oracle", "oracle-oci",
+ "mssql", "sybase", "derby", "db2",
"db2v8" or "auto" for dialect
+ autodetection;</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>multi-db</parameter> - enable
multi-database
+ container with this parameter (set value "true");</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>max-buffer-size</parameter> - a threshold
(in
+ bytes) after which a javax.jcr.Value content will be swapped to a
+ file in a temporary storage. I.e. swap for pending changes.</para>
+ </listitem>
+
+ <listitem>
+ <para><parameter>swap-directory</parameter> - a path in the
file
+ system used to swap the pending changes.</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>In this way we have configured two workspace which will be persisted
+ in two different databases (ws in HSQLDB, ws1 in MySQL).</para>
+
+ <note>
+ <para>Starting from v.1.9 <link
linkend="ch_configuration">repository
+ configuration</link> parameters supports human-readable formats of
+ values (e.g. 200K - 200 Kbytes, 30m - 30 minutes etc)</para>
+ </note>
+ </section>
+
+ <section>
+ <title>Single-database configuration</title>
+
+ <para>It's more simple to configure a single-database data container. We
+ have to configure one naming resource.</para>
+
+ <para>Example (embedded mode for <parameter>jdbcjcr</parameter>
data
+ container):<programlisting><external-component-plugins>
+
<target-component>org.exoplatform.services.naming.InitialContextInitializer</target-component>
+ <component-plugin>
+ <name>bind.datasource</name>
+ <set-method>addPlugin</set-method>
+
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
+ <init-params>
+ <value-param>
+ <name>bind-name</name>
+ <value>jdbcjcr</value>
+ </value-param>
+ <value-param>
+ <name>class-name</name>
+ <value>javax.sql.DataSource</value>
+ </value-param>
+ <value-param>
+ <name>factory</name>
+
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
+ </value-param>
+ <properties-param>
+ <name>ref-addresses</name>
+ <description>ref-addresses</description>
+ <property name="driverClassName"
value="org.postgresql.Driver"/>
+ <property name="url"
value="jdbc:postgresql://exoua.dnsalias.net/portal"/>
+ <property name="username"
value="exoadmin"/>
+ <property name="password"
value="exo12321"/>
+ <property name="maxActive" value="50"/>
+ <property name="maxIdle" value="5"/>
+ <property name="initialSize" value="5"/>
+ </properties-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins></programlisting></para>
+
+ <para>And configure repository workspaces in repositories configuration
+ with this one database. Parameter "multi-db" must be switched off (set
+ value "false").</para>
+
+ <para>Example (two workspaces <parameter>ws</parameter> - jdbcjcr,
+ <parameter>ws1</parameter> -
jdbcjcr):<programlisting><workspaces>
+ <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr"/>
+ <property name="dialect" value="pgsql"/>
+ <property name="multi-db" value="false"/>
+ <property name="max-buffer-size" value="200K"/>
+ <property name="swap-directory"
value="target/temp/swap/ws"/>
+ </properties>
+ </container>
+ <cache enabled="true">
+ <properties>
+ <property name="max-size" value="10K"/>
+ <property name="live-time" value="30m"/>
+ </properties>
+ </cache>
+ <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+ <properties>
+ <property name="index-dir"
value="../temp/index"/>
+ </properties>
+ </query-handler>
+ <lock-manager>
+ <time-out>15m</time-out>
+ <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
+ <properties>
+ <property name="path"
value="target/temp/lock/ws"/>
+ </properties>
+ </persister>
+ </lock-manager>
+ </workspace>
+ <workspace name="ws1"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr"/>
+ <property name="dialect" value="pgsql"/>
+ <property name="multi-db" value="false"/>
+ <property name="max-buffer-size" value="200K"/>
+ <property name="swap-directory"
value="target/temp/swap/ws1"/>
+ </properties>
+ </container>
+ <cache enabled="true">
+ <properties>
+ <property name="max-size" value="10K"/>
+ <property name="live-time" value="5m"/>
+ </properties>
+ </cache>
+ <lock-manager>
+ <time-out>15m</time-out>
+ <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
+ <properties>
+ <property name="path"
value="target/temp/lock/ws1"/>
+ </properties>
+ </persister>
+ </lock-manager>
+ </workspace>
+</workspaces></programlisting></para>
+
+ <para>In this way we have configured two workspaces which will be
+ persisted in one database (PostgreSQL).</para>
+
+ <section>
+ <title>Configuration without DataSource</title>
+
+ <para>Repository configuration without using of the
+ <classname>javax.sql.DataSource</classname> bounded in
JNDI.</para>
+
+ <para>This case may be usable if you have a dedicated JDBC driver
+ implementation with special features like XA transactions,
+ statements/connections pooling etc:<itemizedlist>
+ <listitem>
+ <para>You have to remove the configuration in
+ <classname>InitialContextInitializer</classname> for your
database
+ and configure a new one directly in the workspace
+ container.</para>
+ </listitem>
+
+ <listitem>
+ <para>Remove parameter "source-name" and add next lines
instead.
+ Describe your values for a JDBC driver, database url and
+ username.</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <note>
+ <para>But be careful in this case JDBC driver should implement and
+ provide connection pooling. Connection pooling is very recommended for
+ use with JCR to prevent a database overload.</para>
+ </note>
+
+ <programlisting><workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="dialect" value="hsqldb"/>
+ <property name="driverClassName"
value="org.hsqldb.jdbcDriver"/>
+ <property name="url"
value="jdbc:hsqldb:file:target/temp/data/portal"/>
+ <property name="username" value="su"/>
+ <property name="password" value=""/>
+ ......</programlisting>
+ </section>
+
+ <section>
+ <title>Dynamic Workspace Creation</title>
+
+ <para>Workspaces can be added dynamically during runtime.</para>
+
+ <para>This can be performed in two steps:<itemizedlist>
+ <listitem>
+ <para>Firstly,
+ <classname>ManageableRepository.configWorkspace(WorkspaceEntry
+ wsConfig)</classname> - register a new configuration in
+ RepositoryContainer and create a WorkspaceContainer.</para>
+ </listitem>
+
+ <listitem>
+ <para>Secondly, the main step,
+ <classname>ManageableRepository.createWorkspace(String
+ workspaceName)</classname> - creation of a new workspace.</para>
+ </listitem>
+ </itemizedlist></para>
+ </section>
+ </section>
+
+ <section>
+ <title>Simple and Complex queries</title>
+
+ <para>eXo JCR provides two ways for interact with Database -
+ <classname>JDBCStorageConnection</classname> that uses simple queries
and
+ <classname>CQJDBCStorageConection</classname> that uses complex queries
+ for reducing amount of database callings.</para>
+
+ <para>Simple queries will be used if you chose
+
<classname>org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer</classname>:<programlisting><workspaces>
+ <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ ...
+ </workspace>
+</worksapces></programlisting></para>
+
+ <para>Complex queries will be used if you chose
+
<classname>org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer</classname>:<programlisting><workspaces>
+ <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+ ...
+ </workspace>
+</worksapces></programlisting></para>
+
+ <para>Why we should use a Complex Queries?<simplelist>
+ <member>They are optimised to reduce amount of requests to
+ database.</member>
+ </simplelist>Why we should use a Simple Queries?<simplelist>
+ <member>Simple queries implemented in way to support as many database
+ dialects as possible.</member>
+
+ <member>Simple queries do not use sub queries, left or right
+ joins.</member>
+ </simplelist></para>
+ </section>
+
+ <section>
+ <title>Forse Query Hints</title>
+
+ <para>Some databases supports hints to increase query performance (like
+ Oracle, MySQL, etc). eXo JCR have separate Complex Query implementation
+ for Orcale dialect, that uses query hints to increase performance for few
+ important queries.</para>
+
+ <para>To enable this option put next configuration
+ property:<programlisting><workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="dialect" value="oracle"/>
+ <property name="force.query.hints" value="true"
/>
+ ......</programlisting></para>
+
+ <para>Query hints enabled by default.</para>
+
+ <para>eXo JCR uses query hints only for Complex Query Oracle dialect. For
+ all other dialects this parameter is ignored.</para>
+ </section>
+
+ <section>
+ <title>Notes for Microsoft Windows users</title>
+
+ <para>The current configuration of eXo JCR uses <ulink
+
url="http://commons.apache.org/dbcp/">Apache DBCP</ulink>
connection pool
+ (<classname>org.apache.commons.dbcp.BasicDataSourceFactory</classname>).
+ It's possible to set a big value for maxActive parameter in
+ <filename>configuration.xml</filename>. That means usage of lots of
TCP/IP
+ ports from a client machine inside the pool (i.e. JDBC driver). As a
+ result the data container can throw exceptions like "Address already in
+ use". To solve this problem you have to configure the client's machine
+ networking software for the usage of shorter timeouts for opened TCP/IP
+ ports.</para>
+
+ <para>Microsoft Windows has <parameter>MaxUserPort</parameter>,
+ <parameter>TcpTimedWaitDelay</parameter> registry keys in the node
+
<parameter>HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters</parameter>,
+ by default these keys are unset, set each one with values like
+ these:<itemizedlist>
+ <listitem>
+ <para>"TcpTimedWaitDelay"=dword:0000001e, sets TIME_WAIT
parameter
+ to 30 seconds, default is 240.</para>
+ </listitem>
+
+ <listitem>
+ <para>"MaxUserPort"=dword:00001b58, sets the maximum of open
ports
+ to 7000 or higher, default is 5000.</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>A sample registry file is below:<programlisting>Windows Registry
Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
+"MaxUserPort"=dword:00001b58
+"TcpTimedWaitDelay"=dword:0000001e</programlisting></para>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/multilanguage-support.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/multilanguage-support.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/multilanguage-support.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="ch_multilanguage_support">
+ <?dbhtml filename="ch-multilanguage-support.html"?>
+
+ <title>Multilanguage support in eXo JCR RDB backend</title>
+
+ <section>
+ <title>Intro</title>
+
+ <para>Whenever relational database is used to store multilingual text data
+ of eXo Java Content Repository we need to adapt configuration in order to
+ support UTF-8 encoding. Here is a short HOWTO instruction for several
+ supported RDBMS with examples.</para>
+
+ <para>The configuration file you have to modify:
+ .../webapps/portal/WEB-INF/conf/jcr/repository-configuration.xml</para>
+
+ <note>
+ <para>Datasource <parameter>jdbcjcr</parameter> used in examples
can be
+ configured via <classname>InitialContextInitializer</classname>
+ component.</para>
+ </note>
+ </section>
+
+ <section>
+ <title>Oracle</title>
+
+ <para>In order to run multilanguage JCR on an Oracle backend Unicode
+ encoding for characters set should be applied to the database. Other
+ Oracle globalization parameters don't make any impact. The only property
+ to modify is <constant>NLS_CHARACTERSET</constant>.</para>
+
+ <para>We have tested <constant>NLS_CHARACTERSET</constant> =
+ <constant>AL32UTF8</constant> and it's works well for many European
and
+ Asian languages.</para>
+
+ <para>Example of database configuration (used for JCR
+ testing):<programlisting>NLS_LANGUAGE AMERICAN
+NLS_TERRITORY AMERICA
+NLS_CURRENCY $
+NLS_ISO_CURRENCY AMERICA
+NLS_NUMERIC_CHARACTERS .,
+NLS_CHARACTERSET AL32UTF8
+NLS_CALENDAR GREGORIAN
+NLS_DATE_FORMAT DD-MON-RR
+NLS_DATE_LANGUAGE AMERICAN
+NLS_SORT BINARY
+NLS_TIME_FORMAT HH.MI.SSXFF AM
+NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
+NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
+NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
+NLS_DUAL_CURRENCY $
+NLS_COMP BINARY
+NLS_LENGTH_SEMANTICS BYTE
+NLS_NCHAR_CONV_EXCP FALSE
+NLS_NCHAR_CHARACTERSET AL16UTF16</programlisting></para>
+
+ <warning>
+ <para>JCR 1.12.x doesn't use NVARCHAR columns, so that the value of the
+ parameter NLS_NCHAR_CHARACTERSET does not matter for JCR.</para>
+ </warning>
+
+ <para>Create database with Unicode encoding and use Oracle dialect for the
+ Workspace Container:</para>
+
+ <programlisting><workspace name="collaboration">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr"
/>
+ <property name="dialect" value="oracle"
/>
+ <property name="multi-db" value="false"
/>
+ <property name="max-buffer-size" value="200k"
/>
+ <property name="swap-directory"
value="target/temp/swap/ws" />
+ </properties>
+ .....</programlisting>
+ </section>
+
+ <section>
+ <title>DB2</title>
+
+ <para>DB2 Universal Database (DB2 UDB) supports <ulink
+
url="http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?to...
+ and UTF-16/UCS-2</ulink>. When a Unicode database is created, CHAR,
+ VARCHAR, LONG VARCHAR data are stored in UTF-8 form. It's enough for JCR
+ multi-lingual support.</para>
+
+ <para>Example of UTF-8 database creation:<programlisting>DB2 CREATE
DATABASE dbname USING CODESET UTF-8 TERRITORY US</programlisting></para>
+
+ <para>Create database with UTF-8 encoding and use db2 dialect for
+ Workspace Container on DB2 v.9 and higher:<programlisting><workspace
name="collaboration">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr"
/>
+ <property name="dialect" value="db2" />
+ <property name="multi-db" value="false"
/>
+ <property name="max-buffer-size" value="200k"
/>
+ <property name="swap-directory"
value="target/temp/swap/ws" />
+ </properties>
+ .....</programlisting></para>
+
+ <note>
+ <para>For DB2 v.8.x support change the property "dialect" to
+ db2v8.</para>
+ </note>
+ </section>
+
+ <section>
+ <title>MySQL</title>
+
+ <para>JCR MySQL-backend requires special dialect <ulink
+
url="http://jira.exoplatform.org/browse/JCR-375">MySQL-UTF8&... to
be
+ used for internationalization support. But the database default charset
+ should be latin1 to use limited index space effectively (1000 bytes for
+ MyISAM engine, 767 for InnoDB). If database default charset is multibyte,
+ a JCR database initialization error is thrown concerning index creation
+ failure. In other words JCR can work on any singlebyte default charset of
+ database, with UTF8 supported by MySQL server. But we have tested it only
+ on latin1 database default charset.</para>
+
+ <para>Repository configuration, workspace container entry
+ example:<programlisting><workspace
name="collaboration">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr"
/>
+ <property name="dialect" value="mysql-utf8"
/>
+ <property name="multi-db" value="false"
/>
+ <property name="max-buffer-size" value="200k"
/>
+ <property name="swap-directory"
value="target/temp/swap/ws" />
+ </properties>
+ .....</programlisting></para>
+ </section>
+
+ <section>
+ <title>PostgreSQL</title>
+
+ <para>On PostgreSQL-backend multilingual support can be enabled in <ulink
+
url="http://www.postgresql.org/docs/8.3/interactive/charset.html&quo...
+ ways</ulink>:<itemizedlist>
+ <listitem>
+ <para>Using the locale features of the operating system to provide
+ locale-specific collation order, number formatting, translated
+ messages, and other aspects. UTF-8 is widely used on Linux
+ distributions by default, so it can be useful in such case.</para>
+ </listitem>
+
+ <listitem>
+ <para>Providing a number of different character sets defined in the
+ PostgreSQL server, including multiple-byte character sets, to
+ support storing text any language, and providing character set
+ translation between client and server. We recommend to use UTF-8
+ database charset, it will allow any-to-any conversations and make
+ this issue transparent for the JCR.</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>Create database with UTF-8 encoding and use PgSQL dialect for
+ Workspace Container:<programlisting><workspace
name="collaboration">
+ <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr"
/>
+ <property name="dialect" value="pgsql"
/>
+ <property name="multi-db" value="false"
/>
+ <property name="max-buffer-size" value="200k"
/>
+ <property name="swap-directory"
value="target/temp/swap/ws" />
+ </properties>
+ .....</programlisting></para>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/rest-services-on-groovy.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/rest-services-on-groovy.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/rest-services-on-groovy.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,53 @@
+<?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.RESTServicesOnGroovy">
+ <?dbhtml filename="ch-jcr-rest-services-on-groovy.html"?>
+
+ <title>REST Services on Groovy</title>
+
+ <section>
+ <title>Concept</title>
+
+ <para>Starting from version 1.9 JCR Service supports REST services
+ creation on <ulink url="http://groovy.codehaus.org">Groovy
+ script</ulink>.</para>
+
+ <para>The feature based on <link
linkend="WS.RestFramework">RESTful
+ framework</link> and uses ResourceContainer concept.</para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <para>Scripts should extend ResourceContainer and should be stored in JCR
+ as a node of type exo:groovyResourceContainer.</para>
+
+ <para>Detailed REST services step-by-step implementation check there <link
+ linkend="WS.RestServiceTutorial">Create REST service step by
+ step</link>.</para>
+
+ <para>Component configuration enables Groovy services loader:</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader</type>
+ <init-params>
+ <object-param>
+ <name>observation.config</name>
+ <object
type="org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader$ObservationListenerConfiguration">
+ <field name="repository">
+ <string>repository</string>
+ </field>
+ <field name="workspaces">
+ <collection type="java.util.ArrayList">
+ <value>
+ <string>collaboration</string>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+</component></programlisting>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/search-configuration.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/search-configuration.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/search-configuration.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,818 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.SearchConfiguration">
+ <?dbhtml filename="ch-jcr-search-configuration.html"?>
+
+ <title>Search Configuration</title>
+
+ <section>
+ <title>XML Configuration</title>
+
+ <para>JCR index configuration. You can find this file here:
+
<filename>.../portal/WEB-INF/conf/jcr/repository-configuration.xml</filename></para>
+
+ <programlisting><repository-service
default-repository="db1">
+ <repositories>
+ <repository name="db1" system-workspace="ws"
default-workspace="ws">
+ ....
+ <workspaces>
+ <workspace name="ws">
+ ....
+ <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+ <properties>
+ <property name="index-dir"
value="${java.io.tmpdir}/temp/index/db1/ws" />
+ <property name="synonymprovider-class"
value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider"
/>
+ <property name="synonymprovider-config-path"
value="/synonyms.properties" />
+ <property name="indexing-config-path"
value="/indexing-configuration.xml" />
+ <property name="query-class"
value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+ </properties>
+ </query-handler>
+ ...
+ </workspace>
+ </workspaces>
+ </repository>
+ </repositories>
+</repository-service></programlisting>
+ </section>
+
+ <section>
+ <title>Configuration parameters</title>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Parameter</entry>
+
+ <entry>Default</entry>
+
+ <entry>Description</entry>
+
+ <entry>Since</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>index-dir</entry>
+
+ <entry>none</entry>
+
+ <entry>The location of the index directory. This parameter is
+ mandatory. Up to 1.9 this parameter called
"indexDir"</entry>
+
+ <entry>1.0</entry>
+ </row>
+
+ <row>
+ <entry>use-compoundfile</entry>
+
+ <entry>true</entry>
+
+ <entry>Advises lucene to use compound files for the index
+ files.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>min-merge-docs</entry>
+
+ <entry>100</entry>
+
+ <entry>Minimum number of nodes in an index until segments are
+ merged.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>volatile-idle-time</entry>
+
+ <entry>3</entry>
+
+ <entry>Idle time in seconds until the volatile index part is moved
+ to a persistent index even though minMergeDocs is not
+ reached.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>max-merge-docs</entry>
+
+ <entry>Integer.MAX_VALUE</entry>
+
+ <entry>Maximum number of nodes in segments that will be merged.
+ The default value changed in JCR 1.9 to Integer.MAX_VALUE.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>merge-factor</entry>
+
+ <entry>10</entry>
+
+ <entry>Determines how often segment indices are merged.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>max-field-length</entry>
+
+ <entry>10000</entry>
+
+ <entry>The number of words that are fulltext indexed at most per
+ property.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>cache-size</entry>
+
+ <entry>1000</entry>
+
+ <entry>Size of the document number cache. This cache maps uuids to
+ lucene document numbers</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>force-consistencycheck</entry>
+
+ <entry>false</entry>
+
+ <entry>Runs a consistency check on every startup. If false, a
+ consistency check is only performed when the search index detects
+ a prior forced shutdown.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>auto-repair</entry>
+
+ <entry>true</entry>
+
+ <entry>Errors detected by a consistency check are automatically
+ repaired. If false, errors are only written to the log.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>query-class</entry>
+
+ <entry>QueryImpl</entry>
+
+ <entry>Class name that implements the javax.jcr.query.Query
+ interface.This class must also extend from the class:
+
org.exoplatform.services.jcr.impl.core.query.AbstractQueryImpl.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>document-order</entry>
+
+ <entry>true</entry>
+
+ <entry>If true and the query does not contain an 'order by'
+ clause, result nodes will be in document order. For better
+ performance when queries return a lot of nodes set to
+ 'false'.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>result-fetch-size</entry>
+
+ <entry>Integer.MAX_VALUE</entry>
+
+ <entry>The number of results when a query is executed. Default
+ value: Integer.MAX_VALUE (-> all).</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>excerptprovider-class</entry>
+
+ <entry>DefaultXMLExcerpt</entry>
+
+ <entry>The name of the class that implements
+ org.exoplatform.services.jcr.impl.core.query.lucene.ExcerptProvider
+ and should be used for the rep:excerpt() function in a
+ query.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>support-highlighting</entry>
+
+ <entry>false</entry>
+
+ <entry>If set to true additional information is stored in the
+ index to support highlighting using the rep:excerpt()
+ function.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>synonymprovider-class</entry>
+
+ <entry>none</entry>
+
+ <entry>The name of a class that implements
+ org.exoplatform.services.jcr.impl.core.query.lucene.SynonymProvider.
+ The default value is null (-> not set).</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>synonymprovider-config-path</entry>
+
+ <entry>none</entry>
+
+ <entry>The path to the synonym provider configuration file. This
+ path interpreted relative to the path parameter. If there is a
+ path element inside the SearchIndex element, then this path is
+ interpreted relative to the root path of the path. Whether this
+ parameter is mandatory depends on the synonym provider
+ implementation. The default value is null (-> not set).</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>indexing-configuration-path</entry>
+
+ <entry>none</entry>
+
+ <entry>The path to the indexing configuration file.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>indexing-configuration-class</entry>
+
+ <entry>IndexingConfigurationImpl</entry>
+
+ <entry>The name of the class that implements
+
org.exoplatform.services.jcr.impl.core.query.lucene.IndexingConfiguration.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>force-consistencycheck</entry>
+
+ <entry>false</entry>
+
+ <entry>If set to true a consistency check is performed depending
+ on the parameter forceConsistencyCheck. If set to false no
+ consistency check is performed on startup, even if a redo log had
+ been applied.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>spellchecker-class</entry>
+
+ <entry>none</entry>
+
+ <entry>The name of a class that implements
+
org.exoplatform.services.jcr.impl.core.query.lucene.SpellChecker.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>spellchecker-more-popular</entry>
+
+ <entry>true</entry>
+
+ <entry>If set true - spellchecker return only the suggest words
+ that are as frequent or more frequent than the checked word. If
+ set false, spellchecker return null (if checked word exit in
+ dictionary), or spellchecker will return most close suggest
+ word.</entry>
+
+ <entry>1.10</entry>
+ </row>
+
+ <row>
+ <entry>spellchecker-min-distance</entry>
+
+ <entry>0.55f</entry>
+
+ <entry>Minimal distance between checked word and proposed suggest
+ word.</entry>
+
+ <entry>1.10</entry>
+ </row>
+
+ <row>
+ <entry>errorlog-size</entry>
+
+ <entry>50(Kb)</entry>
+
+ <entry>The default size of error log file in Kb.</entry>
+
+ <entry>1.9</entry>
+ </row>
+
+ <row>
+ <entry>upgrade-index</entry>
+
+ <entry>false</entry>
+
+ <entry>Allows JCR to convert an existing index into the new
+ format. Also it is possible to set this property via system
+ property, for example: -Dupgrade-index=true Indexes before JCR
+ 1.12 will not run with JCR 1.12. Hence you have to run an
+ automatic migration: Start JCR with -Dupgrade-index=true. The old
+ index format is then converted in the new index format. After the
+ conversion the new format is used. On the next start you don't
+ need this option anymore. The old index is replaced and a back
+ conversion is not possible - therefore better take a backup of the
+ index before. (Only for migrations from JCR 1.9 and
+ later.)</entry>
+
+ <entry>1.12</entry>
+ </row>
+
+ <row>
+ <entry>analyzer</entry>
+
+
<entry>org.apache.lucene.analysis.standard.StandardAnalyzer</entry>
+
+ <entry>Class name of a lucene analyzer to use for fulltext
+ indexing of text.</entry>
+
+ <entry>1.12</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section>
+ <title>Global Search Index</title>
+
+ <section>
+ <title>Global Search Index Configuration</title>
+
+ <para>The global search index is configured in the above-mentioned
+ configuration file
+
(<filename>portal/WEB-INF/conf/jcr/repository-configuration.xml</filename>)
+ in the tag "query-handler".</para>
+
+ <programlisting><query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"></programlisting>
+
+ <para>In fact when using Lucene you always should use the same analyzer
+ for indexing and for querying - otherwise the results are unpredictable.
+ You don't have to worry about this, eXo JCR does this for you
+ automatically. If you don't like the StandardAnalyzer configured by
+ default just replace it by your own.</para>
+
+ <para>If you don't have a handy QueryHandler you will learn how create a
+ customized Handler in 5 minutes.</para>
+ </section>
+
+ <section>
+ <title>Customized Search Indexes and Analyzers</title>
+
+ <para>By default Exo JCR uses the Lucene standard Analyzer to index
+ contents. This analyzer uses some standard filters in the method that
+ analyzes the content:<programlisting>public TokenStream tokenStream(String
fieldName, Reader reader) {
+ StandardTokenizer tokenStream = new StandardTokenizer(reader,
replaceInvalidAcronym);
+ tokenStream.setMaxTokenLength(maxTokenLength);
+ TokenStream result = new StandardFilter(tokenStream);
+ result = new LowerCaseFilter(result);
+ result = new StopFilter(result, stopSet);
+ return result;
+ }</programlisting><itemizedlist>
+ <listitem>
+ <para>The first one (StandardFilter) removes 's (as 's in
+ "Peter's") from the end of words and removes dots from
+ acronyms.</para>
+ </listitem>
+
+ <listitem>
+ <para>The second one (LowerCaseFilter) normalizes token text to
+ lower case.</para>
+ </listitem>
+
+ <listitem>
+ <para>The last one (StopFilter) removes stop words from a token
+ stream. The stop set is defined in the analyzer.</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>For specific cases, you may wish to use additional filters like
+ <phrase>ISOLatin1AccentFilter</phrase>, which replaces accented
+ characters in the ISO Latin 1 character set (ISO-8859-1) by their
+ unaccented equivalents.</para>
+
+ <para>In order to use a different filter, you have to create a new
+ analyzer, and a new search index to use the analyzer. You put it in a
+ jar, which is deployed with your application.</para>
+
+ <section>
+ <title>Create the filter</title>
+
+ <para>The ISOLatin1AccentFilter is not present in the current Lucene
+ version used by Exo. You can use the attached file. You can also
+ create your own filter, the relevant method is<programlisting>public final
Token next(final Token reusableToken) throws
java.io.IOException</programlisting>which
+ defines how chars are read and used by the filter.</para>
+ </section>
+
+ <section>
+ <title>Create the analyzer</title>
+
+ <para>The analyzer have to extends
+ org.apache.lucene.analysis.standard.StandardAnalyzer, and overload the
+ method<programlisting>public TokenStream tokenStream(String fieldName,
Reader reader)</programlisting>to
+ put your own filters. You can have a glance at the example analyzer
+ attached to this article.</para>
+ </section>
+
+ <section>
+ <title>Create the search index</title>
+
+ <para>Now, we have the analyzer, we have to write the SearchIndex,
+ which will use the analyzer. Your have to extends
+ org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex. You
+ have to write the constructor, to set the right analyzer, and the
+ method<programlisting>public Analyzer getAnalyzer() {
+ return MyAnalyzer;
+ }</programlisting>to return your analyzer. You can see the attached
+ SearchIndex.</para>
+
+ <note>
+ <para>Since 1.12 version we can set Analyzer directly in
+ configuration. So, creation new SearchIndex only for new Analyzer is
+ redundant.</para>
+ </note>
+ </section>
+
+ <section>
+ <title>Configure your application to use your SearchIndex</title>
+
+ <para>In
+
<filename>portal/WEB-INF/conf/jcr/repository-configuration.xml</filename>,
+ you have to replace each<programlisting><query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"></programlisting>by
+ your own class<programlisting><query-handler
class="mypackage.indexation.MySearchIndex"></programlisting></para>
+ </section>
+
+ <section>
+ <title>Configure your application to use your Analyzer</title>
+
+ <para>In
+
<filename>portal/WEB-INF/conf/jcr/repository-configuration.xml</filename>,
+ you have to add parameter "analyzer" to each query-handler
+ config:<programlisting><query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+ <properties>
+ ...
+ <property name="analyzer"
value="org.exoplatform.services.jcr.impl.core.MyAnalyzer"/>
+ ...
+ </properties>
+</query-handler></programlisting></para>
+
+ <para>When you start exo, your SearchIndex will start to index
+ contents with the specified filters.</para>
+ </section>
+ </section>
+ </section>
+
+ <section>
+ <title>Index Adjustments</title>
+
+ <section>
+ <title>IndexingConfiguration</title>
+
+ <para>Starting with version 1.9, the default search index implementation
+ in JCR allows you to control which properties of a node are indexed. You
+ also can define different analyzers for different nodes.</para>
+
+ <para>The configuration parameter is called indexingConfiguration and
+ per default is not set. This means all properties of a node are
+ indexed.</para>
+
+ <para>If you wish to configure the indexing behavior you need to add a
+ parameter to the query-handler element in your configuration
+ file.</para>
+
+ <programlisting><param name="indexing-configuration-path"
value="/indexing_configuration.xml"/></programlisting>
+ </section>
+
+ <section>
+ <title>Index rules</title>
+
+ <section>
+ <title>Node Scope Limit</title>
+
+ <para>To optimize the index size you can limit the node scope so that
+ <phrase>only certain properties</phrase> of a node type are
+ indexed.</para>
+
+ <para>With the below configuration only properties named Text are
+ indexed for nodes of type nt:unstructured. This configuration also
+ applies to all nodes whose type extends from nt:unstructured.</para>
+
+ <programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <index-rule nodeType="nt:unstructured">
+ <property>Text</property>
+ </index-rule>
+</configuration></programlisting>
+
+ <para>Please note that you have to declare the <phrase>namespace
+ prefixes</phrase> in the configuration element that you are using
+ throughout the XML file!</para>
+ </section>
+
+ <section>
+ <title>Index Boost Value</title>
+
+ <para>It is also possible to configure a <phrase>boost
value</phrase>
+ for the nodes that match the index rule. The default boost value is
+ 1.0. Higher boost values (a reasonable range is 1.0 - 5.0) will yield
+ a higher score value and appear as more relevant.</para>
+
+ <programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <index-rule nodeType="nt:unstructured"
+ boost="2.0">
+ <property>Text</property>
+ </index-rule>
+</configuration></programlisting>
+
+ <para>If you do not wish to boost the complete node but only certain
+ properties you can also provide a boost value for the listed
+ properties:<programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <index-rule nodeType="nt:unstructured">
+ <property boost="3.0">Title</property>
+ <property boost="1.5">Text</property>
+ </index-rule>
+</configuration></programlisting></para>
+ </section>
+
+ <section>
+ <title>Conditional Index Rules</title>
+
+ <para>You may also add a <phrase>condition</phrase> to the
index rule
+ and have multiple rules with the same nodeType. The first index rule
+ that matches will apply and all remaining ones are
+ ignored:<programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <index-rule nodeType="nt:unstructured"
+ boost="2.0"
+ condition="@priority = 'high'">
+ <property>Text</property>
+ </index-rule>
+ <index-rule nodeType="nt:unstructured">
+ <property>Text</property>
+ </index-rule>
+</configuration></programlisting></para>
+
+ <para>In the above example the first rule only applies if the
+ nt:unstructured node has a priority property with a value 'high'. The
+ condition syntax supports only the equals operator and a string
+ literal.</para>
+
+ <para>You may also reference properties in the condition that are not
+ on the current node:<programlisting><?xml
version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <index-rule nodeType="nt:unstructured"
+ boost="2.0"
+ condition="ancestor::*/@priority = 'high'">
+ <property>Text</property>
+ </index-rule>
+ <index-rule nodeType="nt:unstructured"
+ boost="0.5"
+ condition="parent::foo/@priority = 'low'">
+ <property>Text</property>
+ </index-rule>
+ <index-rule nodeType="nt:unstructured"
+ boost="1.5"
+ condition="bar/@priority = 'medium'">
+ <property>Text</property>
+ </index-rule>
+ <index-rule nodeType="nt:unstructured">
+ <property>Text</property>
+ </index-rule>
+</configuration></programlisting></para>
+
+ <para>The indexing configuration also allows you to specify the type
+ of a node in the condition. Please note however that the type match
+ must be exact. It does not consider sub types of the specified node
+ type.</para>
+
+ <programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <index-rule nodeType="nt:unstructured"
+ boost="2.0"
+ condition="element(*, nt:unstructured)/@priority =
'high'">
+ <property>Text</property>
+ </index-rule>
+</configuration></programlisting>
+ </section>
+
+ <section>
+ <title>Exclusion from the Node Scope Index</title>
+
+ <para>Per default all configured properties are fulltext indexed if
+ they are of type STRING and included in the node scope index. A node
+ scope search finds normally all nodes of an index. That is, the select
+ jcr:contains(., 'foo') returns all nodes that have a string property
+ containing the word 'foo'. You can exclude explicitly a property from
+ the node scope index:<programlisting><?xml
version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <index-rule nodeType="nt:unstructured">
+ <property
nodeScopeIndex="false">Text</property>
+ </index-rule>
+</configuration></programlisting></para>
+ </section>
+ </section>
+
+ <section>
+ <title>Index Aggregates</title>
+
+ <para>Sometimes it is useful to include the contents of descendant nodes
+ into a single node to easier search on content that is scattered across
+ multiple nodes.</para>
+
+ <para>JCR allows you to define index aggregates based on relative path
+ patterns and primary node types.</para>
+
+ <para>The following example creates an index aggregate on nt:file that
+ includes the content of the jcr:content node:<programlisting><?xml
version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <aggregate primaryType="nt:file">
+ <include>jcr:content</include>
+ </aggregate>
+</configuration></programlisting></para>
+
+ <para>You can also restrict the included nodes to a certain
+ type:<programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <aggregate primaryType="nt:file">
+ <include
primaryType="nt:resource">jcr:content</include>
+ </aggregate>
+</configuration></programlisting></para>
+
+ <para>You may also use the * to match all child
nodes:<programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <aggregate
primaryType="nt:file">http://wiki.exoplatform.com/xwiki/...
+ <include primaryType="nt:resource">*</include>
+ </aggregate>
+</configuration></programlisting></para>
+
+ <para>If you wish to include nodes up to a certain depth below the
+ current node you can add multiple include elements. E.g. the nt:file
+ node may contain a complete XML document under
+ jcr:content:<programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <aggregate primaryType="nt:file">
+ <include>*</include>
+ <include>*/*</include>
+ <include>*/*/*</include>
+ </aggregate>
+</configuration></programlisting></para>
+ </section>
+
+ <section>
+ <title>Property-Level Analyzers</title>
+
+ <section>
+ <title>Example</title>
+
+ <para>In this configuration section you define how a property has to
+ be analyzed. If there is an analyzer configuration for a property,
+ this analyzer is used for indexing and searching of this property. For
+ example:<programlisting><?xml version="1.0"?>
+<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
+<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
+ <analyzers>
+ <analyzer
class="org.apache.lucene.analysis.KeywordAnalyzer">
+ <property>mytext</property>
+ </analyzer>
+ <analyzer
class="org.apache.lucene.analysis.WhitespaceAnalyzer">
+ <property>mytext2</property>
+ </analyzer>
+ </analyzers>
+</configuration></programlisting></para>
+
+ <para>The configuration above means that the property "mytext"
for the
+ entire workspace is indexed (and searched) with the Lucene
+ KeywordAnalyzer, and property "mytext2" with the WhitespaceAnalyzer.
+ Using different analyzers for different languages is particularly
+ useful.</para>
+
+ <para>The WhitespaceAnalyzer tokenizes a property, the KeywordAnalyzer
+ takes the property as a whole.</para>
+ </section>
+
+ <section>
+ <title>Characteristics of Node Scope Searches</title>
+
+ <para>When using analyzers, you may encounter an unexpected behavior
+ when searching within a property compared to searching within a node
+ scope. The reason is that the node scope always uses the global
+ analyzer.</para>
+
+ <para>Let's suppose that the property "mytext" contains the
text :
+ "testing my analyzers" and that you haven't configured any
analyzers
+ for the property "mytext" (and not changed the default analyzer in
+ SearchIndex).</para>
+
+ <para>If your query is for example:<programlisting>xpath =
"//*[jcr:contains(mytext,'analyzer')]"</programlisting></para>
+
+ <para>This xpath does not return a hit in the node with the property
+ above and default analyzers.</para>
+
+ <para>Also a search on the node scope<programlisting>xpath =
"//*[jcr:contains(.,'analyzer')]"</programlisting>won't
+ give a hit. Realize, that you can only set specific analyzers on a
+ node property, and that the node scope indexing/analyzing is always
+ done with the globally defined analyzer in the SearchIndex
+ element.</para>
+
+ <para>Now, if you change the analyzer used to index the "mytext"
+ property above to<programlisting><analyzer
class="org.apache.lucene.analysis.Analyzer.GermanAnalyzer">
+ <property>mytext</property>
+</analyzer></programlisting>and you do the same search again, then
+ for<programlisting>xpath =
"//*[jcr:contains(mytext,'analyzer')]"</programlisting>you
+ would get a hit because of the word stemming (analyzers -
+ analyzer).</para>
+
+ <para>The other search,<programlisting>xpath =
"//*[jcr:contains(.,'analyzer')]"</programlisting>still
+ would not give a result, since the node scope is indexed with the
+ global analyzer, which in this case does not take into account any
+ word stemming.</para>
+
+ <para>In conclusion, be aware that when using analyzers for specific
+ properties, you might find a hit in a property for some search text,
+ and you do not find a hit with the same search text in the node scope
+ of the property!</para>
+
+ <note>
+ <para>Both index rules and index aggregates influence how content is
+ indexed in JCR. If you change the configuration the existing content
+ is not automatically re-indexed according to the new rules. You
+ therefore have to manually re-index the content when you change the
+ configuration!</para>
+ </note>
+ </section>
+ </section>
+ <section>
+ <title>Advanced features</title>
+ <para>Exo JCR supports some advanced features, which are not specified in JSR
170:
+ * Get a text excerpt with
+ <emphasis role="bold">highlighted words</emphasis> that matches
the query:
+ <ulink
url="ExcerptProvider>http://wiki.exoplatform.com/xwiki/bin/view/J...;.
+ * Search for a term and its
+ <emphasis role="bold">synonyms</emphasis>:
+ <ulink
url="SynonymSearch>http://wiki.exoplatform.com/xwiki/bin/view/JCR...
+ * Search for
+ <emphasis role="bold">similar</emphasis> nodes:
+ <ulink
url="SimilaritySearch>http://wiki.exoplatform.com/xwiki/bin/view/...
+ * Check
+ <emphasis role="bold">spelling</emphasis> of a fulltext query
statement:
+ <ulink
url="SpellChecker>http://wiki.exoplatform.com/xwiki/bin/view/JCR/...
+ * Define index
+ <emphasis role="bold">aggregates and rules</emphasis>:
IndexingConfiguration (see this article)
+ </para>
+ </section>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/workspace-persistence-storage.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/workspace-persistence-storage.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration/workspace-persistence-storage.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,87 @@
+<?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.WorkspaceDataContainer">
+ <?dbhtml filename="ch-jcr-workspace-data-container.html"?>
+ <title>Workspace Data Container</title>
+
+ <para>Each Workspace of JCR has its own persistent storage to hold
+ workspace's items data. eXo Content Repository can be configured so that it
+ can use one or more workspaces that are logical units of the repository
+ content. Physical data storage mechanism is configured using mandatory
+ element <emphasis role="bold">container</emphasis>. The type of
container is
+ described in the attribute <emphasis role="bold">class</emphasis>
= fully
+ qualified name of
+ org.exoplatform.services.jcr.storage.WorkspaceDataContainer subclass
+ like</para>
+
+ <programlisting><container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcjcr1"/>
+ <property name="dialect" value="hsqldb"/>
+ <property name="multi-db" value="true"/>
+ <property name="max-buffer-size" value="200K"/>
+ <property name="swap-directory"
value="target/temp/swap/ws"/>
+ </properties></programlisting>
+
+ <para>Properties are Container specific parameters:</para>
+
+ <para><emphasis role="bold">source-name</emphasis> - JDBC
data source name,
+ registered in JDNI by InitialContextInitializer. ( <emphasis
+ role="bold">sourceName</emphasis> prior v.1.9)</para>
+
+ <para><emphasis role="bold">dialect</emphasis> - database
dialect, one of
+ "hsqldb", "mysql", "mysql-utf8", "pgsql",
"oracle", "oracle-oci", "mssql",
+ "sybase", "derby", "db2", "db2v8"</para>
+
+ <para><emphasis role="bold">multi-db</emphasis> - enable
multi-database
+ container with this parameter (if "true").</para>
+
+ <para><emphasis role="bold">max-buffer-size</emphasis> - a
threshold in
+ bytes, if a value size is greater then it will be spooled to a temporary
+ file.</para>
+
+ <para><emphasis role="bold">swap-directory</emphasis> - a
location where the
+ value will be spooled if no value storage is configured but a
+ max-buffer-size is exceeded.</para>
+
+ <para>eXo JCR has an RDB (JDBC) based, production ready <emphasis
+ role="bold">Workspace Data Container</emphasis>.</para>
+
+ <para>Workspace Data Container MAY support external storages for
+ javax.jcr.Value (which can be the case for BLOB values for example) using
+ the optional element <emphasis
role="bold">value-storages</emphasis>. Data
+ Container will try to read or write Value using underlying value storage
+ plugin if the filter criteria (see below) match the current property.</para>
+
+ <programlisting><value-storages>
+ <value-storage id="Storage #1"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+ <properties>
+ <property name="path" value="data/values"/>
+ </properties>
+ <filters>
+ <filter property-type="Binary"
min-value-size="1M"/><!-- Values large of 1Mbyte -->
+ </filters>
+.........
+</value-storages></programlisting>
+
+ <para>Where <emphasis role="bold">value-storage</emphasis>
is the subclass
+ of org.exoplatform.services.jcr.storage.value.ValueStoragePlugin and
+ <emphasis role="bold">properties</emphasis> are optional plugin
specific
+ parameters.</para>
+
+ <para><emphasis role="bold">filters</emphasis> : Each file
value storage can
+ have the filter(s) for incoming values. If there are several filter
+ criteria, they all have to match (AND-Condition).</para>
+
+ <para>A filter can match values by property type (property-type), property
+ name (property-name), ancestor path (ancestor-path) and/or the size of
+ values stored (min-value-size, e.g. 1M, 4.2G, 100 (bytes)).</para>
+
+ <para>In a code sample we use a filter with property-type and min-value-size
+ only. That means that the storage is only for binary values whose size is
+ greater than 1Mbyte.</para>
+
+ <para>It's recommended to store properties with large values in a file value
+ storage only.</para>
+</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration-persister.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration-persister.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration-persister.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="ch_configuration_persister">
- <?dbhtml filename="ch-configuration-persister.html"?>
- <title>JCR Configuration persister</title>
-
- <section>
- <title>Idea</title>
-
- <para>JCR Repository Service uses
-
<classname>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</classname>
- component to read its configuration.</para>
-
- <programlisting><component>
-
<key>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</key>
-
<type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationImpl</type>
- <init-params>
- <value-param>
- <name>conf-path</name>
- <description>JCR configuration file</description>
- <value>/conf/standalone/exo-jcr-config.xml</value>
- </value-param>
- </init-params>
- </component></programlisting>
-
- <para>In the example Repository Service will read the configuration from
- the file
<filename>/conf/standalone/exo-jcr-config.xml</filename>.</para>
-
- <para>But in some cases it's required to change the configuration on the
- fly. And know that the new one will be used. Additionally we wish not to
- modify the original file.</para>
-
- <para>In this case we have to use the configuration persister feature
- which allows to store the configuration in different locations.</para>
- </section>
-
- <section>
- <title>Usage</title>
-
- <para>On startup
<classname>RepositoryServiceConfiguration</classname>
- component checks if a configuration persister was configured. In that case
- it uses the provided <classname>ConfigurationPersister</classname>
- implementation class to instantiate the persister object.</para>
-
- <para>Configuration with
persister:<programlisting><component>
-
<key>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</key>
-
<type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationImpl</type>
- <init-params>
- <value-param>
- <name>conf-path</name>
- <description>JCR configuration file</description>
- <value>/conf/standalone/exo-jcr-config.xml</value>
- </value-param>
- <properties-param>
- <name>working-conf</name>
- <description>working-conf</description>
- <property name="source-name" value="jdbcjcr"
/>
- <property name="dialect" value="mysql" />
- <property name="persister-class-name"
value="org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister"
/>
- </properties-param>
- </init-params>
- </component></programlisting></para>
-
- <para>Where:<itemizedlist>
- <listitem>
- <para><parameter>source-name</parameter> - JNDI source name
- configured in <classname>InitialContextInitializer</classname>
- component. (<parameter>sourceName</parameter> prior v.1.9.) Find
- more in <link linkend="ch_configuration">database
- configuration</link>.</para>
- </listitem>
-
- <listitem>
- <para><parameter>dialect</parameter> - SQL dialect which will
be
- used with database from <parameter>source-name</parameter>. Find
- more in <link linkend="ch_configuration">database
- configuration</link>.</para>
- </listitem>
-
- <listitem>
- <para><parameter>persister-class-name</parameter> - class
name of
- <classname>ConfigurationPersister</classname> interface
- implementation. (<parameter>persisterClassName</parameter> prior
- v.1.9.)</para>
- </listitem>
- </itemizedlist></para>
-
- <para>ConfigurationPersister interface:<programlisting>/**
- * Init persister.
- * Used by RepositoryServiceConfiguration on init.
- * @return - config data stream
- */
- void init(PropertiesParam params) throws RepositoryConfigurationException;
-
- /**
- * Read config data.
- * @return - config data stream
- */
- InputStream read() throws RepositoryConfigurationException;
-
- /**
- * Create table, write data.
- * @param confData - config data stream
- */
- void write(InputStream confData) throws RepositoryConfigurationException;
-
- /**
- * Tell if the config exists.
- * @return - flag
- */
- boolean hasConfig() throws
RepositoryConfigurationException;</programlisting></para>
-
- <para>JCR Core implementation contains a persister which stores the
- repository configuration in the relational database using JDBC calls -
-
<classname>org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister</classname>.</para>
-
- <para>The implementation will crate and use table JCR_CONFIG in the
- provided database.</para>
-
- <para>But the developer can implement his own persister for his particular
- usecase.</para>
- </section>
-</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/configuration.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,436 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="ch_configuration">
- <?dbhtml filename="ch-configuration.html"?>
-
- <title>eXo JCR configuration</title>
-
- <section>
- <title>Related documents</title>
-
- <itemizedlist>
- <listitem>
- <para><link linkend="ch_search_configuration">Search
- Configuration</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="ch_jdbc_data_container">JDBC Data
Container
- config</link></para>
- </listitem>
-
- <listitem>
- <para><link linkend="ch_external_value_storages">External
Value
- Storages</link></para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Portal and Standalone configuration</title>
-
- <para>Like other eXo services eXo JCR can be configured and used in portal
- or embedded mode (as a service embedded in eXo Portal) and in standalone
- mode.</para>
-
- <para>In Embedded mode, JCR services are registered in the Portal
- container and the second option is to use a Standalone container. The main
- difference between these container types is that the first one is intended
- to be used in a Portal (Web) environment, while the second one can be used
- standalone (TODO see the comprehensive page Service Configuration for
- Beginners for more details).</para>
-
- <para>The following setup procedure is used to obtain a Standalone
- configuration (TODO find more in Container configuration):</para>
-
- <itemizedlist>
- <listitem>
- <para>Configuration that is set explicitly using
- StandaloneContainer.addConfigurationURL(String url) or
- StandaloneContainer.addConfigurationPath(String path) before
- getInstance()</para>
- </listitem>
-
- <listitem>
- <para>Configuration from $base:directory/exo-configuration.xml or
- $base:directory/conf/exo-configuration.xml file. Where $base:directory
- is either AS's home directory in case of J2EE AS environment or just
- the current directory in case of a standalone application.</para>
- </listitem>
-
- <listitem>
- <para>/conf/exo-configuration.xml in the current classloader (e.g.
- war, ear archive)</para>
- </listitem>
-
- <listitem>
- <para>Configuration from
- $service_jar_file/conf/portal/configuration.xml. WARNING: do not rely
- on some concrete jar's configuration if you have more than one jar
- containing conf/portal/configuration.xml file. In this case choosing a
- configuration is unpredictable.</para>
- </listitem>
- </itemizedlist>
-
- <para>JCR service configuration looks like:</para>
-
- <programlisting><component>
-
<key>org.exoplatform.services.jcr.RepositoryService</key>
-
<type>org.exoplatform.services.jcr.impl.RepositoryServiceImpl</type>
- </component>
- <component>
-
<key>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</key>
-
<type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationImpl</type>
- <init-params>
- <value-param>
- <name>conf-path</name>
- <description>JCR repositories configuration
file</description>
-
<value>jar:/conf/standalone/exo-jcr-config.xml</value>
- </value-param>
- <properties-param>
- <name>working-conf</name>
- <description>working-conf</description>
- <property name="source-name" value="jdbcjcr"
/>
- <property name="dialect" value="hsqldb" />
- <property name="persister-class-name"
value="org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister"
/>
- </properties-param>
- </init-params>
- </component></programlisting>
-
- <para>conf-path : a path to a RepositoryService JCR Configuration</para>
-
- <para>working-conf : optional; JCR configuration persister configuration.
- If there isn't a working-conf the persister will be disabled</para>
-
- <section>
- <title>JCR Configuration</title>
-
- <para>The Configuration is defined in an XML file (see DTD
- below).</para>
-
- <para>JCR Service can use multiple Repositories and each repository can
- have multiple Workspaces.</para>
-
- <para>Repositories configuration parameters support human-readable
- formats of values. They are all case-insensitive:</para>
-
- <itemizedlist>
- <listitem>
- <para>Numbers formats: K,KB - kilobytes, M,MB - megabytes, G,GB -
- gigabytes, T,TB - terabytes.</para>
-
- <para>Examples: 100.5 - digit 100.5, 200k - 200 Kbytes, 4m - 4
- Mbytes, 1.4G - 1.4 Gbytes, 10T - 10 Tbytes</para>
- </listitem>
-
- <listitem>
- <para>Time format endings: ms - milliseconds, s - seconds, m -
- minutes, h - hours, d - days, w - weeks, if no ending -
- seconds.</para>
-
- <para>Examples: 500ms - 500 milliseconds, 20 or 20s - 20 seconds,
- 30m - 30 minutes, 12h - 12 hours, 5d - 5 days, 4w - 4 weeks.</para>
- </listitem>
- </itemizedlist>
-
- <para></para>
- </section>
-
- <section id="sect_repository_service_configuration">
- <title>Repository service configuration</title>
-
- <para>Default configuration of the Repository Service located in
- jar:/conf/portal/exo-jcr-config.xml, it will be available for portal and
- standalone modes.</para>
-
- <para>In portal mode it is overriden and located in the portal web
- application portal/WEB-INF/conf/jcr/repository-configuration.xml.</para>
-
- <para>Example of Repository Service configuration for standalone
- mode:</para>
-
- <programlisting><repository-service
default-repository="repository">
- <repositories>
- <repository name="db1" system-workspace="ws"
default-workspace="ws">
- <security-domain>exo-domain</security-domain>
- <access-control>optional</access-control>
- <session-max-age>1h</session-max-age>
-
<authentication-policy>org.exoplatform.services.jcr.impl.core.access.JAASAuthenticator</authentication-policy>
- <workspaces>
- <workspace name="production">
- <!-- for system storage -->
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name"
value="jdbcjcr" />
- <property name="multi-db" value="false"
/>
- <property name="update-storage"
value="false" />
- <property name="max-buffer-size"
value="200k" />
- <property name="swap-directory"
value="../temp/swap/production" />
- </properties>
- <value-storages>
- <value-storage id="system"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
- <properties>
- <property name="path"
value="../temp/values/production" />
- </properties>
- <filters>
- <filter property-type="Binary" />
- </filters>
- </value-storage>
- </value-storages>
- </container>
- <initializer
class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
- <properties>
- <property name="root-nodetype"
value="nt:unstructured" />
- </properties>
- </initializer>
- <cache enabled="true"
class="org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl">
- <properties>
- <property name="max-size" value="10k"
/>
- <property name="live-time" value="1h"
/>
- </properties>
- </cache>
- <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
- <properties>
- <property name="index-dir"
value="../temp/jcrlucenedb/production" />
- </properties>
- </query-handler>
- <lock-manager>
- <time-out>15m</time-out>
- <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
- <properties>
- <property name="path"
value="../temp/lock/system" />
- </properties>
- </persister>
- </lock-manager>
- </workspace>
-
- <workspace name="backup">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name"
value="jdbcjcr" />
- <property name="multi-db" value="false"
/>
- <property name="update-storage"
value="false" />
- <property name="max-buffer-size"
value="200k" />
- <property name="swap-directory"
value="../temp/swap/backup" />
- </properties>
- <value-storages>
- <value-storage id="draft"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
- <properties>
- <property name="path"
value="../temp/values/backup" />
- </properties>
- <filters>
- <filter property-type="Binary" />
- </filters>
- </value-storage>
- </value-storages>
- </container>
- <initializer
class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
- <properties>
- <property name="root-nodetype"
value="nt:unstructured" />
- </properties>
- </initializer>
- <cache enabled="true"
class="org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl">
- <properties>
- <property name="max-size" value="10k"
/>
- <property name="live-time" value="1h"
/>
- </properties>
- </cache>
- <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
- <properties>
- <property name="index-dir"
value="../temp/jcrlucenedb/backup" />
- </properties>
- </query-handler>
- </workspace>
- </workspaces>
- </repository>
- </repositories>
-</repository-service>
-</programlisting>
-
- <para>Repository Service configuration:</para>
-
- <para>default-repository - the name of a default repository (one
- returned by RepositoryService.getRepository())</para>
-
- <para>repositories - the list of repositories</para>
-
- <para>Repository configuration:</para>
-
- <para>name - the name of a repository</para>
-
- <para>default-workspace - the name of a workspace obtained using
- Session's login() or login(Credentials) methods (ones without an
- explicit workspace name)</para>
-
- <para>system-workspace - name of workspace where /jcr:system node is
- placed</para>
-
- <para>security-domain - the name of a security domain for JAAS
- authentication</para>
-
- <para>access-control - the name of an access control policy. There can
- be 3 types: optional - ACL is created on-demand(default), disable - no
- access control, mandatory - an ACL is created for each added node(not
- supported yet)</para>
-
- <para>authentication-policy - the name of an authentication policy
- class</para>
-
- <para>workspaces - the list of workspaces</para>
-
- <para>session-max-age - the time after which an idle session will be
- removed (called logout). If not set, the idle session will never be
- removed.</para>
-
- <para>Workspace configuration:</para>
-
- <para>name - the name of a workspace</para>
-
- <para>auto-init-root-nodetype - DEPRECATED in JCR 1.9 (use initializer).
- The node type for root node initialization</para>
-
- <para>container - workspace data container (physical storage)
- configuration</para>
-
- <para>initializer - workspace initializer configuration</para>
-
- <para>cache - workspace storage cache configuration</para>
-
- <para>query-handler - query handler configuration</para>
-
- <para>Workspace data container configuration:</para>
-
- <para>class - A workspace data container class name</para>
-
- <para>properties - the list of properties (name-value pairs) for the
- concrete Workspace data container</para>
-
- <para>value-storages - the list of value storage plugins</para>
-
- <para>Value Storage plugin configuration (optional feature):</para>
-
- <note>
- <para>The value-storage element is optional. If you don't include it,
- the values will be stored as BLOBs inside the database.</para>
- </note>
-
- <para>value-storage - Optional value Storage plugin definition</para>
-
- <para>class- a value storage plugin class name (attribute)</para>
-
- <para>properties - the list of properties (name-value pairs) for a
- concrete Value Storage plugin</para>
-
- <para>filters - the list of filters defining conditions when this plugin
- is applicable</para>
-
- <para>Initializer configuration (optional):</para>
-
- <para>class - initializer implementation class.</para>
-
- <para>properties - the list of properties (name-value pairs). Properties
- are supported:</para>
-
- <para>root-nodetype - The node type for root node
initialization</para>
-
- <para>root-permissions - Default permissions of the root node. It is
- defined as a set of semicolon-delimited permissions containing a group
- of space-delimited identities (user, group etc, see Organization service
- documentation for details) and the type of permission. For example any
- read;:/admin read;:/admin add_node;:/admin set_property;:/admin remove
- means that users from group admin have all permissions and other users
- have only a 'read' permission.</para>
-
- <para>Configurable initializer adds a capability to override workspace
- initial startup procedure.</para>
-
- <para>Cache configuration:</para>
-
- <para>enabled - if workspace cache is enabled</para>
-
- <para>class - cache implementation class, optional from 1.9. Default
- value is
-
org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl.</para>
-
- <para>Cache can be configured to use concrete implementation of
- WorkspaceStorageCache interface. JCR core has two implementation to use:
- * LinkedWorkspaceStorageCacheImpl - default, with configurable read
- behavior and statistic. * WorkspaceStorageCacheImpl - pre 1.9, still can
- be used.</para>
-
- <para>properties - the list of properties (name-value pairs) for
- Workspace cache:</para>
-
- <para>max-size - cache maximum size.</para>
-
- <para>live-time - cached item live time.</para>
-
- <para>LinkedWorkspaceStorageCacheImpl supports additional optional
- parameters TODO</para>
-
- <para>Query Handler configuration:</para>
-
- <para>class - A Query Handler class name</para>
-
- <para>properties - the list of properties (name-value pairs) for a Query
- Handler (indexDir) properties and advanced features described in *Search
- Configuration*</para>
-
- <para>Lock Manager configuration:</para>
-
- <para>time-out - time after which the unused global lock will be
- removed.</para>
-
- <para>persister - a class for storing lock information for future use.
- For example, remove lock after jcr restart.</para>
-
- <para>path - a lock folder, each workspace has its own.</para>
-
- <para></para>
-
- <para>Configuration definition:</para>
-
- <programlisting><!ELEMENT repository-service (repositories)>
- <!ATTLIST repository-service default-repository NMTOKEN #REQUIRED>
- <!ELEMENT repositories (repository)>
- <!ELEMENT repository
(security-domain,access-control,session-max-age,authentication-policy,workspaces)>
- <!ATTLIST repository
- default-workspace NMTOKEN #REQUIRED
- name NMTOKEN #REQUIRED
- system-workspace NMTOKEN #REQUIRED
- >
- <!ELEMENT security-domain (#PCDATA)>
- <!ELEMENT access-control (#PCDATA)>
- <!ELEMENT session-max-age (#PCDATA)>
- <!ELEMENT authentication-policy (#PCDATA)>
- <!ELEMENT workspaces (workspace+)>
- <!ELEMENT workspace (container,initializer,cache,query-handler)>
- <!ATTLIST workspace name NMTOKEN #REQUIRED>
- <!ELEMENT container (properties,value-storages)>
- <!ATTLIST container class NMTOKEN #REQUIRED>
- <!ELEMENT value-storages (value-storage+)>
- <!ELEMENT value-storage (properties,filters)>
- <!ATTLIST value-storage class NMTOKEN #REQUIRED>
- <!ELEMENT filters (filter+)>
- <!ELEMENT filter EMPTY>
- <!ATTLIST filter property-type NMTOKEN #REQUIRED>
- <!ELEMENT initializer (properties)>
- <!ATTLIST initializer class NMTOKEN #REQUIRED>
- <!ELEMENT cache (properties)>
- <!ATTLIST cache
- enabled NMTOKEN #REQUIRED
- class NMTOKEN #REQUIRED
- >
- <!ELEMENT query-handler (properties)>
- <!ATTLIST query-handler class NMTOKEN #REQUIRED>
- <!ELEMENT access-manager (properties)>
- <!ATTLIST access-manager class NMTOKEN #REQUIRED>
- <!ELEMENT lock-manager (time-out,persister)>
- <!ELEMENT time-out (#PCDATA)>
- <!ELEMENT persister (properties)>
- <!ELEMENT properties (property+)>
- <!ELEMENT property EMPTY></programlisting>
- </section>
- </section>
-</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/external-value-storages.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/external-value-storages.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/external-value-storages.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="ch_external_value_storages">
- <?dbhtml filename="ch-external-value-storages.html"?>
-
- <title>External Value Storages</title>
-
- <section>
- <title>Introduction</title>
-
- <para>By default JCR Values are stored in the Workspace Data container
- along with the JCR structure (i.e. Nodes and Properties). eXo JCR offers
- an additional option of storing JCR Values separately from Workspace Data
- container, which can be extremely helpful to keep Binary Large Objects
- (BLOBs) for example (see [TODOBinary values processing link]).</para>
-
- <para>Value storage configuration is a part of Repository configuration,
- find more details <link
-
linkend="sect_repository_service_configuration">there</link>.</para>
-
- <para>Tree-based storage is recommended for most of cases. If you run an
- application on Amazon EC2 - the S3 option may be interesting for
- architecture. Simple 'flat' storage is good in speed of creation/deletion
- of values, it might be a compromise for a small storages.</para>
- </section>
-
- <section>
- <title>Tree File Value Storage</title>
-
- <para>Holds Values in tree-like FileSystem files.
- <property>path</property> property points to the root directory to store
- the files.</para>
-
- <para>This is a recommended type of external storage, it can contain large
- amount of files limited only by disk/volume free space.</para>
-
- <para>A disadvantage it's a higher time on Value deletion due to unused
- tree-nodes remove.</para>
-
- <programlisting><value-storage id="Storage #1"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
- <properties>
- <property name="path" value="data/values"/>
- </properties>
- <filters>
- <filter property-type="Binary"
min-value-size="1M"/>
- </filters></programlisting>
-
- <para>Where :<simplelist>
- <member><parameter>id</parameter> - the value storage unique
- identifier, used for linking with properties stored in workspace
- container</member>
-
- <member><parameter>path</parameter> - a location where value
files
- will be stored</member>
- </simplelist></para>
-
- <para>Each file value storage can have the
<function>filter(s)</function>
- for incoming values. A filter can match values by property type
- (<property>property-type</property>), property name
- (<property>property-name</property>), ancestor path
- (<property>ancestor-path</property>) and/or size of values stored
- (<property>min-value-size</property>, in bytes). In code sample we use a
- filter with property-type and min-value-size only. I.e. storage for binary
- values with size greater of 1MB. It's recommended to store properties with
- large values in file value storage only.</para>
-
- <para>Another example shows a value storage with different locations for
- large files (<property>min-value-size</property> a 20Mb-sized filter). A
- value storage uses ORed logic in the process of filter selection. That
- means the first filter in the list will be asked first and if not matched
- the next will be called etc. Here a value matches the 20 MB-sized filter
- <property>min-value-size</property> and will be stored in the path
- "data/20Mvalues", all other in "data/values".</para>
-
- <programlisting><value-storages>
- <value-storage id="Storage #1"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
- <properties>
- <property name="path" value="data/20Mvalues"/>
- </properties>
- <filters>
- <filter property-type="Binary"
min-value-size="20M"/>
- </filters>
- <value-storage>
- <value-storage id="Storage #2"
class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
- <properties>
- <property name="path" value="data/values"/>
- </properties>
- <filters>
- <filter property-type="Binary"
min-value-size="1M"/>
- </filters>
- <value-storage>
-<value-storages></programlisting>
- </section>
-
- <section>
- <title>Simple File Value Storage</title>
-
- <note>
- <para>Not recommended to use in production due to low capacity
- capabilities on most file systems.</para>
-
- <para>But if you're sure in your file-system or data amount is small it
- may be useful for you as haves a faster speed of Value removal.</para>
- </note>
-
- <para>Holds Values in flat FileSystem files.
<property>path</property>
- property points to root directory in order to store files</para>
-
- <programlisting><value-storage id="Storage #1"
class="org.exoplatform.services.jcr.impl.storage.value.fs.SimpleFileValueStorage">
- <properties>
- <property name="path" value="data/values"/>
- </properties>
- <filters>
- <filter property-type="Binary"
min-value-size="1M"/>
- </filters></programlisting>
- </section>
-
- <section>
- <title>Content Addressable Value storage (CAS) support</title>
-
- <para>eXo JCR supports <phrase>Content-addressable
storage</phrase>
- feature for <phrase>Values</phrase> storing.</para>
-
- <note>
- <para>Content-addressable storage, also referred to as associative
- storage and abbreviated CAS, is a mechanism for storing information that
- can be retrieved based on its content, not its storage location. It is
- typically used for high-speed storage and retrieval of fixed content,
- such as documents stored for compliance with government
- regulations.</para>
- </note>
-
- <para>Content Addressable Value storage stores unique content once.
- Different properties (values) with same content will be stored as one data
- file shared between those values. We can tell the Value content will be
- shared across some Values in storage and will be stored on one physical
- file.</para>
-
- <para>Storage size will be decreased for application which governs
- potentially same data in the content.</para>
-
- <note>
- <para>For example: if you have 100 different properties containing the
- same data (e.g. mail attachment) the storage stores only one single
- file. The file will be shared with all referencing properties.</para>
- </note>
-
- <para>If property Value changes it is stored in an additional file.
- Alternatively the file is shared with other values, pointing to the same
- content.</para>
-
- <para>The storage calculates Value content address each time the property
- was changed. CAS write operations are much more expensive compared to the
- non-CAS storages.</para>
-
- <para>Content address calculation based on java.security.MessageDigest
- hash computation and tested with <abbrev>MD5</abbrev> and
- <abbrev>SHA1</abbrev> algorithms.</para>
-
- <note>
- <para>CAS storage works most efficiently on data that does not change
- often. For data that changes frequently, CAS is not as efficient as
- location-based addressing.</para>
- </note>
-
- <para>CAS support can be enabled for <phrase>Tree</phrase> and
- <phrase>Simple File Value Storage</phrase> types.</para>
-
- <para>To enable CAS support just configure it in JCR Repositories
- configuration like we do for other Value Storages.</para>
-
- <programlisting><workspaces>
- <workspace name="ws">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name"
value="jdbcjcr"/>
- <property name="dialect"
value="oracle"/>
- <property name="multi-db"
value="false"/>
- <property name="update-storage"
value="false"/>
- <property name="max-buffer-size"
value="200k"/>
- <property name="swap-directory"
value="target/temp/swap/ws"/>
- </properties>
- <value-storages>
-<!------------------- here ----------------------->
- <value-storage id="ws"
class="org.exoplatform.services.jcr.impl.storage.value.fs.CASableTreeFileValueStorage">
- <properties>
- <property name="path"
value="target/temp/values/ws"/>
- <property name="digest-algo"
value="MD5"/>
- <property name="vcas-type"
value="org.exoplatform.services.jcr.impl.storage.value.cas.JDBCValueContentAddressStorageImpl"/>
- <property name="jdbc-source-name"
value="jdbcjcr"/>
- <property name="jdbc-dialect"
value="oracle"/>
- </properties>
- <filters>
- <filter property-type="Binary"/>
- </filters>
- </value-storage>
- </value-storages></programlisting>
-
- <para>Properties:<simplelist>
- <member><parameter>digest-algo</parameter> - digest hash
algorithm
- (MD5 and SHA1 were tested);</member>
-
- <member><parameter>vcas-type</parameter> - Value CAS internal
data
- type, JDBC backed is currently implemented
-
org.exoplatform.services.jcr.impl.storage.value.cas.JDBCValueContentAddressStorageImp;l</member>
-
- <member><parameter>jdbc-source-name</parameter> -
- JDBCValueContentAddressStorageImpl specific parameter, database will
- be used to save CAS metadata. It's simple to use same as in workspace
- container;</member>
-
- <member><parameter>jdbc-dialect</parameter> -
- JDBCValueContentAddressStorageImpl specific parameter, database
- dialect. It's simple to use same as in workspace container;</member>
- </simplelist></para>
- </section>
-</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/jdbc-data-container-config.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/jdbc-data-container-config.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/jdbc-data-container-config.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,592 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="ch_jdbc_data_container">
- <?dbhtml filename="ch-jdbc-data-container-config.html"?>
-
- <title>JDBC Data Container Config</title>
-
- <section>
- <title>Introduction</title>
-
- <para>eXo JCR persistent data container can work in two configuration
- modes:<itemizedlist>
- <listitem>
- <para><phrase>Multi-database</phrase>: one database for each
- workspace (used in standalone eXo JCR service mode)</para>
- </listitem>
-
- <listitem>
- <para><phrase>Single-database</phrase>: all workspaces
persisted in
- one database (used in embedded eXo JCR service mode, e.g. in eXo
- portal)</para>
- </listitem>
- </itemizedlist></para>
-
- <para>The data container uses the JDBC driver to communicate with the
- actual database software, i.e. any JDBC-enabled data storage can be used
- with eXo JCR implementation.</para>
-
- <para>Currently the data container is tested with the following
- RDBMS:<itemizedlist>
- <listitem>
- <para>MySQL (5.x including UTF8 support)</para>
- </listitem>
-
- <listitem>
- <para>PostgreSQL (8.x)</para>
- </listitem>
-
- <listitem>
- <para>Oracle Database (9i, 10g)</para>
- </listitem>
-
- <listitem>
- <para>Microsoft SQL Server (2005)</para>
- </listitem>
-
- <listitem>
- <para>Sybase ASE (15.0)</para>
- </listitem>
-
- <listitem>
- <para>Apache Derby/Java DB (10.1.x, 10.2.x)</para>
- </listitem>
-
- <listitem>
- <para>IBM DB2 (8.x, 9.x)</para>
- </listitem>
-
- <listitem>
- <para>HSQLDB (1.8.0.7)</para>
- </listitem>
- </itemizedlist></para>
-
- <para>Each database software supports ANSI SQL standards but has its own
- specifics too. So, each database has its own configuration in eXo JCR as a
- database dialect parameter. If you need a more detailed configuration of
- the database it's possible to do that by editing the metadata SQL-script
- files.</para>
-
- <para>In case the non-ANSI node name is used it's necessary to use a
- database with MultiLanguage support[TODO link to MultiLanguage]. Some JDBC
- drivers need additional parameters for establishing a Unicode friendly
- connection. E.g. under mysql it's necessary to add an additional parameter
- for the JDBC driver at the end of JDBC URL. For instance:
-
<
code>jdbc:mysql://exoua.dnsalias.net/portal?characterEncoding=utf8<...
-
- <para>There are preconfigured configuration files for HSQLDB. Look for
- these files in /conf/portal and /conf/standalone folders of the jar-file
- <package>exo.jcr.component.core-XXX.XXX.jar</package> or
- source-distribution of eXo JCR implementation.</para>
-
- <para>By default the configuration files are located in service jars
- <filename>/conf/portal/configuration.xml</filename> (eXo services
- including JCR Repository Service) and
- <filename>exo-jcr-config.xml</filename> (repositories configuration). In
- eXo portal product JCR is configured in portal web application
- <filename>portal/WEB-INF/conf/jcr/jcr-configuration.xml</filename> (JCR
- Repository Service and related serivces) and repository-configuration.xml
- (repositories configuration).</para>
-
- <para>Read more about <link
linkend="ch_configuration">Repository
- configuration</link>.</para>
- </section>
-
- <section>
- <title>Multi-database Configuration</title>
-
- <para>You need to configure each workspace in a repository. You may have
- each one on different remote servers as far as you need.</para>
-
- <para>First of all configure the data containers in the
-
<classname>org.exoplatform.services.naming.InitialContextInitializer</classname>
- service. It's the JNDI context initializer which registers (binds) naming
- resources (DataSources) for data containers.</para>
-
- <para>Example (standalone mode, two data containers
- <parameter>jdbcjcr</parameter> - local HSQLDB,
- <parameter>jdbcjcr1</parameter> - remote
MySQL):<programlisting><component>
-
<key>org.exoplatform.services.naming.InitialContextInitializer</key>
-
<type>org.exoplatform.services.naming.InitialContextInitializer</type>
- <component-plugins>
- <component-plugin>
- <name>bind.datasource</name>
- <set-method>addPlugin</set-method>
-
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
- <init-params>
- <value-param>
- <name>bind-name</name>
- <value>jdbcjcr</value>
- </value-param>
- <value-param>
- <name>class-name</name>
- <value>javax.sql.DataSource</value>
- </value-param>
- <value-param>
- <name>factory</name>
-
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
- </value-param>
- <properties-param>
- <name>ref-addresses</name>
- <description>ref-addresses</description>
- <property name="driverClassName"
value="org.hsqldb.jdbcDriver"/>
- <property name="url"
value="jdbc:hsqldb:file:target/temp/data/portal"/>
- <property name="username" value="sa"/>
- <property name="password" value=""/>
- </properties-param>
- </init-params>
- </component-plugin>
- <component-plugin>
- <name>bind.datasource</name>
- <set-method>addPlugin</set-method>
-
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
- <init-params>
- <value-param>
- <name>bind-name</name>
- <value>jdbcjcr1</value>
- </value-param>
- <value-param>
- <name>class-name</name>
- <value>javax.sql.DataSource</value>
- </value-param>
- <value-param>
- <name>factory</name>
-
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
- </value-param>
- <properties-param>
- <name>ref-addresses</name>
- <description>ref-addresses</description>
- <property name="driverClassName"
value="com.mysql.jdbc.Driver"/>
- <property name="url"
value="jdbc:mysql://exoua.dnsalias.net/jcr"/>
- <property name="username"
value="exoadmin"/>
- <property name="password"
value="exo12321"/>
- <property name="maxActive" value="50"/>
- <property name="maxIdle" value="5"/>
- <property name="initialSize" value="5"/>
- </properties-param>
- </init-params>
- </component-plugin>
- <component-plugins>
- <init-params>
- <value-param>
- <name>default-context-factory</name>
-
<value>org.exoplatform.services.naming.SimpleContextFactory</value>
- </value-param>
- </init-params>
- </component></programlisting></para>
-
- <para>We configure the database connection parameters:<itemizedlist>
- <listitem>
- <para><parameter>driverClassName</parameter>, e.g.
- "org.hsqldb.jdbcDriver", "com.mysql.jdbc.Driver",
- "org.postgresql.Driver"</para>
- </listitem>
-
- <listitem>
- <para><parameter>url</parameter>, e.g.
- "jdbc:hsqldb:file:target/temp/data/portal",
- "jdbc:mysql://exoua.dnsalias.net/jcr"</para>
- </listitem>
-
- <listitem>
- <para><parameter>username</parameter>, e.g. "sa",
"exoadmin"</para>
- </listitem>
-
- <listitem>
- <para><parameter>password</parameter>, e.g. "",
"exo12321"</para>
- </listitem>
- </itemizedlist></para>
-
- <para>There can be connection pool configuration parameters
- (org.apache.commons.dbcp.BasicDataSourceFactory):<itemizedlist>
- <listitem>
- <para><parameter>maxActive</parameter>, e.g. 50</para>
- </listitem>
-
- <listitem>
- <para><parameter>maxIdle</parameter>, e.g. 5</para>
- </listitem>
-
- <listitem>
- <para><parameter>initialSize</parameter>, e.g.
5</para>
- </listitem>
-
- <listitem>
- <para>and other according to <ulink
-
url="http://jakarta.apache.org/commons/dbcp/configuration.html"...
- DBCP configuration</ulink></para>
- </listitem>
- </itemizedlist></para>
-
- <para>When the data container configuration is done we can configure the
- repository service. Each workspace will be configured for its own data
- container.</para>
-
- <para>Example (two workspaces <parameter>ws</parameter> - jdbcjcr,
- <parameter>ws1</parameter> -
jdbcjcr1):<programlisting><workspaces>
- <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr"/>
- <property name="dialect" value="hsqldb"/>
- <property name="multi-db" value="true"/>
- <property name="max-buffer-size" value="200K"/>
- <property name="swap-directory"
value="target/temp/swap/ws"/>
- </properties>
- </container>
- <cache enabled="true">
- <properties>
- <property name="max-size"
value="10K"/><!-- 10Kbytes -->
- <property name="live-time"
value="30m"/><!-- 30 min -->
- </properties>
- </cache>
- <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
- <properties>
- <property name="index-dir"
value="target/temp/index"/>
- </properties>
- </query-handler>
- <lock-manager>
- <time-out>15m</time-out><!-- 15 min -->
- <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
- <properties>
- <property name="path"
value="target/temp/lock/ws"/>
- </properties>
- </persister>
- </lock-manager>
- </workspace>
- <workspace name="ws1"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr1"/>
- <property name="dialect" value="mysql"/>
- <property name="multi-db" value="true"/>
- <property name="max-buffer-size" value="200K"/>
- <property name="swap-directory"
value="target/temp/swap/ws1"/>
- </properties>
- </container>
- <cache enabled="true">
- <properties>
- <property name="max-size" value="10K"/>
- <property name="live-time" value="5m"/>
- </properties>
- </cache>
- <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
- <properties>
- <property name="index-dir"
value="target/temp/index"/>
- </properties>
- </query-handler>
- <lock-manager>
- <time-out>15m</time-out><!-- 15 min -->
- <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
- <properties>
- <property name="path"
value="target/temp/lock/ws1"/>
- </properties>
- </persister>
- </lock-manager>
- </workspace>
-</workspaces></programlisting><itemizedlist>
- <listitem>
- <para><parameter>source-name</parameter> - a
javax.sql.DataSource
- name configured in InitialContextInitializer component (was
- <parameter>sourceName</parameter> prior JCR 1.9);</para>
- </listitem>
-
- <listitem>
- <para><parameter>dialect</parameter> - a database dialect,
one of
- "hsqldb", "mysql", "mysql-utf8",
"pgsql", "oracle", "oracle-oci",
- "mssql", "sybase", "derby", "db2",
"db2v8" or "auto" for dialect
- autodetection;</para>
- </listitem>
-
- <listitem>
- <para><parameter>multi-db</parameter> - enable
multi-database
- container with this parameter (set value "true");</para>
- </listitem>
-
- <listitem>
- <para><parameter>max-buffer-size</parameter> - a threshold
(in
- bytes) after which a javax.jcr.Value content will be swapped to a
- file in a temporary storage. I.e. swap for pending changes.</para>
- </listitem>
-
- <listitem>
- <para><parameter>swap-directory</parameter> - a path in the
file
- system used to swap the pending changes.</para>
- </listitem>
- </itemizedlist></para>
-
- <para>In this way we have configured two workspace which will be persisted
- in two different databases (ws in HSQLDB, ws1 in MySQL).</para>
-
- <note>
- <para>Starting from v.1.9 <link
linkend="ch_configuration">repository
- configuration</link> parameters supports human-readable formats of
- values (e.g. 200K - 200 Kbytes, 30m - 30 minutes etc)</para>
- </note>
- </section>
-
- <section>
- <title>Single-database configuration</title>
-
- <para>It's more simple to configure a single-database data container. We
- have to configure one naming resource.</para>
-
- <para>Example (embedded mode for <parameter>jdbcjcr</parameter>
data
- container):<programlisting><external-component-plugins>
-
<target-component>org.exoplatform.services.naming.InitialContextInitializer</target-component>
- <component-plugin>
- <name>bind.datasource</name>
- <set-method>addPlugin</set-method>
-
<type>org.exoplatform.services.naming.BindReferencePlugin</type>
- <init-params>
- <value-param>
- <name>bind-name</name>
- <value>jdbcjcr</value>
- </value-param>
- <value-param>
- <name>class-name</name>
- <value>javax.sql.DataSource</value>
- </value-param>
- <value-param>
- <name>factory</name>
-
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
- </value-param>
- <properties-param>
- <name>ref-addresses</name>
- <description>ref-addresses</description>
- <property name="driverClassName"
value="org.postgresql.Driver"/>
- <property name="url"
value="jdbc:postgresql://exoua.dnsalias.net/portal"/>
- <property name="username"
value="exoadmin"/>
- <property name="password"
value="exo12321"/>
- <property name="maxActive" value="50"/>
- <property name="maxIdle" value="5"/>
- <property name="initialSize" value="5"/>
- </properties-param>
- </init-params>
- </component-plugin>
- </external-component-plugins></programlisting></para>
-
- <para>And configure repository workspaces in repositories configuration
- with this one database. Parameter "multi-db" must be switched off (set
- value "false").</para>
-
- <para>Example (two workspaces <parameter>ws</parameter> - jdbcjcr,
- <parameter>ws1</parameter> -
jdbcjcr):<programlisting><workspaces>
- <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr"/>
- <property name="dialect" value="pgsql"/>
- <property name="multi-db" value="false"/>
- <property name="max-buffer-size" value="200K"/>
- <property name="swap-directory"
value="target/temp/swap/ws"/>
- </properties>
- </container>
- <cache enabled="true">
- <properties>
- <property name="max-size" value="10K"/>
- <property name="live-time" value="30m"/>
- </properties>
- </cache>
- <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
- <properties>
- <property name="index-dir"
value="../temp/index"/>
- </properties>
- </query-handler>
- <lock-manager>
- <time-out>15m</time-out>
- <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
- <properties>
- <property name="path"
value="target/temp/lock/ws"/>
- </properties>
- </persister>
- </lock-manager>
- </workspace>
- <workspace name="ws1"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr"/>
- <property name="dialect" value="pgsql"/>
- <property name="multi-db" value="false"/>
- <property name="max-buffer-size" value="200K"/>
- <property name="swap-directory"
value="target/temp/swap/ws1"/>
- </properties>
- </container>
- <cache enabled="true">
- <properties>
- <property name="max-size" value="10K"/>
- <property name="live-time" value="5m"/>
- </properties>
- </cache>
- <lock-manager>
- <time-out>15m</time-out>
- <persister
class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
- <properties>
- <property name="path"
value="target/temp/lock/ws1"/>
- </properties>
- </persister>
- </lock-manager>
- </workspace>
-</workspaces></programlisting></para>
-
- <para>In this way we have configured two workspaces which will be
- persisted in one database (PostgreSQL).</para>
-
- <section>
- <title>Configuration without DataSource</title>
-
- <para>Repository configuration without using of the
- <classname>javax.sql.DataSource</classname> bounded in
JNDI.</para>
-
- <para>This case may be usable if you have a dedicated JDBC driver
- implementation with special features like XA transactions,
- statements/connections pooling etc:<itemizedlist>
- <listitem>
- <para>You have to remove the configuration in
- <classname>InitialContextInitializer</classname> for your
database
- and configure a new one directly in the workspace
- container.</para>
- </listitem>
-
- <listitem>
- <para>Remove parameter "source-name" and add next lines
instead.
- Describe your values for a JDBC driver, database url and
- username.</para>
- </listitem>
- </itemizedlist></para>
-
- <note>
- <para>But be careful in this case JDBC driver should implement and
- provide connection pooling. Connection pooling is very recommended for
- use with JCR to prevent a database overload.</para>
- </note>
-
- <programlisting><workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="dialect" value="hsqldb"/>
- <property name="driverClassName"
value="org.hsqldb.jdbcDriver"/>
- <property name="url"
value="jdbc:hsqldb:file:target/temp/data/portal"/>
- <property name="username" value="su"/>
- <property name="password" value=""/>
- ......</programlisting>
- </section>
-
- <section>
- <title>Dynamic Workspace Creation</title>
-
- <para>Workspaces can be added dynamically during runtime.</para>
-
- <para>This can be performed in two steps:<itemizedlist>
- <listitem>
- <para>Firstly,
- <classname>ManageableRepository.configWorkspace(WorkspaceEntry
- wsConfig)</classname> - register a new configuration in
- RepositoryContainer and create a WorkspaceContainer.</para>
- </listitem>
-
- <listitem>
- <para>Secondly, the main step,
- <classname>ManageableRepository.createWorkspace(String
- workspaceName)</classname> - creation of a new workspace.</para>
- </listitem>
- </itemizedlist></para>
- </section>
- </section>
-
- <section>
- <title>Simple and Complex queries</title>
-
- <para>eXo JCR provides two ways for interact with Database -
- <classname>JDBCStorageConnection</classname> that uses simple queries
and
- <classname>CQJDBCStorageConection</classname> that uses complex queries
- for reducing amount of database callings.</para>
-
- <para>Simple queries will be used if you chose
-
<classname>org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer</classname>:<programlisting><workspaces>
- <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- ...
- </workspace>
-</worksapces></programlisting></para>
-
- <para>Complex queries will be used if you chose
-
<classname>org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer</classname>:<programlisting><workspaces>
- <workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
- ...
- </workspace>
-</worksapces></programlisting></para>
-
- <para>Why we should use a Complex Queries?<simplelist>
- <member>They are optimised to reduce amount of requests to
- database.</member>
- </simplelist>Why we should use a Simple Queries?<simplelist>
- <member>Simple queries implemented in way to support as many database
- dialects as possible.</member>
-
- <member>Simple queries do not use sub queries, left or right
- joins.</member>
- </simplelist></para>
- </section>
-
- <section>
- <title>Forse Query Hints</title>
-
- <para>Some databases supports hints to increase query performance (like
- Oracle, MySQL, etc). eXo JCR have separate Complex Query implementation
- for Orcale dialect, that uses query hints to increase performance for few
- important queries. </para>
-
- <para>To enable this option put next configuration
- property:<programlisting><workspace name="ws"
auto-init-root-nodetype="nt:unstructured">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="dialect" value="oracle"/>
- <property name="force.query.hints" value="true"
/>
- ......</programlisting></para>
-
- <para>Query hints enabled by default. </para>
-
- <para>eXo JCR uses query hints only for Complex Query Oracle dialect. For
- all other dialects this parameter is ignored.</para>
- </section>
-
- <section>
- <title>Notes for Microsoft Windows users</title>
-
- <para>The current configuration of eXo JCR uses Apache DBCP connection
- pool
- (<classname>org.apache.commons.dbcp.BasicDataSourceFactory</classname>).
- It's possible to set a big value for maxActive parameter in
- <filename>configuration.xml</filename>. That means usage of lots of
TCP/IP
- ports from a client machine inside the pool (i.e. JDBC driver). As a
- result the data container can throw exceptions like "Address already in
- use". To solve this problem you have to configure the client's machine
- networking software for the usage of shorter timeouts for opened TCP/IP
- ports.</para>
-
- <para>Microsoft Windows has <parameter>MaxUserPort</parameter>,
- <parameter>TcpTimedWaitDelay</parameter> registry keys in the node
-
<parameter>HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters</parameter>,
- by default these keys are unset, set each one with values like
- these:<itemizedlist>
- <listitem>
- <para>"TcpTimedWaitDelay"=dword:0000001e, sets TIME_WAIT
parameter
- to 30 seconds, default is 240.</para>
- </listitem>
-
- <listitem>
- <para>"MaxUserPort"=dword:00001b58, sets the maximum of open
ports
- to 7000 or higher, default is 5000.</para>
- </listitem>
- </itemizedlist></para>
-
- <para>A sample registry file is below:<programlisting>Windows Registry
Editor Version 5.00
-
-[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
-"MaxUserPort"=dword:00001b58
-"TcpTimedWaitDelay"=dword:0000001e</programlisting></para>
- </section>
-</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/multilanguage-support.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/multilanguage-support.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/multilanguage-support.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="ch_multilanguage_support">
- <?dbhtml filename="ch-multilanguage-support.html"?>
-
- <title>Multilanguage support in eXo JCR RDB backend</title>
-
- <section>
- <title>Intro</title>
-
- <para>Whenever relational database is used to store multilingual text data
- of eXo Java Content Repository we need to adapt configuration in order to
- support UTF-8 encoding. Here is a short HOWTO instruction for several
- supported RDBMS with examples.</para>
-
- <para>The configuration file you have to modify:
- .../webapps/portal/WEB-INF/conf/jcr/repository-configuration.xml</para>
-
- <note>
- <para>Datasource <parameter>jdbcjcr</parameter> used in examples
can be
- configured via <classname>InitialContextInitializer</classname>
- component.</para>
- </note>
- </section>
-
- <section>
- <title>Oracle</title>
-
- <para>In order to run multilanguage JCR on an Oracle backend Unicode
- encoding for characters set should be applied to the database. Other
- Oracle globalization parameters don't make any impact. The only property
- to modify is <constant>NLS_CHARACTERSET</constant>.</para>
-
- <para>We have tested <constant>NLS_CHARACTERSET</constant> =
- <constant>AL32UTF8</constant> and it's works well for many European
and
- Asian languages.</para>
-
- <para>Example of database configuration (used for JCR
- testing):<programlisting>NLS_LANGUAGE AMERICAN
-NLS_TERRITORY AMERICA
-NLS_CURRENCY $
-NLS_ISO_CURRENCY AMERICA
-NLS_NUMERIC_CHARACTERS .,
-NLS_CHARACTERSET AL32UTF8
-NLS_CALENDAR GREGORIAN
-NLS_DATE_FORMAT DD-MON-RR
-NLS_DATE_LANGUAGE AMERICAN
-NLS_SORT BINARY
-NLS_TIME_FORMAT HH.MI.SSXFF AM
-NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
-NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
-NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
-NLS_DUAL_CURRENCY $
-NLS_COMP BINARY
-NLS_LENGTH_SEMANTICS BYTE
-NLS_NCHAR_CONV_EXCP FALSE
-NLS_NCHAR_CHARACTERSET AL16UTF16</programlisting></para>
-
- <warning>
- <para>JCR 1.12.x doesn't use NVARCHAR columns, so that the value of the
- parameter NLS_NCHAR_CHARACTERSET does not matter for JCR.</para>
- </warning>
-
- <para>Create database with Unicode encoding and use Oracle dialect for the
- Workspace Container:</para>
-
- <programlisting><workspace name="collaboration">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr"
/>
- <property name="dialect" value="oracle"
/>
- <property name="multi-db" value="false"
/>
- <property name="max-buffer-size" value="200k"
/>
- <property name="swap-directory"
value="target/temp/swap/ws" />
- </properties>
- .....</programlisting>
- </section>
-
- <section>
- <title>DB2</title>
-
- <para>DB2 Universal Database (DB2 UDB) supports <ulink
-
url="http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?to...
- and UTF-16/UCS-2</ulink>. When a Unicode database is created, CHAR,
- VARCHAR, LONG VARCHAR data are stored in UTF-8 form. It's enough for JCR
- multi-lingual support.</para>
-
- <para>Example of UTF-8 database creation:<programlisting>DB2 CREATE
DATABASE dbname USING CODESET UTF-8 TERRITORY US</programlisting></para>
-
- <para>Create database with UTF-8 encoding and use db2 dialect for
- Workspace Container on DB2 v.9 and higher:<programlisting><workspace
name="collaboration">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr"
/>
- <property name="dialect" value="db2" />
- <property name="multi-db" value="false"
/>
- <property name="max-buffer-size" value="200k"
/>
- <property name="swap-directory"
value="target/temp/swap/ws" />
- </properties>
- .....</programlisting></para>
-
- <note>
- <para>For DB2 v.8.x support change the property "dialect" to
- db2v8.</para>
- </note>
- </section>
-
- <section>
- <title>MySQL</title>
-
- <para>JCR MySQL-backend requires special dialect <ulink
-
url="http://jira.exoplatform.org/browse/JCR-375">MySQL-UTF8&... to
be
- used for internationalization support. But the database default charset
- should be latin1 to use limited index space effectively (1000 bytes for
- MyISAM engine, 767 for InnoDB). If database default charset is multibyte,
- a JCR database initialization error is thrown concerning index creation
- failure. In other words JCR can work on any singlebyte default charset of
- database, with UTF8 supported by MySQL server. But we have tested it only
- on latin1 database default charset.</para>
-
- <para>Repository configuration, workspace container entry
- example:<programlisting><workspace
name="collaboration">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr"
/>
- <property name="dialect" value="mysql-utf8"
/>
- <property name="multi-db" value="false"
/>
- <property name="max-buffer-size" value="200k"
/>
- <property name="swap-directory"
value="target/temp/swap/ws" />
- </properties>
- .....</programlisting></para>
- </section>
-
- <section>
- <title>PostgreSQL</title>
-
- <para>On PostgreSQL-backend multilingual support can be enabled in <ulink
-
url="http://www.postgresql.org/docs/8.3/interactive/charset.html&quo...
- ways</ulink>:<itemizedlist>
- <listitem>
- <para>Using the locale features of the operating system to provide
- locale-specific collation order, number formatting, translated
- messages, and other aspects. UTF-8 is widely used on Linux
- distributions by default, so it can be useful in such case.</para>
- </listitem>
-
- <listitem>
- <para>Providing a number of different character sets defined in the
- PostgreSQL server, including multiple-byte character sets, to
- support storing text any language, and providing character set
- translation between client and server. We recommend to use UTF-8
- database charset, it will allow any-to-any conversations and make
- this issue transparent for the JCR.</para>
- </listitem>
- </itemizedlist></para>
-
- <para>Create database with UTF-8 encoding and use PgSQL dialect for
- Workspace Container:<programlisting><workspace
name="collaboration">
- <container
class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
- <properties>
- <property name="source-name" value="jdbcjcr"
/>
- <property name="dialect" value="pgsql"
/>
- <property name="multi-db" value="false"
/>
- <property name="max-buffer-size" value="200k"
/>
- <property name="swap-directory"
value="target/temp/swap/ws" />
- </properties>
- .....</programlisting></para>
- </section>
-</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/search-configuration.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/search-configuration.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/search-configuration.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,799 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="ch_search_configuration">
- <?dbhtml filename="ch-search-configuration.html"?>
-
- <title>Search Configuration</title>
-
- <section>
- <title>XML Configuration</title>
-
- <para>JCR index configuration. You can find this file here:
-
<filename>.../portal/WEB-INF/conf/jcr/repository-configuration.xml</filename></para>
-
- <programlisting><repository-service
default-repository="db1">
- <repositories>
- <repository name="db1" system-workspace="ws"
default-workspace="ws">
- ....
- <workspaces>
- <workspace name="ws">
- ....
- <query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
- <properties>
- <property name="index-dir"
value="${java.io.tmpdir}/temp/index/db1/ws" />
- <property name="synonymprovider-class"
value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider"
/>
- <property name="synonymprovider-config-path"
value="/synonyms.properties" />
- <property name="indexing-config-path"
value="/indexing-configuration.xml" />
- <property name="query-class"
value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
- </properties>
- </query-handler>
- ...
- </workspace>
- </workspaces>
- </repository>
- </repositories>
-</repository-service></programlisting>
- </section>
-
- <section>
- <title>Configuration parameters</title>
-
- <table>
- <title></title>
-
- <tgroup cols="4">
- <thead>
- <row>
- <entry>Parameter</entry>
-
- <entry>Default</entry>
-
- <entry>Description</entry>
-
- <entry>Since</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>index-dir</entry>
-
- <entry>none</entry>
-
- <entry>The location of the index directory. This parameter is
- mandatory. Up to 1.9 this parameter called
"indexDir"</entry>
-
- <entry>1.0</entry>
- </row>
-
- <row>
- <entry>use-compoundfile</entry>
-
- <entry>true</entry>
-
- <entry>Advises lucene to use compound files for the index
- files.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>min-merge-docs</entry>
-
- <entry>100</entry>
-
- <entry>Minimum number of nodes in an index until segments are
- merged.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>volatile-idle-time</entry>
-
- <entry>3</entry>
-
- <entry>Idle time in seconds until the volatile index part is moved
- to a persistent index even though minMergeDocs is not
- reached.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>max-merge-docs</entry>
-
- <entry>Integer.MAX_VALUE</entry>
-
- <entry>Maximum number of nodes in segments that will be merged.
- The default value changed in JCR 1.9 to Integer.MAX_VALUE.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>merge-factor</entry>
-
- <entry>10</entry>
-
- <entry>Determines how often segment indices are merged.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>max-field-length</entry>
-
- <entry>10000</entry>
-
- <entry>The number of words that are fulltext indexed at most per
- property.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>cache-size</entry>
-
- <entry>1000</entry>
-
- <entry>Size of the document number cache. This cache maps uuids to
- lucene document numbers</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>force-consistencycheck</entry>
-
- <entry>false</entry>
-
- <entry>Runs a consistency check on every startup. If false, a
- consistency check is only performed when the search index detects
- a prior forced shutdown.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>auto-repair</entry>
-
- <entry>true</entry>
-
- <entry>Errors detected by a consistency check are automatically
- repaired. If false, errors are only written to the log.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>query-class</entry>
-
- <entry>QueryImpl</entry>
-
- <entry>Class name that implements the javax.jcr.query.Query
- interface.This class must also extend from the class:
-
org.exoplatform.services.jcr.impl.core.query.AbstractQueryImpl.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>document-order</entry>
-
- <entry>true</entry>
-
- <entry>If true and the query does not contain an 'order by'
- clause, result nodes will be in document order. For better
- performance when queries return a lot of nodes set to
- 'false'.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>result-fetch-size</entry>
-
- <entry>Integer.MAX_VALUE</entry>
-
- <entry>The number of results when a query is executed. Default
- value: Integer.MAX_VALUE (-> all).</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>excerptprovider-class</entry>
-
- <entry>DefaultXMLExcerpt</entry>
-
- <entry>The name of the class that implements
- org.exoplatform.services.jcr.impl.core.query.lucene.ExcerptProvider
- and should be used for the rep:excerpt() function in a
- query.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>support-highlighting</entry>
-
- <entry>false</entry>
-
- <entry>If set to true additional information is stored in the
- index to support highlighting using the rep:excerpt()
- function.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>synonymprovider-class</entry>
-
- <entry>none</entry>
-
- <entry>The name of a class that implements
- org.exoplatform.services.jcr.impl.core.query.lucene.SynonymProvider.
- The default value is null (-> not set).</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>synonymprovider-config-path</entry>
-
- <entry>none</entry>
-
- <entry>The path to the synonym provider configuration file. This
- path interpreted relative to the path parameter. If there is a
- path element inside the SearchIndex element, then this path is
- interpreted relative to the root path of the path. Whether this
- parameter is mandatory depends on the synonym provider
- implementation. The default value is null (-> not set).</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>indexing-configuration-path</entry>
-
- <entry>none</entry>
-
- <entry>The path to the indexing configuration file.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>indexing-configuration-class</entry>
-
- <entry>IndexingConfigurationImpl</entry>
-
- <entry>The name of the class that implements
-
org.exoplatform.services.jcr.impl.core.query.lucene.IndexingConfiguration.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>force-consistencycheck</entry>
-
- <entry>false</entry>
-
- <entry>If set to true a consistency check is performed depending
- on the parameter forceConsistencyCheck. If set to false no
- consistency check is performed on startup, even if a redo log had
- been applied.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>spellchecker-class</entry>
-
- <entry>none</entry>
-
- <entry>The name of a class that implements
-
org.exoplatform.services.jcr.impl.core.query.lucene.SpellChecker.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>spellchecker-more-popular</entry>
-
- <entry>true</entry>
-
- <entry>If set true - spellchecker return only the suggest words
- that are as frequent or more frequent than the checked word. If
- set false, spellchecker return null (if checked word exit in
- dictionary), or spellchecker will return most close suggest
- word.</entry>
-
- <entry>1.10</entry>
- </row>
-
- <row>
- <entry>spellchecker-min-distance</entry>
-
- <entry>0.55f</entry>
-
- <entry>Minimal distance between checked word and proposed suggest
- word.</entry>
-
- <entry>1.10</entry>
- </row>
-
- <row>
- <entry>errorlog-size</entry>
-
- <entry>50(Kb)</entry>
-
- <entry>The default size of error log file in Kb.</entry>
-
- <entry>1.9</entry>
- </row>
-
- <row>
- <entry>upgrade-index</entry>
-
- <entry>false</entry>
-
- <entry>Allows JCR to convert an existing index into the new
- format. Also it is possible to set this property via system
- property, for example: -Dupgrade-index=true Indexes before JCR
- 1.12 will not run with JCR 1.12. Hence you have to run an
- automatic migration: Start JCR with -Dupgrade-index=true. The old
- index format is then converted in the new index format. After the
- conversion the new format is used. On the next start you don't
- need this option anymore. The old index is replaced and a back
- conversion is not possible - therefore better take a backup of the
- index before. (Only for migrations from JCR 1.9 and
- later.)</entry>
-
- <entry>1.12</entry>
- </row>
-
- <row>
- <entry>analyzer</entry>
-
-
<entry>org.apache.lucene.analysis.standard.StandardAnalyzer</entry>
-
- <entry>Class name of a lucene analyzer to use for fulltext
- indexing of text.</entry>
-
- <entry>1.12</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>Global Search Index</title>
-
- <section>
- <title>Global Search Index Configuration</title>
-
- <para>The global search index is configured in the above-mentioned
- configuration file
-
(<filename>portal/WEB-INF/conf/jcr/repository-configuration.xml</filename>)
- in the tag "query-handler".</para>
-
- <programlisting><query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"></programlisting>
-
- <para>In fact when using Lucene you always should use the same analyzer
- for indexing and for querying - otherwise the results are unpredictable.
- You don't have to worry about this, eXo JCR does this for you
- automatically. If you don't like the StandardAnalyzer configured by
- default just replace it by your own.</para>
-
- <para>If you don't have a handy QueryHandler you will learn how create a
- customized Handler in 5 minutes.</para>
- </section>
-
- <section>
- <title>Customized Search Indexes and Analyzers</title>
-
- <para>By default Exo JCR uses the Lucene standard Analyzer to index
- contents. This analyzer uses some standard filters in the method that
- analyzes the content:<programlisting>public TokenStream tokenStream(String
fieldName, Reader reader) {
- StandardTokenizer tokenStream = new StandardTokenizer(reader,
replaceInvalidAcronym);
- tokenStream.setMaxTokenLength(maxTokenLength);
- TokenStream result = new StandardFilter(tokenStream);
- result = new LowerCaseFilter(result);
- result = new StopFilter(result, stopSet);
- return result;
- }</programlisting><itemizedlist>
- <listitem>
- <para>The first one (StandardFilter) removes 's (as 's in
- "Peter's") from the end of words and removes dots from
- acronyms.</para>
- </listitem>
-
- <listitem>
- <para>The second one (LowerCaseFilter) normalizes token text to
- lower case.</para>
- </listitem>
-
- <listitem>
- <para>The last one (StopFilter) removes stop words from a token
- stream. The stop set is defined in the analyzer.</para>
- </listitem>
- </itemizedlist></para>
-
- <para>For specific cases, you may wish to use additional filters like
- <phrase>ISOLatin1AccentFilter</phrase>, which replaces accented
- characters in the ISO Latin 1 character set (ISO-8859-1) by their
- unaccented equivalents.</para>
-
- <para>In order to use a different filter, you have to create a new
- analyzer, and a new search index to use the analyzer. You put it in a
- jar, which is deployed with your application.</para>
-
- <section>
- <title>Create the filter</title>
-
- <para>The ISOLatin1AccentFilter is not present in the current Lucene
- version used by Exo. You can use the attached file. You can also
- create your own filter, the relevant method is<programlisting>public final
Token next(final Token reusableToken) throws
java.io.IOException</programlisting>which
- defines how chars are read and used by the filter.</para>
- </section>
-
- <section>
- <title>Create the analyzer</title>
-
- <para>The analyzer have to extends
- org.apache.lucene.analysis.standard.StandardAnalyzer, and overload the
- method<programlisting>public TokenStream tokenStream(String fieldName,
Reader reader)</programlisting>to
- put your own filters. You can have a glance at the example analyzer
- attached to this article.</para>
- </section>
-
- <section>
- <title>Create the search index</title>
-
- <para>Now, we have the analyzer, we have to write the SearchIndex,
- which will use the analyzer. Your have to extends
- org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex. You
- have to write the constructor, to set the right analyzer, and the
- method<programlisting>public Analyzer getAnalyzer() {
- return MyAnalyzer;
- }</programlisting>to return your analyzer. You can see the attached
- SearchIndex.</para>
-
- <note>
- <para>Since 1.12 version we can set Analyzer directly in
- configuration. So, creation new SearchIndex only for new Analyzer is
- redundant.</para>
- </note>
- </section>
-
- <section>
- <title>Configure your application to use your SearchIndex</title>
-
- <para>In
-
<filename>portal/WEB-INF/conf/jcr/repository-configuration.xml</filename>,
- you have to replace each<programlisting><query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"></programlisting>by
- your own class<programlisting><query-handler
class="mypackage.indexation.MySearchIndex"></programlisting></para>
- </section>
-
- <section>
- <title>Configure your application to use your Analyzer</title>
-
- <para>In
-
<filename>portal/WEB-INF/conf/jcr/repository-configuration.xml</filename>,
- you have to add parameter "analyzer" to each query-handler
- config:<programlisting><query-handler
class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
- <properties>
- ...
- <property name="analyzer"
value="org.exoplatform.services.jcr.impl.core.MyAnalyzer"/>
- ...
- </properties>
-</query-handler></programlisting></para>
-
- <para>When you start exo, your SearchIndex will start to index
- contents with the specified filters.</para>
- </section>
- </section>
- </section>
-
- <section>
- <title>Index Adjustments</title>
-
- <section>
- <title>IndexingConfiguration</title>
-
- <para>Starting with version 1.9, the default search index implementation
- in JCR allows you to control which properties of a node are indexed. You
- also can define different analyzers for different nodes.</para>
-
- <para>The configuration parameter is called indexingConfiguration and
- per default is not set. This means all properties of a node are
- indexed.</para>
-
- <para>If you wish to configure the indexing behavior you need to add a
- parameter to the query-handler element in your configuration
- file.</para>
-
- <programlisting><param name="indexing-configuration-path"
value="/indexing_configuration.xml"/></programlisting>
- </section>
-
- <section>
- <title>Index rules</title>
-
- <section>
- <title>Node Scope Limit</title>
-
- <para>To optimize the index size you can limit the node scope so that
- <phrase>only certain properties</phrase> of a node type are
- indexed.</para>
-
- <para>With the below configuration only properties named Text are
- indexed for nodes of type nt:unstructured. This configuration also
- applies to all nodes whose type extends from nt:unstructured.</para>
-
- <programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <index-rule nodeType="nt:unstructured">
- <property>Text</property>
- </index-rule>
-</configuration></programlisting>
-
- <para>Please note that you have to declare the <phrase>namespace
- prefixes</phrase> in the configuration element that you are using
- throughout the XML file!</para>
- </section>
-
- <section>
- <title>Index Boost Value</title>
-
- <para>It is also possible to configure a <phrase>boost
value</phrase>
- for the nodes that match the index rule. The default boost value is
- 1.0. Higher boost values (a reasonable range is 1.0 - 5.0) will yield
- a higher score value and appear as more relevant.</para>
-
- <programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <index-rule nodeType="nt:unstructured"
- boost="2.0">
- <property>Text</property>
- </index-rule>
-</configuration></programlisting>
-
- <para>If you do not wish to boost the complete node but only certain
- properties you can also provide a boost value for the listed
- properties:<programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <index-rule nodeType="nt:unstructured">
- <property boost="3.0">Title</property>
- <property boost="1.5">Text</property>
- </index-rule>
-</configuration></programlisting></para>
- </section>
-
- <section>
- <title>Conditional Index Rules</title>
-
- <para>You may also add a <phrase>condition</phrase> to the
index rule
- and have multiple rules with the same nodeType. The first index rule
- that matches will apply and all remaining ones are
- ignored:<programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <index-rule nodeType="nt:unstructured"
- boost="2.0"
- condition="@priority = 'high'">
- <property>Text</property>
- </index-rule>
- <index-rule nodeType="nt:unstructured">
- <property>Text</property>
- </index-rule>
-</configuration></programlisting></para>
-
- <para>In the above example the first rule only applies if the
- nt:unstructured node has a priority property with a value 'high'. The
- condition syntax supports only the equals operator and a string
- literal.</para>
-
- <para>You may also reference properties in the condition that are not
- on the current node:<programlisting><?xml
version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <index-rule nodeType="nt:unstructured"
- boost="2.0"
- condition="ancestor::*/@priority = 'high'">
- <property>Text</property>
- </index-rule>
- <index-rule nodeType="nt:unstructured"
- boost="0.5"
- condition="parent::foo/@priority = 'low'">
- <property>Text</property>
- </index-rule>
- <index-rule nodeType="nt:unstructured"
- boost="1.5"
- condition="bar/@priority = 'medium'">
- <property>Text</property>
- </index-rule>
- <index-rule nodeType="nt:unstructured">
- <property>Text</property>
- </index-rule>
-</configuration></programlisting></para>
-
- <para>The indexing configuration also allows you to specify the type
- of a node in the condition. Please note however that the type match
- must be exact. It does not consider sub types of the specified node
- type.</para>
-
- <programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <index-rule nodeType="nt:unstructured"
- boost="2.0"
- condition="element(*, nt:unstructured)/@priority =
'high'">
- <property>Text</property>
- </index-rule>
-</configuration></programlisting>
- </section>
-
- <section>
- <title>Exclusion from the Node Scope Index</title>
-
- <para>Per default all configured properties are fulltext indexed if
- they are of type STRING and included in the node scope index. A node
- scope search finds normally all nodes of an index. That is, the select
- jcr:contains(., 'foo') returns all nodes that have a string property
- containing the word 'foo'. You can exclude explicitly a property from
- the node scope index:<programlisting><?xml
version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <index-rule nodeType="nt:unstructured">
- <property
nodeScopeIndex="false">Text</property>
- </index-rule>
-</configuration></programlisting></para>
- </section>
- </section>
-
- <section>
- <title>Index Aggregates</title>
-
- <para>Sometimes it is useful to include the contents of descendant nodes
- into a single node to easier search on content that is scattered across
- multiple nodes.</para>
-
- <para>JCR allows you to define index aggregates based on relative path
- patterns and primary node types.</para>
-
- <para>The following example creates an index aggregate on nt:file that
- includes the content of the jcr:content node:<programlisting><?xml
version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
-
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <aggregate primaryType="nt:file">
- <include>jcr:content</include>
- </aggregate>
-</configuration></programlisting></para>
-
- <para>You can also restrict the included nodes to a certain
- type:<programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
-
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <aggregate primaryType="nt:file">
- <include
primaryType="nt:resource">jcr:content</include>
- </aggregate>
-</configuration></programlisting></para>
-
- <para>You may also use the * to match all child
nodes:<programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
-
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <aggregate
primaryType="nt:file">http://wiki.exoplatform.com/xwiki/...
- <include primaryType="nt:resource">*</include>
- </aggregate>
-</configuration></programlisting></para>
-
- <para>If you wish to include nodes up to a certain depth below the
- current node you can add multiple include elements. E.g. the nt:file
- node may contain a complete XML document under
- jcr:content:<programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:jcr="http://www.jcp.org/jcr/1.0"
-
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <aggregate primaryType="nt:file">
- <include>*</include>
- <include>*/*</include>
- <include>*/*/*</include>
- </aggregate>
-</configuration></programlisting></para>
- </section>
-
- <section>
- <title>Property-Level Analyzers</title>
-
- <section>
- <title>Example</title>
-
- <para>In this configuration section you define how a property has to
- be analyzed. If there is an analyzer configuration for a property,
- this analyzer is used for indexing and searching of this property. For
- example:<programlisting><?xml version="1.0"?>
-<!DOCTYPE configuration SYSTEM
"http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd">
-<configuration
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
- <analyzers>
- <analyzer
class="org.apache.lucene.analysis.KeywordAnalyzer">
- <property>mytext</property>
- </analyzer>
- <analyzer
class="org.apache.lucene.analysis.WhitespaceAnalyzer">
- <property>mytext2</property>
- </analyzer>
- </analyzers>
-</configuration></programlisting></para>
-
- <para>The configuration above means that the property "mytext"
for the
- entire workspace is indexed (and searched) with the Lucene
- KeywordAnalyzer, and property "mytext2" with the WhitespaceAnalyzer.
- Using different analyzers for different languages is particularly
- useful.</para>
-
- <para>The WhitespaceAnalyzer tokenizes a property, the KeywordAnalyzer
- takes the property as a whole.</para>
- </section>
-
- <section>
- <title>Characteristics of Node Scope Searches</title>
-
- <para>When using analyzers, you may encounter an unexpected behavior
- when searching within a property compared to searching within a node
- scope. The reason is that the node scope always uses the global
- analyzer.</para>
-
- <para>Let's suppose that the property "mytext" contains the
text :
- "testing my analyzers" and that you haven't configured any
analyzers
- for the property "mytext" (and not changed the default analyzer in
- SearchIndex).</para>
-
- <para>If your query is for example:<programlisting>xpath =
"//*[jcr:contains(mytext,'analyzer')]"</programlisting></para>
-
- <para>This xpath does not return a hit in the node with the property
- above and default analyzers.</para>
-
- <para>Also a search on the node scope<programlisting>xpath =
"//*[jcr:contains(.,'analyzer')]"</programlisting>won't
- give a hit. Realize, that you can only set specific analyzers on a
- node property, and that the node scope indexing/analyzing is always
- done with the globally defined analyzer in the SearchIndex
- element.</para>
-
- <para>Now, if you change the analyzer used to index the "mytext"
- property above to<programlisting><analyzer
class="org.apache.lucene.analysis.Analyzer.GermanAnalyzer">
- <property>mytext</property>
-</analyzer></programlisting>and you do the same search again, then
- for<programlisting>xpath =
"//*[jcr:contains(mytext,'analyzer')]"</programlisting>you
- would get a hit because of the word stemming (analyzers -
- analyzer).</para>
-
- <para>The other search,<programlisting>xpath =
"//*[jcr:contains(.,'analyzer')]"</programlisting>still
- would not give a result, since the node scope is indexed with the
- global analyzer, which in this case does not take into account any
- word stemming.</para>
-
- <para>In conclusion, be aware that when using analyzers for specific
- properties, you might find a hit in a property for some search text,
- and you do not find a hit with the same search text in the node scope
- of the property!</para>
-
- <note>
- <para>Both index rules and index aggregates influence how content is
- indexed in JCR. If you change the configuration the existing content
- is not automatically re-indexed according to the new rules. You
- therefore have to manually re-index the content when you change the
- configuration!</para>
- </note>
- </section>
- </section>
- </section>
-</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/jcr-query-usecases.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,324 @@
+<?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">
+ <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 <ulink
+ url="Index Boost Value">Index Boost Value</ulink></para>
+
+ <para>Also, see an example <ulink url="JCR.Order by
Score">JCR.Order by
+ Score</ulink></para>
+ </section>
+ </section>
+
+ <section>
+ <title>Query Examples</title>
+
+ <section>
+ <title>Query result settings</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="JCR.SetOffsetandSetLimit">Set Offset
And
+ Limit</link></para>
+ </listitem>
+
+ <!--listitem>
+ <xi:include href="offset-and-limit.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </listitem-->
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Type Constraints</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="JCR.Find All Nodes">JCR.Find All
+ Nodes</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Find Nodes by Primary
Type">JCR.Find Nodes by
+ Primary Type</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Find Nodes by Mixin Type">JCR.Find
Nodes by
+ Mixin Type</ulink></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Property Constraints</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="JCR.Property Comparison">JCR.Property
+ Comparison</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.LIKE Constraint">JCR.LIKE
+ Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Escaping in LIKE
Statements">JCR.Escaping in
+ LIKE Statements</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.NOT Constraint">JCR.NOT
+ Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.AND Constraint">JCR.AND
+ Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.OR Constraint">JCR.OR
+ Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Property Existence
Constraint">JCR.Property
+ Existence Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Upper and Lower Case
Constraints">JCR.Upper
+ and Lower Case Constraints</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Date Property Comparison">JCR.Date
Property
+ Comparison</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Node Name Constraint">JCR.Node
Name
+ Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Multivalue Property
Comparison">JCR.Multivalue
+ Property Comparison</ulink></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Path Constraint</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="JCR.Exact Path Constraint">JCR.Exact
Path
+ Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Child Node Constraint">JCR.Child
Node
+ Constraint</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Find All Descendant Nodes">JCR.Find
All
+ Descendant Nodes</ulink></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Ordering specifing</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="JCR.Order by Property">JCR.Order by
+ Property</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Order by Descendant Node
Property">JCR.Order
+ by Descendant Node Property</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Order by Score">JCR.Order by
+ Score</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Order by Path or Name">JCR.Order by
Path or
+ Name</ulink></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title><ulink url="Fulltext Search">Fulltext
Search</ulink></title>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="JCR.Fulltext Search by
Property">JCR.Fulltext
+ Search by Property</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink
+ url="JCR.Fulltext Search by All Properties">JCR.Fulltext Search
by
+ All Properties</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink
+ url="Find nt:file document by content of child jcr:content
node>Aggregation rule">Find
+ nt:file document by content of child jcr:content node>Aggregation
+ rule</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink
+ url="How to set new Analyzer. Accent symblos ignoring>JCR.Ignore
Accent Symbols">How
+ to set new Analyzer. Accent symblos ignoring>JCR.Ignore Accent
+ Symbols</ulink></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Indexing rules and additional features</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="Aggregation rule">Aggregation
rule</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="JCR.Search Result
Highlighting">JCR.Search Result
+ Highlighting</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="Index Boost Value">Index Boost
+ Value</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink
+ url="Exclusion from the Node Scope Index>JCR.Node Scope
Index">Exclusion
+ from the Node Scope Index>JCR.Node Scope
Index</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink
+ url="Regular expressions as property name in indexing rule > Regexp
Indexing Rule">Regular
+ expressions as property name in indexing rule > Regexp Indexing
+ Rule</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="Synonim Provider">Synonim
Provider</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="Spell Checking">Spell
Checking</ulink></para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="Find Similar Nodes">Find Similar
+ Nodes</ulink></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section>
+ <title>Tips and tricks</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="Xpath and numbers in node names">Xpath
and numbers
+ in node names</ulink></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/offset-and-limit.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/offset-and-limit.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/offset-and-limit.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,107 @@
+<?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">
+<section id="JCR.SetOffsetandSetLimit">
+ <title>SetOffset and SetLimit</title>
+
+ <para>Select all nodes with primary type 'nt:unstructured' and returns
only
+ 3 nodes starting with the second node in list.</para>
+
+ <section>
+ <title>Common info</title>
+
+ <para>QueryImpl class has two methods: one to indicate how many results
+ shall be returned at most, and another to fix the starting
+ position.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>setOffset(long offset) - Sets the start offset of the result
+ set.</para>
+ </listitem>
+
+ <listitem>
+ <para>setLimit(long position) - Sets the maximum size of the result
+ set.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Repository structure</title>
+
+ <para>Repository contains mix:title nodes, where jcr:title has different
+ values.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>root</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>node1 (nt:unstructured)</para>
+ </listitem>
+
+ <listitem>
+ <para>node2 (nt:unstructured)</para>
+ </listitem>
+
+ <listitem>
+ <para>node3 (nt:unstructured)</para>
+ </listitem>
+
+ <listitem>
+ <para>node4 (nt:unstructured)</para>
+ </listitem>
+
+ <listitem>
+ <para>node5 (nt:unstructured)</para>
+ </listitem>
+
+ <listitem>
+ <para>node6 (nt:unstructured)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Query execution</title>
+
+ <para><emphasis role="bold">SQL</emphasis></para>
+
+ <programlisting>// make SQL query
+QueryManager queryManager = workspace.getQueryManager();
+// create query
+String sqlStatement = "SELECT * FROM nt:unstructured";
+QueryImpl query = (QueryImpl)queryManager.createQuery(sqlStatement, Query.SQL);
+//return starting with second result
+query.setOffset(1);
+// return 3 results
+query.setLimit(3);
+// execute query and fetch result
+QueryResult result = query.execute();</programlisting>
+ </section>
+
+ <section>
+ <title>Fetch result</title>
+
+ <para>Lets get nodes:</para>
+
+ <programlisting>NodeIterator it = result.getNodes();
+
+if(it.hasNext())
+{
+ Node findedNode = it.nextNode();
+}</programlisting>
+
+ <para>In usual case (without using setOffset and setLimit methods) Node
+ iterator returns all nodes (node1...node6). But in our case NodeIterator
+ will return "node2","node3" and "node4".</para>
+
+ <para>\[node1 <emphasis role="bold">node2</emphasis>
<emphasis
+ role="bold">node3</emphasis> <emphasis
role="bold">node4</emphasis> node5
+ node6\]</para>
+ </section>
+</section>
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/searching-repository-content.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/searching-repository-content.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr/searching/searching-repository-content.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -0,0 +1,374 @@
+<?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.SearchingRepositoryContent">
+ <?dbhtml filename="ch-jcr-searching-repository-conten.html"?>
+
+ <title>Searching Repository Content</title>
+
+ <section id="Introduction">
+ <title>Introduction</title>
+
+ <para>You can find the JCR configuration file here:
+ .../portal/WEB-INF/conf/jcr/repository-configuration.xml. Please read also
+ <link linkend="JCR.SearchConfiguration">Search
Configuration</link> for
+ more information about index configuration.</para>
+ </section>
+
+ <section id="BidirectionalRangeIteratorsince1.9">
+ <title>Bi-directional RangeIterator (since 1.9)</title>
+
+ <para>QueryResult.getNodes() will return bi-directional NodeIterator
+ implementation.</para>
+
+ <note>
+ <para>Bi-directional NodeIterator is <emphasis
role="bold">not
+ supported</emphasis> in two cases:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>SQL query: select * from nt:base</para>
+ </listitem>
+
+ <listitem>
+ <para>XPath query: //* .</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>")</para>
+ </note>
+
+ <para>TwoWayRangeIterator interface:</para>
+
+ <programlisting>/**
+ * Skip a number of elements in the iterator.
+ *
+ * @param skipNum the non-negative number of elements to skip
+ * @throws java.util.NoSuchElementException if skipped past the first element
+ * in the iterator.
+ */
+public void skipBack(long skipNum);</programlisting>
+
+ <para>Usage:</para>
+
+ <programlisting>NodeIterator iter = queryResult.getNodes();
+while (iter.hasNext()) {
+ if (skipForward) {
+ iter.skip(10); // Skip 10 nodes in forward direction
+ } else if (skipBack) {
+ TwoWayRangeIterator backIter = (TwoWayRangeIterator) iter;
+ backIter.skipBack(10); // Skip 10 nodes back
+ }
+ .......
+}</programlisting>
+ </section>
+
+ <section id="FuzzySearchessince1.0">
+ <title>Fuzzy Searches (since 1.0)</title>
+
+ <para>JCR supports such features as Lucene Fuzzy Searches <ulink
+
url="http://lucene.apache.org/java/2_3_2/queryparsersyntax.html"...
+ Lucene - Query Parser Syntax</ulink>.</para>
+
+ <para>To use it you have to form a query like described below:</para>
+
+ <programlisting>QueryManager qman = session.getWorkspace().getQueryManager();
+Query q = qman.createQuery("select * from nt:base where contains(field,
'ccccc~')", Query.SQL);
+QueryResult res = q.execute();</programlisting>
+ </section>
+
+ <section id="SynonymSearchsince1.9">
+ <title>SynonymSearch (since 1.9)</title>
+
+ <para>Searching with synonyms is integrated in the jcr:contains() function
+ and uses the same syntax as synonym searches in Google. If a search term
+ is prefixed by a tilde symbol ( ~ ) also synonyms of the search term are
+ taken into consideration. Example:</para>
+
+ <programlisting>SQL: select * from nt:resource where contains(.,
'~parameter')
+
+XPath: //element(*, nt:resource)[jcr:contains(.,
'~parameter')</programlisting>
+
+ <para>This feature is disabled per default and you need to add a
+ configuration parameter to the query-handler element in your jcr
+ configuration file to enable it.</para>
+
+ <programlisting><param name="synonymprovider-config-path"
value="..you path to configuration file....."/>
+<param name="synonymprovider-class"
value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider"/></programlisting>
+
+ <programlisting>/**
+ * <code>SynonymProvider</code> defines an interface for a
component that
+ * returns synonyms for a given term.
+ */
+public interface SynonymProvider {
+
+ /**
+ * Initializes the synonym provider and passes the file system resource to
+ * the synonym provider configuration defined by the configuration value of
+ * the <code>synonymProviderConfigPath</code> parameter.
The resource may be
+ * <code>null</code> if the configuration parameter is not
set.
+ *
+ * @param fsr the file system resource to the synonym provider
+ * configuration.
+ * @throws IOException if an error occurs while initializing the synonym
+ * provider.
+ */
+ public void initialize(InputStream fsr) throws IOException;
+
+ /**
+ * Returns an array of terms that are considered synonyms for the given
+ * <code>term</code>.
+ *
+ * @param term a search term.
+ * @return an array of synonyms for the given
<code>term</code> or an empty
+ * array if no synonyms are known.
+ */
+ public String[] getSynonyms(String term);
+}</programlisting>
+ </section>
+
+ <section id="HighlightingSince1.9">
+ <title>Highlighting (Since 1.9)</title>
+
+ <para>An ExcerptProvider retrieves text excerpts for a node in the query
+ result and marks up the words in the text that match the query
+ terms.</para>
+
+ <para>Per default highlighting words that matched the query is disabled
+ because this feature requires that additional information is written to
+ the search index. To enable this feature you need to add a configuration
+ parameter to the query-handler element in your jcr configuration file to
+ enable it.</para>
+
+ <programlisting><param name="support-highlighting"
value="true"/></programlisting>
+
+ <para>Additionally there is a parameter that controls the format of the
+ excerpt created. In JCR 1.9 the default is set to
+ org.exoplatform.services.jcr.impl.core.query.lucene.DefaultHTMLExcerpt.
+ The configuration parameter for this setting is:</para>
+
+ <programlisting><param name="excerptprovider-class"
value="org.exoplatform.services.jcr.impl.core.query.lucene.DefaultXMLExcerpt"/></programlisting>
+
+ <section id="DefaultXMLExcerpt">
+ <title>DefaultXMLExcerpt</title>
+
+ <para>This excerpt provider creates an XML fragment of the following
+ form:</para>
+
+ <programlisting><excerpt>
+ <fragment>
+ <highlight>exoplatform</highlight> implements both
the mandatory
+ XPath and optional SQL <highlight>query</highlight>
syntax.
+ </fragment>
+ <fragment>
+ Before parsing the XPath <highlight>query</highlight>
in
+ <highlight>exoplatform</highlight>, the statement is
surrounded
+ </fragment>
+</excerpt></programlisting>
+ </section>
+
+ <section id="DefaultHTMLExcerpt">
+ <title>DefaultHTMLExcerpt</title>
+
+ <para>This excerpt provider creates an HTML fragment of the following
+ form:</para>
+
+ <programlisting><div>
+ <span>
+ <strong>exoplatform</strong> implements both the
mandatory XPath
+ and optional SQL <strong>query</strong> syntax.
+ </span>
+ <span>
+ Before parsing the XPath <strong>query</strong> in
+ <strong>exoplatform</strong>, the statement is
surrounded
+ </span>
+</div></programlisting>
+ </section>
+
+ <section id="Howtouseit">
+ <title>How to use it</title>
+
+ <para>If you are using XPath you must use the rep:excerpt() function in
+ the last location step, just like you would select properties:</para>
+
+ <programlisting>QueryManager qm = session.getWorkspace().getQueryManager();
+Query q = qm.createQuery("//*[jcr:contains(.,
'exoplatform')]/(@Title|rep:excerpt(.))", Query.XPATH);
+QueryResult result = q.execute();
+for (RowIterator it = result.getRows(); it.hasNext(); ) {
+ Row r = it.nextRow();
+ Value title = r.getValue("Title");
+ Value excerpt = r.getValue("rep:excerpt(.)");
+}</programlisting>
+
+ <para>The above code searches for nodes that contain the word
+ exoplatform and then gets the value of the Title property and an excerpt
+ for each result node.</para>
+
+ <para>It is also possible to use a relative path in the call
+ Row.getValue() while the query statement still remains the same. Also
+ you may use a relative path to a string property. The returned value
+ will then be an excerpt based on string value of the property.</para>
+
+ <para>Both available excerpt provider will create fragments of about 150
+ characters and up to 3 fragments.</para>
+
+ <para>In SQL the function is called excerpt() without the rep prefix,
+ but the column in the RowIterator will nonetheless be labled
+ rep:excerpt(.)!</para>
+
+ <programlisting>QueryManager qm = session.getWorkspace().getQueryManager();
+Query q = qm.createQuery("select excerpt(.) from nt:resource where contains(.,
'exoplatform')", Query.SQL);
+QueryResult result = q.execute();
+for (RowIterator it = result.getRows(); it.hasNext(); ) {
+ Row r = it.nextRow();
+ Value excerpt = r.getValue("rep:excerpt(.)");
+}</programlisting>
+ </section>
+ </section>
+
+ <section id="SpellChecker">
+ <title>SpellChecker</title>
+
+ <para>The lucene based query handler implementation supports a pluggable
+ spell checker mechanism. Per default spell checking is not available and
+ you have to configure it first. See parameter spellCheckerClass on page
+ <link linkend="JCR.SearchConfiguration">Search
Configuration</link> JCR
+ currently provides an implementation class , which uses the <ulink
+
url="http://wiki.apache.org/jakarta-lucene/SpellChecker">luc...
+ contrib . The dictionary is derived from the fulltext indexed content of
+ the workspace and updated periodically. You can configure the refresh
+ interval by picking one of the available inner classes of
+
org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>OneMinuteRefreshInterval</para>
+ </listitem>
+
+ <listitem>
+ <para>FiveMinutesRefreshInterval</para>
+ </listitem>
+
+ <listitem>
+ <para>ThirtyMinutesRefreshInterval</para>
+ </listitem>
+
+ <listitem>
+ <para>OneHourRefreshInterval</para>
+ </listitem>
+
+ <listitem>
+ <para>SixHoursRefreshInterval</para>
+ </listitem>
+
+ <listitem>
+ <para>TwelveHoursRefreshInterval</para>
+ </listitem>
+
+ <listitem>
+ <para>OneDayRefreshInterval</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>E.g. if you want a refresh interval of six hours the class name is:
+
org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$SixHoursRefreshInterval.
+ If you use
+ org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker
+ the refresh interval will be one hour.</para>
+
+ <para>The spell checker dictionary is stored as a lucene index under
+ <emphasis
role="bold">"index-dir"/spellchecker</emphasis>. If it does
not
+ exist, a background thread will create it on startup. Similarly the
+ dictionary refresh is also done in a background thread to not block
+ regular queries.</para>
+
+ <section id="HowdoIuseit">
+ <title>How do I use it?</title>
+
+ <para>You can spell check a fulltext statement either with an XPath or a
+ SQL query:</para>
+
+ <programlisting>// rep:spellcheck('explatform') will always evaluate
to true
+Query query =
qm.createQuery("/jcr:root[rep:spellcheck('explatform')]/(rep:spellcheck())",
Query.XPATH);
+RowIterator rows = query.execute().getRows();
+// the above query will always return the root node no matter what string we check
+Row r = rows.nextRow();
+// get the result of the spell checking
+Value v = r.getValue("rep:spellcheck()");
+if (v == null) {
+ // no suggestion returned, the spelling is correct or the spell checker
+ // does not know how to correct it.
+} else {
+ String suggestion = v.getString();
+}</programlisting>
+
+ <para>And the same using SQL:</para>
+
+ <programlisting>// SPELLCHECK('exoplatform') will always evaluate to
true
+Query query = qm.createQuery("SELECT rep:spellcheck() FROM nt:base WHERE jcr:path =
'/' AND SPELLCHECK('explatform')", Query.SQL);
+RowIterator rows = query.execute().getRows();
+// the above query will always return the root node no matter what string we check
+Row r = rows.nextRow();
+// get the result of the spell checking
+Value v = r.getValue("rep:spellcheck()");
+if (v == null) {
+ // no suggestion returned, the spelling is correct or the spell checker
+ // does not know how to correct it.
+} else {
+ String suggestion = v.getString();
+}</programlisting>
+ </section>
+ </section>
+
+ <section id="SimilaritySince1.12">
+ <title>Similarity (Since 1.12)</title>
+
+ <para>Starting with version, 1.12 JCR allows you to search for nodes that
+ are similar to an existing node.</para>
+
+ <para>Similarity is determined by looking up terms that are common to
+ nodes. There are some conditions that must be met for a term to be
+ considered. This is required to limit the number possibly relevant
+ terms.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Only terms with at least 4 characters are considered.</para>
+ </listitem>
+
+ <listitem>
+ <para>Only terms that occur at least 2 times in the source node are
+ considered.</para>
+ </listitem>
+
+ <listitem>
+ <para>Only terms that occur in at least 5 nodes are
considered.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Note: The similarity functionality requires that the
+ supportHightlighting is enabled. Please make sure that you have the
+ following parameter set for the query handler in your
+ workspace.xml.</para>
+
+ <programlisting><param name="support-highlighting"
value="true"/></programlisting>
+
+ <para>The functions are called rep:similar() (in XPath) and similar() (in
+ SQL) and have two arguments:</para>
+
+ <para>relativePath: a relative path to a descendant node or . for the
+ current node. absoluteStringPath: a string literal that contains the path
+ to the node for which to find similar nodes.</para>
+
+ <warning>
+ <para>Relative path is not supported yet.</para>
+ </warning>
+
+ <para>Examples:</para>
+
+ <programlisting>//element(*, nt:resource)[rep:similar(.,
'/parentnode/node.txt/jcr:content')]</programlisting>
+
+ <para>Finds nt:resource nodes, which are similar to node by path
+ /parentnode/node.txt/jcr:content.</para>
+ </section>
+</chapter>
Modified: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/jcr.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -12,26 +12,63 @@
<xi:include href="jcr/architecture.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <!-- concepts -->
+ <xi:include href="jcr/concepts/why-jcr.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/jcr-advantages.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/jcr-compatibility-levels.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/jcr-usage.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/jcr-extensions.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/jcr-applications.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/nodetype-registration.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/jcr-registry-service.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/jcr-namespace-altering.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/concepts/nodetypes-and-namespaces.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
<!-- common configs -->
- <xi:include href="jcr/configuration.xml"
+ <xi:include href="jcr/configuration/exo-jcr-configuration.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="jcr/jdbc-data-container-config.xml"
+ <xi:include href="jcr/configuration/multilanguage-support.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="jcr/external-value-storages.xml"
+ <xi:include href="jcr/configuration/search-configuration.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="jcr/search-configuration.xml"
+ <xi:include href="jcr/configuration/configuration-persister.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="jcr/multilanguage-support.xml"
+ <xi:include href="jcr/configuration/jdbc-data-container-config.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="jcr/configuration-persister.xml"
+ <xi:include href="jcr/configuration/external-value-storages.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="jcr/configuration/workspace-persistence-storage.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/configuration/rest-services-on-groovy.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
<!-- cluster configs -->
<xi:include href="jcr/cluster-config.xml"
@@ -52,48 +89,26 @@
<xi:include href="jcr/transaction-manager-lookup.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <!-- statistics configs -->
+ <!-- search -->
+
+ <xi:include href="jcr/searching/jcr-query-usecases.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr/searching/searching-repository-content.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <!-- other -->
+
<xi:include href="jcr/statistics.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
<!-- data container configs -->
<xi:include href="jcr/data-container.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="jcr/data-container-howto.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/why-jcr.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/jcr-advantages.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/jcr-compatibility-levels.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/jcr-usage.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/jcr-extensions.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/jcr-applications.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/nodetype-registration.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/jcr-registry-service.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/jcr-namespace-altering.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="jcr/concepts/nodetypes-and-namespaces.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
-
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
</part>
Modified:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,472 +1,472 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter>
- <?dbhtml filename="ch-ws.html"?>
-
- <title>REST Framework</title>
-
- <important>
- <para>This describes REST framework before version exo-ws-2.0</para>
- </important>
-
- <section>
- <title>Requirements</title>
-
- <para>The purpose of eXo REST framework is to make eXo services (i.e. the
- components deployed inside eXo Container) simple and transparently
- accessible via HTTP in RESTful manner. In other words those services
- should be viewed as a set of REST Resources - endpoints of the HTTP
- request-response chain, we call those services ResourceContainers.</para>
-
- <para>image: Simplified working model</para>
-
- <para>Taking into account HTTP/REST constraints, it is considered that
- Resources (naturally mapped as Java methods) contained in
- ResourceContainer conform with the following conditions:</para>
-
- <itemizedlist>
- <listitem>
- <para>they are uniquely identifiable in the same way as it is
- specified for HTTP i.e. using URI</para>
- </listitem>
-
- <listitem>
- <para>they can accept data from an HTTP request using all possible
- mechanisms, i.e. as a part of an URL, as URI parameters, as HTTP
- headers and body</para>
- </listitem>
-
- <listitem>
- <para>they can return data to an HTTP response using all possible
- mechanisms, i.e. as HTTP status, headers and body</para>
- </listitem>
- </itemizedlist>
-
- <para>From the implementation point of view:</para>
-
- <itemizedlist>
- <listitem>
- <para>the framework should be as much JSR-311 compatible as possible
- for the time the Specification is in draft and fully compatible after
- the standard's release</para>
- </listitem>
-
- <listitem>
- <para>the ResourceContainer components should be deployable and
- accessible in the same way as an ordinary service</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Implementation</title>
-
- <para>In our REST architecture implementation, an HTTPServlet is the
- front-end for the REST engine. In this RESTful framework, endpoints for
- HTTP request are represented by java classes (ResourceContainers). All
- ResourceContainers are run as components of an ExoContainer, so they are
- configured within the same configuration file.</para>
-
- <para>ResourceBinder and ResourceDispatcher are two other important
- components of the REST engine. ResourceBinder deals with binding and
- unbinding ResourceContainer. ResourceDispatcher dispatches REST requests
- to ResourceContainer. ResourceBinder and ResourceDispatcher are also
- components of the ExoContainer</para>
-
- <section>
- <title>ResourceContainer</title>
-
- <para>A ResourceContainer is an annotated java class. Annotations must
- at least describe URLs and HTTP methods to be served by this container.
- But they may also describe other parameters, like produced content type
- or transformers. Transformers are special Java classes, used to
- serialize and deserialize Java objects.</para>
-
- <para>A very simple ResourceContainer may look like this:</para>
-
- <programlisting>@HTTPMethod("GET")
-@URITemplate("/test1/{param}/test2/")
-public Response method1(@URIParam("param") String param) {
-//...
-//...
- Response resp = Response.Builder.ok().build();
- return resp;
-}</programlisting>
-
- <para>The ResourceContainer described above is very simple, it can serve
- the GET HTTP method for the relative URL /test1/{param}/test2/ where
- {param} can be any string value. Additionally, {param} can be used as a
- method parameter of the container by annotating it as :
- @URIParam("param") String param. For example, in URL /test1/myID/test2
- the method parameter "param" has the value
"myID".</para>
-
- <para>@URITemplate may be used for annotating classes or methods. If the
- TYPE scope annotation is for example @URITemplate("/testservices/") and
- a METHOD scope annotation is @URITemplate("/service1/") then that method
- can be called with the path /testservices/service1/. All
- ResourceContainer methods return Response objects. A Response includes
- HTTP status, an entity (the requested resource), HTTP headers and
- OutputEntityTransformer.</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-scheme.png" />
- </imageobject>
- </mediaobject>
-
- <para>A client sends a request, after some operations, the HTTP request
- is parsed into three parts: the HTTP request stream, which consists of
- the body of the request, HTTP headers and query parameters. Then
- ResourceDispatcher gets this request. During the start of ExoContainers
- ResourceBinder collects all available ResourceContainers and after the
- start passes the list of ResourceContainers to the ResourceDispatcher.
- When ResourceDispatcher gets the request from a client it tries to
- search for a valid ResourceContainer. For this search ResourceDispatcher
- uses @HTTPMethod, @URITemplate and @ProducedMimeType annotations. The
- last one is not always necessary, if it is not specified this is set in
- / (all mime types). When ResourceDispatcher found the "right"
- ResourceContainer it tries to call a method with some parameters.
- ResourceDispatcher will send only parameters which ResourceContainer
- requests. In the code example above the parameter is a part of the
- requested URL between "/test1/" and "/test2/".
ResourceContainer methods
- can consist only of some well-defined parameters. See the next
- rules:</para>
-
- <itemizedlist>
- <listitem>
- <para>Only one parameter of a method can be not annotated. This
- parameter represents the body of the HTTP request.</para>
- </listitem>
-
- <listitem>
- <para>All other parameters should be of java.lang.String types or
- must have a constructor with the java.lang.String parameter and must
- have annotation.</para>
- </listitem>
-
- <listitem>
- <para>If the parameter which represents the HTTP request body is
- present, then in the annotation @InputTransformer a java class must
- be defined that can build the requested parameter from
- java.io.InputStream. About transformation see below. After request
- processing ResourceContainer creates Request. Request is a special
- Java object which consists of HTTP status, a response header, an
- entity, a transformer. The entity is a representation of the
- requested resource. If Response has an entity it also must have
- OutputEntityTransformer. OutputEntityTransformer can be set in a few
- different ways.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Response</title>
-
- <para>Response is created by Builder. Builder is an inner static Java
- class within Response. Builder has some preset ways to build Response,
- for example (see code example above). The method ok() creates Builder
- with status 200 (OK HTTP status) and ok() returns again a Builder
- object. In this way a developer can again call other Builder methods.
- For example:</para>
-
- <programlisting>//...
-Document doc = ....
-Response response = Response.Builder.ok().entity(doc,
"text/xml").transformer(new
XMLOutputTransformer()).build();</programlisting>
-
- <para>In the code example above Response has HTTP status 200, an XML
- document like entity, a Content-Type header "text/xml" and
- OutputEntityTransformer of type XMLOutputTransformer. The method build()
- should be called at the end of process. In the same way a developer can
- build some other prepared Responses, like CREATED, NO CONTENT,
- FORBIDDEN, INTERNAL ERROR and other. In this example we set
- OutputEntityTransformer directly. Another mechanism to do this is the
- same like in the case with InputEntityTransformer.</para>
-
- <programlisting>//...
-@HTTPMethod("GET")
-@URITemplate("/test/resource1/")
-(a)InputTransformer(XMLInputTransformer.class)
-(a)OutputTransformer(XMLOutputTransformer.class)
-public Response method1(Document inputDoc) {
-//...
- Document doc = ....
- Response response = Response.Builder.ok(doc, "text/xml").build();
- return response;
-}</programlisting>
-
- <para>InputEntityTransformer is described in the annotation to the
- method "method1". OutputEntityTransformer is described in the annotation
- to the method "method1".</para>
- </section>
-
- <section>
- <title>Transformer</title>
-
- <para>All transformers can be created by EntityTransformerFactory.
- Transformers can be divided in two groups. Transformers from the first
- one extend the abstract class InputEntityTransformer.
- InputEntityTransformer implements the interface
- GenericInputEntityTransformer, and GenericInputEntityTransformer extends
- the interface GenericEntityTransformer. This architecture gives the
- possibility to use one class EntityTransformerFactory for creating both
- types of transformers (input and output). At first we will speak about
- InputEntityTransformer.</para>
-
- <para><command>InputEntityTransformer</command></para>
-
- <para>All classes which extend the abstract class InputEntitytransformer
- must override the method ObjectreadFrom(InputStream entityDataStream).
- This method must return an object with the same type as
- ResourceContainer requires in method parameters (one not annotated
- parameter). This mechanism works in the following way. For example, a
- class which extends InputEntityTransformer will be called
- SimpleInputTransformer. So, SimpleInputTransformer must have a simple
- constructor (without any parameters). SimpleInputTransformer also has
- two methods void setType(Class entityType) and Class getType(). Those
- methods are described in InputEntityTransformer. And, as we said above,
- SimpleInputTransformer must override the abstract method Object
- readFrom(InputStream entityDataStream). So, a developer needs to create
- a class which can build a Java Object from InputStream and then create
- annotation to ResourceContainer or some method in ResourceContainer.
- This annotation must define the type of InputEntityTransformer. Here is
- the code of the annotation InputTransformer.</para>
-
- <programlisting>//...
-@Retention(RUNTIME)
-@Target({TYPE, METHOD})
-public @interface InputTransformer {
- Class<? extends InputEntityTransformer> value();
-}</programlisting>
-
- <para>Then ResourceDispatcher gets InputTransformer from the factory
- during runtime then builds an Object from stream and adds it to the
- parameter array. See the code below.</para>
-
- <programlisting>//...
- InputEntityTransformer transformer = (InputEntityTransformer)
factory_.newTransformer(resource.getInputTransformerType());
- transformer.setType(methodParameters[i]);
- params[i] = transformer.readFrom(request.getEntityStream());
-//...
- Response response = (Response)
resource.getServer().invoke(resource.getResourceContainer(),
params);</programlisting>
-
- <para>A developer can find some prepared transformers in the package
- "org.exoplatform.services.rest.transformer".</para>
-
- <para><command>OutputEntityTransformer</command></para>
-
- <para>OutputEntityTransformer can be used to serialize the Object which
- represents the requested resource to OutputStream.
- OutputEntityTransformer, in future we will call it
- SimpleOutputTransformer, can be defined in a few ways.</para>
-
- <para>Now some more words about transformation. The RESTful framework
- has two multi-purpose input/output transformers. One of them is
- JAXB(Input/Output)Transformer, and another one is
- Serializable(Input/Output)Transformer. The first one uses JAXB API for
- serializing and deserializing an object. Serializable
- (Input/Output)Transformer uses the own methods of an entity for
- serialization and deserialization. Here is an example:</para>
-
- <programlisting>/...
-public class SimpleSerializableEntity implements SerializableEntity {
-
- String data;
-
- public SimpleSerializableEntity() {
- }
-
- public void readObject(InputStream in) throws IOException {
- StringBuffer sb = new StringBuffer();
- int rd = -1;
- while((rd = in.read()) != -1)
- sb.append((char)rd);
- data = sb.toString();
- }
-
- public void writeObject(OutputStream out) throws IOException {
- out.write(data.getBytes());
- }
-}</programlisting>
-
- <para>SerializableInputTransformer will try to use the method void
- readObject(InputStream in) and SerializableOutputTransformer will try to
- use the method void writeObject(OutputStream in).</para>
- </section>
-
- <section>
- <title>Binding and unbinding components (ResourceContainers)</title>
-
- <para>ResourceBinder takes care of binding and unbinding components
- which represent ResourceContainer. All ResourceContainers must be
- defined as ExoContainer components in configuration files, for
- example:</para>
-
- <programlisting><component>
-
<type>org.exoplatform.services.rest.samples.RESTSampleService</type>
-</component></programlisting>
-
- <para>ResourceBinder is an ExoContainer component and implements the
- interface org.picocontainer.Startable (see the picocontainer
- documentation). So at the start of ExoContainer ResourceBinder collects
- all available ResourceContainers. ResourceBinder makes validation for
- all ResourceContainers. At least each ResourceContainer must have the
- @HTTPMethod annotation and @URITemplate annotation. Other annotations
- are not obligatory. It's not allowed to have few ResourceContainers or
- methods with the same @HTTPMethod and @URITemplate annotation value. For
- example, if one container/method has the following code:</para>
-
- <programlisting>public class SimpleResourceContainer implements
ResourceContainer {
- @HTTPMethod("GET")
- @URITemplate("/services/{id}/service1/")
- @InputTransformer(StringInputTransformer.class)
- @OutputTransformer(StringOutputTransformer.class)
- public Response method1(String data, @URIParam("id") String param) {
- // ...
- }
-}</programlisting>
-
- <para>than another component with @HTTPMethod("GET") and
- @URITemplate("/services/service1/{id}/") can't be bound. And now
we'll
- try to explain this situation. On the one hand URITemplate is defined by
- value /services/{id}/service1/, instead of {id} there can be any other
- string value, so the combination /services/service1/service1/ is
- possible and valid. On the other hand another URITemplate
- /services/service1/{id}/ can have the string service1 instead of {id},
- so for this resource the combination /services/service1/service1/ is
- possible and valid. And now we have two resources with the same
- URITemplate and the same HTTPMethod. This situation is not obligatory,
- we can't say what method we must call! In this case ResourceBinder
- generates InvalidResourceDescriptorException. Binder also checks the
- method parameters. In parameters only one parameter without annotation
- and of free type is allowed. All other parameters must have String type
- (or have a constructor with String) and be annotated. In other cases
- InvalidResourceDescriptorException* is generated. If all components have
- the "right" @HTTPMethod and @URITemplate annotations they should be
- bound without any problems. ResourceDispather gets a collection of
- ResourceContainers during the start and everything is ready to serve a
- request.</para>
-
- <para>Note: within the scope of one component (one class) validation for
- URI templates is not implemented, so a developer must take care of
- @URITemplate and @HTTPMethod. Both of them must not be the same for
- different methods. Except if @QueryTemplate or/and @ProducedMimeTypes
- annotation is used.</para>
- </section>
-
- <section>
- <title>ResourceDispatcher</title>
-
- <para>Now let's talk about the features of ResourceDispatcher.
- ResourceDispatcher is the main part of the RESTful engine. Above we said
- some words about transformation and the role of ResourceDispatcher in
- this process. Now we are ready to talk about annotated method
- parameters. In one of the code examples above you could see the next
- construction</para>
-
- <programlisting>public Response method1(String data,
@URIParam("id") String param) {</programlisting>
-
- <para>The method method1 is described with two parameters. The first
- parameter String data is built from the entity body (InputStream). The
- second one - String param is annotated by a special type Annotation.
- This Annotation has the following code:</para>
-
- <programlisting>@Target(value={PARAMETER})
-@Retention(RUNTIME)
-public @interface URIParam {
- String value();
-}</programlisting>
-
- <para>How does it work? After having found the right method
- ResourceDispatcher gets the list of method parameters and starts
- handling them. Dispatcher tries to find the not annotated parameter
- (this entity body) and addresses InputEntityTransformer in order to
- build the required Object from InputStream. When dispatcher finds an
- annotated parameter it checks the type of annotation. It is possible to
- have four types of annotation: @URIParam, @HeaderParam, @QueryParam and
- @ContextParameter. If dispatcher has found the annotation
- @URIParam("id") then it takes the parameter with the key "id"
from
- ResourceDescription and adds it into the parameter array. The same
- situation is with header, context and query parameters. So within the
- method a developer gets only the necessary parameters from header, query
- and uri. Some more information about @ContextParameters.
- @ContextParameters can be set in the configuration file of a
- component:</para>
-
- <programlisting><component>
-<type>org.exoplatform.services.rest.ResourceDispatcher</type>
- <init-params>
- <properties-param>
- <name>context-params</name>
- <property name="test" value="test_1"/>
- </properties-param>
- </init-params>
-</component></programlisting>
-
- <para>In this case any service can use this parameter, for
- example:</para>
-
- <programlisting>...method(@ContextParam("test") String p) {
- System.out.println(p);
-}</programlisting>
-
- <para>After its execution you should see "test_1" in
console.</para>
-
- <para>And in each service the next context parameters can be used. The
- name of these parameters are described in ResourceDispatcher:</para>
-
- <programlisting>public static final String CONTEXT_PARAM_HOST =
"host";
-public static final String CONTEXT_PARAM_BASE_URI = "baseURI";
-public static final String CONTEXT_PARAM_REL_URI = "relURI";
-public static final String CONTEXT_PARAM_ABSLOCATION =
"absLocation";</programlisting>
-
- <para>After that dispatcher finishes collecting parameters that the
- method requires, invokes this method and passes the result to the client
- as it is described above.</para>
-
- <para>This part of code can explain how this mechanism works:</para>
-
- <programlisting>//...
- for (int i = 0; i < methodParametersAnnotations.length; i++) {
- if (methodParametersAnnotations[i] == null) {
- InputEntityTransformer transformer = (InputEntityTransformer) factory
- .newTransformer(resource.getInputTransformerType());
- transformer.setType(methodParameters[i]);
- params[i] = transformer.readFrom(request.getEntityStream());
- } else {
- Constructor<?> constructor =
methodParameters[i].getConstructor(String.class);
- String constructorParam = null;
- Annotation a = methodParametersAnnotations[i];
- if (a.annotationType().isAssignableFrom(URIParam.class)) {
- URIParam u = (URIParam) a;
- constructorParam =
request.getResourceIdentifier().getParameters().get(u.value());
- } else if (a.annotationType().isAssignableFrom(HeaderParam.class)) {
- HeaderParam h = (HeaderParam) a;
- constructorParam = request.getHeaderParams().get(h.value());
- } else if (a.annotationType().isAssignableFrom(QueryParam.class)) {
- QueryParam q = (QueryParam) a;
- constructorParam = request.getQueryParams().get(q.value());
- } else if (a.annotationType().isAssignableFrom(ContextParam.class)) {
- ContextParam c = (ContextParam) a;
- constructorParam = contextHolder_.get().get(c.value());
- }
- if (methodParameters[i].isAssignableFrom(String.class)) {
- params[i] = constructorParam;
- } else {
- params[i] = (constructorParam != null) ?
constructor.newInstance(constructorParam) : null;
- }
- }
- }
- Response resp = (Response)
resource.getServer().invoke(resource.getResourceContainer(), params);
-//...</programlisting>
-
- <para>The more detailed schema looks like this:</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-scheme-detailed.png" />
- </imageobject>
- </mediaobject>
- </section>
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="WS.RestFramework">
+ <?dbhtml filename="ch-ws-rest-framework.html"?>
+
+ <title>REST Framework</title>
+
+ <important>
+ <para>This describes REST framework before version exo-ws-2.0</para>
+ </important>
+
+ <section>
+ <title>Requirements</title>
+
+ <para>The purpose of eXo REST framework is to make eXo services (i.e. the
+ components deployed inside eXo Container) simple and transparently
+ accessible via HTTP in RESTful manner. In other words those services
+ should be viewed as a set of REST Resources - endpoints of the HTTP
+ request-response chain, we call those services ResourceContainers.</para>
+
+ <para>image: Simplified working model</para>
+
+ <para>Taking into account HTTP/REST constraints, it is considered that
+ Resources (naturally mapped as Java methods) contained in
+ ResourceContainer conform with the following conditions:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>they are uniquely identifiable in the same way as it is
+ specified for HTTP i.e. using URI</para>
+ </listitem>
+
+ <listitem>
+ <para>they can accept data from an HTTP request using all possible
+ mechanisms, i.e. as a part of an URL, as URI parameters, as HTTP
+ headers and body</para>
+ </listitem>
+
+ <listitem>
+ <para>they can return data to an HTTP response using all possible
+ mechanisms, i.e. as HTTP status, headers and body</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>From the implementation point of view:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the framework should be as much JSR-311 compatible as possible
+ for the time the Specification is in draft and fully compatible after
+ the standard's release</para>
+ </listitem>
+
+ <listitem>
+ <para>the ResourceContainer components should be deployable and
+ accessible in the same way as an ordinary service</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Implementation</title>
+
+ <para>In our REST architecture implementation, an HTTPServlet is the
+ front-end for the REST engine. In this RESTful framework, endpoints for
+ HTTP request are represented by java classes (ResourceContainers). All
+ ResourceContainers are run as components of an ExoContainer, so they are
+ configured within the same configuration file.</para>
+
+ <para>ResourceBinder and ResourceDispatcher are two other important
+ components of the REST engine. ResourceBinder deals with binding and
+ unbinding ResourceContainer. ResourceDispatcher dispatches REST requests
+ to ResourceContainer. ResourceBinder and ResourceDispatcher are also
+ components of the ExoContainer</para>
+
+ <section>
+ <title>ResourceContainer</title>
+
+ <para>A ResourceContainer is an annotated java class. Annotations must
+ at least describe URLs and HTTP methods to be served by this container.
+ But they may also describe other parameters, like produced content type
+ or transformers. Transformers are special Java classes, used to
+ serialize and deserialize Java objects.</para>
+
+ <para>A very simple ResourceContainer may look like this:</para>
+
+ <programlisting>@HTTPMethod("GET")
+@URITemplate("/test1/{param}/test2/")
+public Response method1(@URIParam("param") String param) {
+//...
+//...
+ Response resp = Response.Builder.ok().build();
+ return resp;
+}</programlisting>
+
+ <para>The ResourceContainer described above is very simple, it can serve
+ the GET HTTP method for the relative URL /test1/{param}/test2/ where
+ {param} can be any string value. Additionally, {param} can be used as a
+ method parameter of the container by annotating it as :
+ @URIParam("param") String param. For example, in URL /test1/myID/test2
+ the method parameter "param" has the value
"myID".</para>
+
+ <para>@URITemplate may be used for annotating classes or methods. If the
+ TYPE scope annotation is for example @URITemplate("/testservices/") and
+ a METHOD scope annotation is @URITemplate("/service1/") then that method
+ can be called with the path /testservices/service1/. All
+ ResourceContainer methods return Response objects. A Response includes
+ HTTP status, an entity (the requested resource), HTTP headers and
+ OutputEntityTransformer.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-scheme.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>A client sends a request, after some operations, the HTTP request
+ is parsed into three parts: the HTTP request stream, which consists of
+ the body of the request, HTTP headers and query parameters. Then
+ ResourceDispatcher gets this request. During the start of ExoContainers
+ ResourceBinder collects all available ResourceContainers and after the
+ start passes the list of ResourceContainers to the ResourceDispatcher.
+ When ResourceDispatcher gets the request from a client it tries to
+ search for a valid ResourceContainer. For this search ResourceDispatcher
+ uses @HTTPMethod, @URITemplate and @ProducedMimeType annotations. The
+ last one is not always necessary, if it is not specified this is set in
+ / (all mime types). When ResourceDispatcher found the "right"
+ ResourceContainer it tries to call a method with some parameters.
+ ResourceDispatcher will send only parameters which ResourceContainer
+ requests. In the code example above the parameter is a part of the
+ requested URL between "/test1/" and "/test2/".
ResourceContainer methods
+ can consist only of some well-defined parameters. See the next
+ rules:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Only one parameter of a method can be not annotated. This
+ parameter represents the body of the HTTP request.</para>
+ </listitem>
+
+ <listitem>
+ <para>All other parameters should be of java.lang.String types or
+ must have a constructor with the java.lang.String parameter and must
+ have annotation.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the parameter which represents the HTTP request body is
+ present, then in the annotation @InputTransformer a java class must
+ be defined that can build the requested parameter from
+ java.io.InputStream. About transformation see below. After request
+ processing ResourceContainer creates Request. Request is a special
+ Java object which consists of HTTP status, a response header, an
+ entity, a transformer. The entity is a representation of the
+ requested resource. If Response has an entity it also must have
+ OutputEntityTransformer. OutputEntityTransformer can be set in a few
+ different ways.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Response</title>
+
+ <para>Response is created by Builder. Builder is an inner static Java
+ class within Response. Builder has some preset ways to build Response,
+ for example (see code example above). The method ok() creates Builder
+ with status 200 (OK HTTP status) and ok() returns again a Builder
+ object. In this way a developer can again call other Builder methods.
+ For example:</para>
+
+ <programlisting>//...
+Document doc = ....
+Response response = Response.Builder.ok().entity(doc,
"text/xml").transformer(new
XMLOutputTransformer()).build();</programlisting>
+
+ <para>In the code example above Response has HTTP status 200, an XML
+ document like entity, a Content-Type header "text/xml" and
+ OutputEntityTransformer of type XMLOutputTransformer. The method build()
+ should be called at the end of process. In the same way a developer can
+ build some other prepared Responses, like CREATED, NO CONTENT,
+ FORBIDDEN, INTERNAL ERROR and other. In this example we set
+ OutputEntityTransformer directly. Another mechanism to do this is the
+ same like in the case with InputEntityTransformer.</para>
+
+ <programlisting>//...
+@HTTPMethod("GET")
+@URITemplate("/test/resource1/")
+(a)InputTransformer(XMLInputTransformer.class)
+(a)OutputTransformer(XMLOutputTransformer.class)
+public Response method1(Document inputDoc) {
+//...
+ Document doc = ....
+ Response response = Response.Builder.ok(doc, "text/xml").build();
+ return response;
+}</programlisting>
+
+ <para>InputEntityTransformer is described in the annotation to the
+ method "method1". OutputEntityTransformer is described in the annotation
+ to the method "method1".</para>
+ </section>
+
+ <section>
+ <title>Transformer</title>
+
+ <para>All transformers can be created by EntityTransformerFactory.
+ Transformers can be divided in two groups. Transformers from the first
+ one extend the abstract class InputEntityTransformer.
+ InputEntityTransformer implements the interface
+ GenericInputEntityTransformer, and GenericInputEntityTransformer extends
+ the interface GenericEntityTransformer. This architecture gives the
+ possibility to use one class EntityTransformerFactory for creating both
+ types of transformers (input and output). At first we will speak about
+ InputEntityTransformer.</para>
+
+ <para><command>InputEntityTransformer</command></para>
+
+ <para>All classes which extend the abstract class InputEntitytransformer
+ must override the method ObjectreadFrom(InputStream entityDataStream).
+ This method must return an object with the same type as
+ ResourceContainer requires in method parameters (one not annotated
+ parameter). This mechanism works in the following way. For example, a
+ class which extends InputEntityTransformer will be called
+ SimpleInputTransformer. So, SimpleInputTransformer must have a simple
+ constructor (without any parameters). SimpleInputTransformer also has
+ two methods void setType(Class entityType) and Class getType(). Those
+ methods are described in InputEntityTransformer. And, as we said above,
+ SimpleInputTransformer must override the abstract method Object
+ readFrom(InputStream entityDataStream). So, a developer needs to create
+ a class which can build a Java Object from InputStream and then create
+ annotation to ResourceContainer or some method in ResourceContainer.
+ This annotation must define the type of InputEntityTransformer. Here is
+ the code of the annotation InputTransformer.</para>
+
+ <programlisting>//...
+@Retention(RUNTIME)
+@Target({TYPE, METHOD})
+public @interface InputTransformer {
+ Class<? extends InputEntityTransformer> value();
+}</programlisting>
+
+ <para>Then ResourceDispatcher gets InputTransformer from the factory
+ during runtime then builds an Object from stream and adds it to the
+ parameter array. See the code below.</para>
+
+ <programlisting>//...
+ InputEntityTransformer transformer = (InputEntityTransformer)
factory_.newTransformer(resource.getInputTransformerType());
+ transformer.setType(methodParameters[i]);
+ params[i] = transformer.readFrom(request.getEntityStream());
+//...
+ Response response = (Response)
resource.getServer().invoke(resource.getResourceContainer(),
params);</programlisting>
+
+ <para>A developer can find some prepared transformers in the package
+ "org.exoplatform.services.rest.transformer".</para>
+
+ <para><command>OutputEntityTransformer</command></para>
+
+ <para>OutputEntityTransformer can be used to serialize the Object which
+ represents the requested resource to OutputStream.
+ OutputEntityTransformer, in future we will call it
+ SimpleOutputTransformer, can be defined in a few ways.</para>
+
+ <para>Now some more words about transformation. The RESTful framework
+ has two multi-purpose input/output transformers. One of them is
+ JAXB(Input/Output)Transformer, and another one is
+ Serializable(Input/Output)Transformer. The first one uses JAXB API for
+ serializing and deserializing an object. Serializable
+ (Input/Output)Transformer uses the own methods of an entity for
+ serialization and deserialization. Here is an example:</para>
+
+ <programlisting>/...
+public class SimpleSerializableEntity implements SerializableEntity {
+
+ String data;
+
+ public SimpleSerializableEntity() {
+ }
+
+ public void readObject(InputStream in) throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int rd = -1;
+ while((rd = in.read()) != -1)
+ sb.append((char)rd);
+ data = sb.toString();
+ }
+
+ public void writeObject(OutputStream out) throws IOException {
+ out.write(data.getBytes());
+ }
+}</programlisting>
+
+ <para>SerializableInputTransformer will try to use the method void
+ readObject(InputStream in) and SerializableOutputTransformer will try to
+ use the method void writeObject(OutputStream in).</para>
+ </section>
+
+ <section>
+ <title>Binding and unbinding components (ResourceContainers)</title>
+
+ <para>ResourceBinder takes care of binding and unbinding components
+ which represent ResourceContainer. All ResourceContainers must be
+ defined as ExoContainer components in configuration files, for
+ example:</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.services.rest.samples.RESTSampleService</type>
+</component></programlisting>
+
+ <para>ResourceBinder is an ExoContainer component and implements the
+ interface org.picocontainer.Startable (see the picocontainer
+ documentation). So at the start of ExoContainer ResourceBinder collects
+ all available ResourceContainers. ResourceBinder makes validation for
+ all ResourceContainers. At least each ResourceContainer must have the
+ @HTTPMethod annotation and @URITemplate annotation. Other annotations
+ are not obligatory. It's not allowed to have few ResourceContainers or
+ methods with the same @HTTPMethod and @URITemplate annotation value. For
+ example, if one container/method has the following code:</para>
+
+ <programlisting>public class SimpleResourceContainer implements
ResourceContainer {
+ @HTTPMethod("GET")
+ @URITemplate("/services/{id}/service1/")
+ @InputTransformer(StringInputTransformer.class)
+ @OutputTransformer(StringOutputTransformer.class)
+ public Response method1(String data, @URIParam("id") String param) {
+ // ...
+ }
+}</programlisting>
+
+ <para>than another component with @HTTPMethod("GET") and
+ @URITemplate("/services/service1/{id}/") can't be bound. And now
we'll
+ try to explain this situation. On the one hand URITemplate is defined by
+ value /services/{id}/service1/, instead of {id} there can be any other
+ string value, so the combination /services/service1/service1/ is
+ possible and valid. On the other hand another URITemplate
+ /services/service1/{id}/ can have the string service1 instead of {id},
+ so for this resource the combination /services/service1/service1/ is
+ possible and valid. And now we have two resources with the same
+ URITemplate and the same HTTPMethod. This situation is not obligatory,
+ we can't say what method we must call! In this case ResourceBinder
+ generates InvalidResourceDescriptorException. Binder also checks the
+ method parameters. In parameters only one parameter without annotation
+ and of free type is allowed. All other parameters must have String type
+ (or have a constructor with String) and be annotated. In other cases
+ InvalidResourceDescriptorException* is generated. If all components have
+ the "right" @HTTPMethod and @URITemplate annotations they should be
+ bound without any problems. ResourceDispather gets a collection of
+ ResourceContainers during the start and everything is ready to serve a
+ request.</para>
+
+ <para>Note: within the scope of one component (one class) validation for
+ URI templates is not implemented, so a developer must take care of
+ @URITemplate and @HTTPMethod. Both of them must not be the same for
+ different methods. Except if @QueryTemplate or/and @ProducedMimeTypes
+ annotation is used.</para>
+ </section>
+
+ <section>
+ <title>ResourceDispatcher</title>
+
+ <para>Now let's talk about the features of ResourceDispatcher.
+ ResourceDispatcher is the main part of the RESTful engine. Above we said
+ some words about transformation and the role of ResourceDispatcher in
+ this process. Now we are ready to talk about annotated method
+ parameters. In one of the code examples above you could see the next
+ construction</para>
+
+ <programlisting>public Response method1(String data,
@URIParam("id") String param) {</programlisting>
+
+ <para>The method method1 is described with two parameters. The first
+ parameter String data is built from the entity body (InputStream). The
+ second one - String param is annotated by a special type Annotation.
+ This Annotation has the following code:</para>
+
+ <programlisting>@Target(value={PARAMETER})
+@Retention(RUNTIME)
+public @interface URIParam {
+ String value();
+}</programlisting>
+
+ <para>How does it work? After having found the right method
+ ResourceDispatcher gets the list of method parameters and starts
+ handling them. Dispatcher tries to find the not annotated parameter
+ (this entity body) and addresses InputEntityTransformer in order to
+ build the required Object from InputStream. When dispatcher finds an
+ annotated parameter it checks the type of annotation. It is possible to
+ have four types of annotation: @URIParam, @HeaderParam, @QueryParam and
+ @ContextParameter. If dispatcher has found the annotation
+ @URIParam("id") then it takes the parameter with the key "id"
from
+ ResourceDescription and adds it into the parameter array. The same
+ situation is with header, context and query parameters. So within the
+ method a developer gets only the necessary parameters from header, query
+ and uri. Some more information about @ContextParameters.
+ @ContextParameters can be set in the configuration file of a
+ component:</para>
+
+ <programlisting><component>
+<type>org.exoplatform.services.rest.ResourceDispatcher</type>
+ <init-params>
+ <properties-param>
+ <name>context-params</name>
+ <property name="test" value="test_1"/>
+ </properties-param>
+ </init-params>
+</component></programlisting>
+
+ <para>In this case any service can use this parameter, for
+ example:</para>
+
+ <programlisting>...method(@ContextParam("test") String p) {
+ System.out.println(p);
+}</programlisting>
+
+ <para>After its execution you should see "test_1" in
console.</para>
+
+ <para>And in each service the next context parameters can be used. The
+ name of these parameters are described in ResourceDispatcher:</para>
+
+ <programlisting>public static final String CONTEXT_PARAM_HOST =
"host";
+public static final String CONTEXT_PARAM_BASE_URI = "baseURI";
+public static final String CONTEXT_PARAM_REL_URI = "relURI";
+public static final String CONTEXT_PARAM_ABSLOCATION =
"absLocation";</programlisting>
+
+ <para>After that dispatcher finishes collecting parameters that the
+ method requires, invokes this method and passes the result to the client
+ as it is described above.</para>
+
+ <para>This part of code can explain how this mechanism works:</para>
+
+ <programlisting>//...
+ for (int i = 0; i < methodParametersAnnotations.length; i++) {
+ if (methodParametersAnnotations[i] == null) {
+ InputEntityTransformer transformer = (InputEntityTransformer) factory
+ .newTransformer(resource.getInputTransformerType());
+ transformer.setType(methodParameters[i]);
+ params[i] = transformer.readFrom(request.getEntityStream());
+ } else {
+ Constructor<?> constructor =
methodParameters[i].getConstructor(String.class);
+ String constructorParam = null;
+ Annotation a = methodParametersAnnotations[i];
+ if (a.annotationType().isAssignableFrom(URIParam.class)) {
+ URIParam u = (URIParam) a;
+ constructorParam =
request.getResourceIdentifier().getParameters().get(u.value());
+ } else if (a.annotationType().isAssignableFrom(HeaderParam.class)) {
+ HeaderParam h = (HeaderParam) a;
+ constructorParam = request.getHeaderParams().get(h.value());
+ } else if (a.annotationType().isAssignableFrom(QueryParam.class)) {
+ QueryParam q = (QueryParam) a;
+ constructorParam = request.getQueryParams().get(q.value());
+ } else if (a.annotationType().isAssignableFrom(ContextParam.class)) {
+ ContextParam c = (ContextParam) a;
+ constructorParam = contextHolder_.get().get(c.value());
+ }
+ if (methodParameters[i].isAssignableFrom(String.class)) {
+ params[i] = constructorParam;
+ } else {
+ params[i] = (constructorParam != null) ?
constructor.newInstance(constructorParam) : null;
+ }
+ }
+ }
+ Response resp = (Response)
resource.getServer().invoke(resource.getResourceContainer(), params);
+//...</programlisting>
+
+ <para>The more detailed schema looks like this:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-scheme-detailed.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+ </section>
+</chapter>
Modified:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml 2010-08-03
06:46:23 UTC (rev 2855)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml 2010-08-03
07:16:23 UTC (rev 2856)
@@ -1,221 +1,221 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter>
- <?dbhtml filename="ch-ws.html"?>
-
- <title>REST Service Tutorial</title>
-
- <important>
- <para>This article describes REST framework before version
- exo-ws-2.0.</para>
- </important>
-
- <section>
- <title>Introduction</title>
-
- <para>This HOW-TO explains how to create your own REST based services. In
- this HOW-TO we will create a simple calculator, which can do basic
- operations with integers.</para>
- </section>
-
- <section>
- <title>Source code</title>
-
- <programlisting>// ...
-@URITemplate("/calculator/{item1}/{item2}/")
-public class Calculator implements ResourceContainer {
-}</programlisting>
-
- <para>Writing <command>@URITemplate</command> before the class
definition
- gives you the possibility not to set it for each method. Furthermore the
- class must implement the interface <command>ResourceContainer</command>.
- This interface doesn't have any methods, it is just an indication for the
- <command>ResourceBinder</command>. Add the code for adding two
- integers.</para>
-
- <programlisting>// ...
-@URITemplate("/calculator/{item1}/{item2}/")
-public class Calculator implements ResourceContainer {
- @QueryTemplate("operation=add")
- @OutputTransformer(StringOutputTransformer.class)
- @HTTPMethod("GET")
- public Response add(@URIParam("item1") Integer item1,
- @URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-}</programlisting>
-
- <para>@QueryTemplate("operation=add") - only requests with query
- parameters "operation=add" can reach this method;
- @OutputTransformer(StringOutputTransformer.class) - the output
- transformer; @HTTPMethod("GET") - the HTTP method
"GET".</para>
-
- <para>Write the code for other operations in the same way. Then the result
- should look like:</para>
-
- <programlisting>package org.exoplatform.services.rest.example;
-
-import org.exoplatform.services.rest.HTTPMethod;
-import org.exoplatform.services.rest.OutputTransformer;
-import org.exoplatform.services.rest.QueryTemplate;
-import org.exoplatform.services.rest.Response;
-import org.exoplatform.services.rest.URIParam;
-import org.exoplatform.services.rest.URITemplate;
-import org.exoplatform.services.rest.container.ResourceContainer;
-import org.exoplatform.services.rest.transformer.StringOutputTransformer;
-
-@URITemplate("/calculator/{item1}/{item2}/")
-(a)OutputTransformer(StringOutputTransformer.class)
-public class Calculator implements ResourceContainer {
-
- @QueryTemplate("operation=add")
- @HTTPMethod("GET")
- public Response add(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-
- @QueryTemplate("operation=subtract")
- @HTTPMethod("GET")
- public Response subtract(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" - ").append(item2).append(" =
").append(item1 - item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-
- @QueryTemplate("operation=multiply")
- @HTTPMethod("GET")
- public Response multiply(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" * ").append(item2).append(" =
").append(item1 * item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-
- @QueryTemplate("operation=divide")
- @HTTPMethod("GET")
- public Response divide(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" / ").append(item2).append(" =
").append(item1 / item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-}</programlisting>
-
- <para>So we are done with the source code.</para>
- </section>
-
- <section>
- <title>Configuration</title>
-
- <para>Create the directory conf/portal and create the file
- configuration.xml in it. Add the following code to this file:</para>
-
- <programlisting><?xml version="1.0"
encoding="ISO-8859-1"?>
-<configuration>
- <component>
-
<type>org.exoplatform.services.rest.example.Calculator</type>
- </component>
-</configuration></programlisting>
- </section>
-
- <section>
- <title>Build</title>
-
- <para>Now we must create the following directory structure to get the
- possibility to build the source code using maven.</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-build-process.png" />
- </imageobject>
- </mediaobject>
-
- <para>Then create the file pom.xml using the following:</para>
-
- <programlisting><project>
- <parent>
- <groupId>org.exoplatform.ws</groupId>
- <artifactId>config</artifactId>
- <version>trunk</version>
- </parent>
-
- <modelVersion&#624;.0.0</modelVersion>
- <groupId>org.exoplatform.ws.rest</groupId>
- <artifactId>simple.calculator</artifactId>
- <packaging>jar</packaging>
- <version>trunk</version>
- <description>Simple REST service</description>
-
- <dependencies>
- <dependency>
- <groupId>org.exoplatform.ws.rest</groupId>
- <artifactId>exo.rest.core</artifactId>
- <version>trunk</version>
- </dependency>
- </dependencies>
-</project></programlisting>
-
- <para>Build this by executing the command:</para>
-
- <programlisting>andrew@ubu:~/workspace/calculator$ mvn clean
install</programlisting>
- </section>
-
- <section>
- <title>Deploy</title>
-
- <para>We have done all now. Then copy the jar file from the target
- directory of project exo-tomcat into the server with all prepared stuff
- for REST services. (You can download it here: <link
-
linkend="???">http://forge.objectweb.org/project/download.ph...
-
- <para>So just put the jar file into the lib directory of the tomcat and
- restart it. In the console you should see this message:</para>
-
- <programlisting>[INFO] ResourceBinder - Bind new ResourceContainer:
org.exoplatform.services.rest.example.Calculator@19846fd</programlisting>
-
- <para>This message indicates that our service was found, bound and is
- ready to work</para>
- </section>
-
- <section>
- <title>Usage</title>
-
- <para>Open your browser and type the following URL: <link
-
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=add</link>
- and you should see the next page:</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-run-process.png" />
- </imageobject>
- </mediaobject>
-
- <para>The service is working. This is a very simple example, but it should
- help developers use the REST framework.</para>
-
- <para>Try to check other URLs.</para>
-
- <itemizedlist>
- <listitem>
- <para><link
-
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=subtract</link>
- - must give "12 - 5 = 7";</para>
- </listitem>
-
- <listitem>
- <para><link
-
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=multiply</link>
- - must give "12 * 5 = 60";</para>
- </listitem>
-
- <listitem>
- <para><link
-
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=divide</link>-
- must give "12 / 5 = 2" (we are working with integers!);</para>
- </listitem>
- </itemizedlist>
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="WS.RestServiceTutorial">
+ <?dbhtml filename="ch-ws-rest-service-tutorial.html"?>
+
+ <title>REST Service Tutorial</title>
+
+ <important>
+ <para>This article describes REST framework before version
+ exo-ws-2.0.</para>
+ </important>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>This HOW-TO explains how to create your own REST based services. In
+ this HOW-TO we will create a simple calculator, which can do basic
+ operations with integers.</para>
+ </section>
+
+ <section>
+ <title>Source code</title>
+
+ <programlisting>// ...
+@URITemplate("/calculator/{item1}/{item2}/")
+public class Calculator implements ResourceContainer {
+}</programlisting>
+
+ <para>Writing <command>@URITemplate</command> before the class
definition
+ gives you the possibility not to set it for each method. Furthermore the
+ class must implement the interface <command>ResourceContainer</command>.
+ This interface doesn't have any methods, it is just an indication for the
+ <command>ResourceBinder</command>. Add the code for adding two
+ integers.</para>
+
+ <programlisting>// ...
+@URITemplate("/calculator/{item1}/{item2}/")
+public class Calculator implements ResourceContainer {
+ @QueryTemplate("operation=add")
+ @OutputTransformer(StringOutputTransformer.class)
+ @HTTPMethod("GET")
+ public Response add(@URIParam("item1") Integer item1,
+ @URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+}</programlisting>
+
+ <para>@QueryTemplate("operation=add") - only requests with query
+ parameters "operation=add" can reach this method;
+ @OutputTransformer(StringOutputTransformer.class) - the output
+ transformer; @HTTPMethod("GET") - the HTTP method
"GET".</para>
+
+ <para>Write the code for other operations in the same way. Then the result
+ should look like:</para>
+
+ <programlisting>package org.exoplatform.services.rest.example;
+
+import org.exoplatform.services.rest.HTTPMethod;
+import org.exoplatform.services.rest.OutputTransformer;
+import org.exoplatform.services.rest.QueryTemplate;
+import org.exoplatform.services.rest.Response;
+import org.exoplatform.services.rest.URIParam;
+import org.exoplatform.services.rest.URITemplate;
+import org.exoplatform.services.rest.container.ResourceContainer;
+import org.exoplatform.services.rest.transformer.StringOutputTransformer;
+
+@URITemplate("/calculator/{item1}/{item2}/")
+(a)OutputTransformer(StringOutputTransformer.class)
+public class Calculator implements ResourceContainer {
+
+ @QueryTemplate("operation=add")
+ @HTTPMethod("GET")
+ public Response add(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=subtract")
+ @HTTPMethod("GET")
+ public Response subtract(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" - ").append(item2).append(" =
").append(item1 - item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=multiply")
+ @HTTPMethod("GET")
+ public Response multiply(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" * ").append(item2).append(" =
").append(item1 * item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=divide")
+ @HTTPMethod("GET")
+ public Response divide(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" / ").append(item2).append(" =
").append(item1 / item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+}</programlisting>
+
+ <para>So we are done with the source code.</para>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>Create the directory conf/portal and create the file
+ configuration.xml in it. Add the following code to this file:</para>
+
+ <programlisting><?xml version="1.0"
encoding="ISO-8859-1"?>
+<configuration>
+ <component>
+
<type>org.exoplatform.services.rest.example.Calculator</type>
+ </component>
+</configuration></programlisting>
+ </section>
+
+ <section>
+ <title>Build</title>
+
+ <para>Now we must create the following directory structure to get the
+ possibility to build the source code using maven.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-build-process.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>Then create the file pom.xml using the following:</para>
+
+ <programlisting><project>
+ <parent>
+ <groupId>org.exoplatform.ws</groupId>
+ <artifactId>config</artifactId>
+ <version>trunk</version>
+ </parent>
+
+ <modelVersion&#624;.0.0</modelVersion>
+ <groupId>org.exoplatform.ws.rest</groupId>
+ <artifactId>simple.calculator</artifactId>
+ <packaging>jar</packaging>
+ <version>trunk</version>
+ <description>Simple REST service</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.exoplatform.ws.rest</groupId>
+ <artifactId>exo.rest.core</artifactId>
+ <version>trunk</version>
+ </dependency>
+ </dependencies>
+</project></programlisting>
+
+ <para>Build this by executing the command:</para>
+
+ <programlisting>andrew@ubu:~/workspace/calculator$ mvn clean
install</programlisting>
+ </section>
+
+ <section>
+ <title>Deploy</title>
+
+ <para>We have done all now. Then copy the jar file from the target
+ directory of project exo-tomcat into the server with all prepared stuff
+ for REST services. (You can download it here: <link
+
linkend="???">http://forge.objectweb.org/project/download.ph...
+
+ <para>So just put the jar file into the lib directory of the tomcat and
+ restart it. In the console you should see this message:</para>
+
+ <programlisting>[INFO] ResourceBinder - Bind new ResourceContainer:
org.exoplatform.services.rest.example.Calculator@19846fd</programlisting>
+
+ <para>This message indicates that our service was found, bound and is
+ ready to work</para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <para>Open your browser and type the following URL: <link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=add</link>
+ and you should see the next page:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-run-process.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>The service is working. This is a very simple example, but it should
+ help developers use the REST framework.</para>
+
+ <para>Try to check other URLs.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=subtract</link>
+ - must give "12 - 5 = 7";</para>
+ </listitem>
+
+ <listitem>
+ <para><link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=multiply</link>
+ - must give "12 * 5 = 60";</para>
+ </listitem>
+
+ <listitem>
+ <para><link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=divide</link>-
+ must give "12 / 5 = 2" (we are working with integers!);</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>