<?xml version="1.0" encoding="UTF-8"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
-->
<chapter id="ref_guide_slice">
  <title>
    Slice: Distributed Persistence
  </title>
  <para>
  The standard JPA runtime environment works with a <emphasis>single</emphasis>
  database instance. <emphasis>Slice</emphasis> is a plug-in module for OpenJPA
  to work with <emphasis>multiple</emphasis> databases within the same
  transaction. Following sections describe the features and usage of Slice for
  distributed database environment.
  </para>

  <section id="slice_overview">
    <title>Overview</title>
    <para>
    Enterprise applications are increasingly deployed in distributed database
    environment. A distributed, horizontally-partitioned
    database environment can be an effective scaling strategy for growing data
	volume, to support multiple clients on a multi-tenant hosting platform and
	many other practical scenarios that can benefit from data partitioning.
    </para>

    <para>
    Any JPA-based user application has to address demanding technical and
    conceptual challenges to interact with multiple physical databases
    within a single transaction.
    OpenJPA Slice encapsulates the complexity of distributed database environment
    via the abstraction of <emphasis>virtual</emphasis> database which internally
    manages multiple physical database instances referred
    as <emphasis>slice</emphasis>.
    <emphasis>Virtualization</emphasis> of distributed databases makes OpenJPA
	object management kernel and the user application to work in the same way as
	in the case of a single physical database.
    </para>
  </section>

    <section id="features_and_limitations">
       <title>Salient Features</title>
         <section><title>Transparency</title>
            <para>
			  The primary design objective for Slice is to make the user
			  application transparent to the change in storage strategy where
			  data resides in multiple (possibly heterogeneous) databases instead
			  of a single database. Slice achieves this transparency by
			  virtualization of multiple databases as a single database such
			  that OpenJPA object management kernel continues to interact in
			  exactly the same manner with storage layer. Similarly,
              the existing application or the persistent domain model requires
              <emphasis>no change</emphasis> to upgrade from a single database
              to a distributed database environment.
            </para>
			<para>
			  An existing application developed for a single database can be
			  adapted to work with multiple databases purely by configuring
			  a persistence unit via <classname>META-INF/persistence.xml</classname>.
			</para>
         </section>

		<section><title>Scaling</title>
			<para>
			The primary performance characteristics for Slice is to scale against
			growing data volume by <emphasis>horizontal</emphasis> partitioning data
			across many databases.
			</para>
			<para>
			Slice executes the database operations such as query or flush <emphasis>in
			parallel</emphasis> across each physical database. Hence, scaling characteristics
			against data volume are bound by the size of the maximum data
			partition instead of the size of the entire data set. The use cases
			where the data is naturally amenable to horizontal partitions,
			for example, by temporal interval (e.g. Purchase Orders per month)
			or by geographical regions (e.g. Customer by Zip Code) can derive
			significant performance benefit and favorable scaling behavior by
			using Slice.
			</para>
		</section>

        <section><title>Distributed Query</title>
            <para>
            The queries are executed in parallel across one or more slices and the
			individual query results are merged into a single list before being
			returned to the caller application. The <emphasis>merge</emphasis> operation is
			more complex for the queries that involve sorting and/or specify a
			range. Slice supports both sorting and range queries.
            </para>
			<para>
            Slice also supports aggregate queries where the aggregate operation
			is <emphasis>commutative</emphasis> to partitioning such as
			<classname>COUNT()</classname> or <classname>MAX()</classname> but not <classname>AVG()</classname>.
            </para>

            <para>
            By default, any query is executed against all available slices.
			However, the application can target the query only to a subset of
			slices by setting <emphasis>hint</emphasis> on <classname>jakarta.persistence.Query</classname>.
			The hint key is  <classname>openjpa.hint.slice.Target</classname> and
            hint value is an array of slice identifiers. The following
            example shows how to target a query only to a pair of slices
			with logical identifier <classname>"One"</classname> and <classname>"Two"</classname>.

            <programlisting>
              <![CDATA[EntityManager em = ...;
              em.getTransaction().begin();
              String hint = "openjpa.hint.slice.Target";
              Query query = em.createQuery("SELECT p FROM PObject")
				              .setHint(hint, new String[]{"One", "Two"});
              List result = query.getResultList();
              // verify that each instance is originating from the hinted slices
              for (Object pc : result) {
                 String sliceOrigin = SlicePersistence.getSlice(pc);
                 assertTrue ("One".equals(sliceOrigin) || "Two".equals(sliceOrigin));
              }
              ]]>
            </programlisting>
            </para>

            <para>
            To confine queries to a subset of slices via setting query hints can be considered
            intrusive to existing application. The alternative means of targeting queries is to
            configure a <emphasis>Query Target Policy</emphasis>. This policy is configured
            via plug-in property <classname>openjpa.slice.QueryTargetPolicy</classname>. The
            plug-in property is fully-qualified class name of an implementation
            for <classname>org.apache.openjpa.slice.QueryTargetPolicy</classname> interface.
            This interface contract allows a user application to target a query to a subset
            of slices based on the query and its bound parameters. The query target policy is consulted
            only when no explicit target hint is set on the query. By default, the policy
            executes a query on all available slices.
            </para>

            <para>
            A similar policy interface <classname>org.apache.openjpa.slice.FinderTargetPolicy</classname>
            is available to target queries that originate from <classname>find()</classname>
            by primary key. This finder target policy is consulted
            only when no explicit target hint is set on the current fetch plan. By default, the policy
            executes a query on all available slices to find an instance by its primary key.
            </para>
         </section>

         <section><title>Data Distribution</title>
            <para>
             The user application decides how the newly persistent instances be
             distributed across the slices. The user application specifies the
			 data distribution policy by implementing
             <classname>org.apache.openjpa.slice.DistributionPolicy</classname>.

			 The  <classname>DistributionPolicy</classname> interface
			 is simple with a single method. The complete listing of the
			 documented interface follows:
		   <programlisting>
		   <![CDATA[
			public interface DistributionPolicy {
			/**
			 * Gets the name of the slice where the given newly persistent
			 * instance will be stored.
			 *
			 * @param pc The newly persistent or to-be-merged object.
			 * @param slices name of the configured slices.
			 * @param context persistence context managing the given instance.
			 *
			 * @return identifier of the slice. This name must match one of the
			 * configured slice names.
			 * @see DistributedConfiguration#getSliceNames()
			 */
			String distribute(Object pc, List<String> slices, Object context);
			}
		]]>
       </programlisting>
        </para>

		 <para>
			 Slice runtime invokes this user-supplied method for the newly
			 persistent instance that is explicit argument of the
			 <classname>jakarta.persistence.EntityManager.persist(Object pc)</classname>
			 method. The user application must return a valid slice name from
			 this method to designate the target slice for the given instance.
			 The data distribution policy may be based on the attribute
			 of the data itself. For example, all Customer whose first name
			 begins with character 'A' to 'M' will be stored in one slice
			 while names beginning with 'N' to 'Z' will be stored in another
			 slice. The noteworthy aspect of such policy implementation is
			 the attribute values that participate in
			 the distribution policy logic should be set before invoking
			 <classname>EntityManager.persist()</classname> method.
		 </para>

		<para>
			The user application needs to specify the target slice <emphasis>only</emphasis>
			for the <emphasis>root</emphasis> instance i.e. the explicit argument for the
			<classname>EntityManager.persist(Object pc)</classname> method. Slice computes
			the transitive closure of the graph i.e. the set of all instances
			directly or indirectly reachable from the root instance and stores
			them in the same target slice.
		</para>

		 <para>
		 Slice tracks the original database for existing instances. When
		 an application issues a query, the resultant instances can be loaded
		 from different slices. As Slice tracks the original slice for each
		 instance, any subsequent update to an instance is committed to the
		 appropriate original database slice.
		</para>

            <note>
            <para>
            You can find the original slice of an instance <classname>pc</classname> by
            the static utility method
            <methodname>SlicePersistence.getSlice(pc)</methodname>.
            This method returns the slice identifier associated with the
            given <emphasis>managed</emphasis> instance. If the instance is not
            being managed then the method return null because any unmanaged or
            detached instance is not associated with any slice.
            </para>
            </note>
         </section>

		<section><title>Data Replication</title>
			<para>
			While Slice ensures that the transitive closure is stored in the
			same slice, there can be data elements that are commonly referred by
			many instances such as Country or Currency code. Such quasi-static
			master data can be stored as identical copies in multiple slices.
			The user application must enumerate the replicated entity type names in
			<classname>openjpa.slice.ReplicatedTypes</classname> as a comma-separated list
			and implement a <classname>org.apache.openjpa.slice.ReplicationPolicy</classname>
			interface. The <classname>ReplicationPolicy</classname> interface
			is quite similar to <classname>DistributionPolicy</classname>
			interface except it returns an array of target slice names instead
			of a single slice.
			<programlisting>
           <![CDATA[
			 String[] replicate(Object pc, List<String> slices, Object context);
        ]]>
       </programlisting>
		</para>
			<para>
				The default implementation assumes that replicated instances are
				stored in all available slices. If any such replicated instance
				is modified then the modification is updated to all target slices
				to maintain the critical assumption that the state of a replicated
				instance is identical across all its target slices.
			</para>
		</section>

         <section><title>Heterogeneous Database</title>
            <para>
              Each slice can be configured independently with its own JDBC
              driver and other connection parameters. Hence the target database
              environment can constitute of heterogeneous databases.
            </para>
        </section>

         <section><title>Distributed Transaction</title>
            <para>
            The database slices participate in a global transaction provided
            each slice is configured with a XA-compliant JDBC driver, even
            when the persistence unit is configured for <classname>RESOURCE_LOCAL</classname>
            transaction.
            </para>
            <para>
            <warning>
            If any of the configured slices is not XA-compliant <emphasis>and</emphasis>
            the persistence unit is configured for <classname>RESOURCE_LOCAL</classname>
            transaction then each slice is committed without any two-phase
            commit protocol. If commit on any slice fails, then atomic nature of
            the transaction is not ensured.
            </warning>
            </para>
          </section>

         <section id="collocation_constraint"><title>Collocation Constraint</title>
            <para>
            No relationship can exist across database slices. In O-R mapping parlance,
            this condition translates to the limitation that the transitive closure of an object graph must be
            <emphasis>collocated</emphasis> in the same database.
            For example, consider a domain model where Person relates to Address.
            Person X refers to Address A while Person Y refers to Address B.
            Collocation Constraint means that <emphasis>both</emphasis> X and A
            must be stored in the same
            database slice. Similarly Y and B must be stored in a single slice.
            </para>
            <para>
            Slice, however, helps to maintain collocation constraint automatically.
            The instances in the closure set of any newly persistent instance
            reachable via cascaded relationship is stored in the same slice.
            The user-defined distribution policy requires to supply the slice
            for the root instance only.
            </para>
         </section>
    </section>

  <section id="slice_configuration">
    <title>Usage</title>
    <para>
     Slice is activated via the following property settings:
    </para>
    <section>
      <title>How to activate Slice Runtime?</title>
      <para>
       The basic configuration property is
       <programlisting>
        <![CDATA[ <property name="openjpa.BrokerFactory" value="slice"/>]]>
       </programlisting>
       This critical configuration activates a specialized object management
	   kernel that can work against multiple databases.
      </para>
    </section>

    <section>
      <title>How to configure each database slice?</title>
      <para>
      Each database slice is identified by a logical name unique within a
      persistent unit. The list of the slices is specified by
      <classname>openjpa.slice.Names</classname> property.
      For example, specify three slices named <classname>"One"</classname>,
      <classname>"Two"</classname> and <classname>"Three"</classname> as follows:
      <programlisting>
      <![CDATA[ <property name="openjpa.slice.Names" value="One, Two, Three"/>]]>
      </programlisting>
      </para>
      <para>
      This property is not mandatory. If this property is not specified then
      the configuration is scanned for logical slice names. Any property
      <classname>"abc"</classname> of the form <classname>openjpa.slice.XYZ.abc</classname> will
      register a slice with logical
      name <classname>"XYZ"</classname>.
      </para>
      <para>
      The order of the names is significant when no <classname>openjpa.slice.Master</classname>
      property is not specified. The persistence unit is then scanned to find
      all configured slice names and they are ordered alphabetically.
      </para>

      <para>
       Each database slice properties can be configured independently.
       For example, the
       following configuration will register two slices with logical name
       <classname>One</classname> and <classname>Two</classname>.
       <programlisting>
        <![CDATA[<property name="openjpa.slice.One.ConnectionURL" value="jdbc:mysql:localhost//slice1"/>
        <property name="openjpa.slice.Two.ConnectionURL" value="jdbc:mysql:localhost//slice2"/>]]>
       </programlisting>
      </para>

      <para>
       Any OpenJPA specific property can be configured per slice basis.
       For example, the following configuration will use two different JDBC
       drivers for slice <classname>One</classname> and <classname>Two</classname>.
       <programlisting>
        <![CDATA[<property name="openjpa.slice.One.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
        <property name="openjpa.slice.Two.ConnectionDriverName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>]]>
       </programlisting>
      </para>

      <para>
        Any property if unspecified for a particular slice will be defaulted by
        corresponding OpenJPA property. For example, consider following three slices
        <programlisting>
         <![CDATA[<property name="openjpa.slice.One.ConnectionURL"          value="jdbc:mysql:localhost//slice1"/>
         <property name="openjpa.slice.Two.ConnectionURL"          value="jdbc:mysql:localhost//slice2"/>
         <property name="openjpa.slice.Three.ConnectionURL"        value="jdbc:oracle:localhost//slice3"/>

         <property name="openjpa.ConnectionDriverName"     value="com.mysql.jdbc.Driver"/>
         <property name="openjpa.slice.Three.ConnectionDriverName" value="oracle.jdbc.Driver"/>]]>
        </programlisting>
        In this example, <classname>Three</classname> will use slice-specific
        <classname>oracle.jdbc.Driver</classname> driver while slice
        <classname>One</classname> and <classname>Two</classname> will use
        the driver <classname>com.mysql.jdbc.Driver</classname> as
        specified by <classname>openjpa.ConnectionDriverName</classname>
        property value.
    </para>

        <para>
            A connection pool may also be used with Slice by using the <literal>openjpa.ConnectionProperties</literal> property.
            For example to use commons-dbcp with Derby you might use the following properties :
            <programlisting>
                <![CDATA[<property name="openjpa.BrokerFactory" value="slice"/>
                <property name="openjpa.ConnectionDriverName" value="org.apache.commons.dbcp.BasicDataSource"/>
                <property name="openjpa.slice.Names" value="One,Two"/>
                <property name="openjpa.slice.Master" value="Two"/>

                <property name="openjpa.slice.One.ConnectionProperties" value="Url=jdbc:derby:target/database/openjpa-slice1;create=true, DriverClassName=org.apache.derby.jdbc.EmbeddedDriver"/>
                <property name="openjpa.slice.Two.ConnectionProperties" value="Url=jdbc:derby:target/database/openjpa-slice2;create=true, DriverClassName=org.apache.derby.jdbc.EmbeddedDriver"/>

                <property name="openjpa.jdbc.DBDictionary" value="derby"/>]]>
            </programlisting>
            <note>
                <para>
                    Be aware that you need to set the DBDictionary when using commons-dbcp.
                </para>
            </note>
        </para>
    </section>

    <section id="distribution_policy">
       <title>Implement DistributionPolicy interface</title>
       <para>
        Slice needs to determine which slice will persist a new instance.
        The application can only decide this policy (for example,
        all PurchaseOrders before April 30 goes to slice <classname>One</classname>,
        all the rest goes to slice <classname>Two</classname>). This is why
        the application has to implement
        <classname>org.apache.openjpa.slice.DistributionPolicy</classname> and
        specify the implementation class in configuration
        <programlisting>
         <![CDATA[ <property name="openjpa.slice.DistributionPolicy" value="com.acme.foo.MyOptimialDistributionPolicy"/>]]>
        </programlisting>
       </para>

       <para>
        The interface <classname>org.apache.openjpa.slice.DistributionPolicy</classname>
        is simple with a single method. The complete listing of the
        documented interface follows:
       <programlisting>
       <![CDATA[
public interface DistributionPolicy {
    /**
     * Gets the name of the slice where a given instance will be stored.
     *
     * @param pc The newly persistent or to-be-merged object.
     * @param slices name of the configured slices.
     * @param context persistence context managing the given instance.
     *
     * @return identifier of the slice. This name must match one of the
     * configured slice names.
     * @see DistributedConfiguration#getSliceNames()
     */
    String distribute(Object pc, List<String> slices, Object context);
}
]]>
       </programlisting>
        </para>

        <para>
        While implementing a distribution policy the most important thing to
        remember is <link linkend="collocation_constraint">collocation constraint</link>.
        Because Slice can not establish or query any cross-database relationship, all the
        related instances must be stored in the same database slice.

        Slice can determine the closure of a root object by traversal of
        cascaded relationships. Hence user-defined policy has to only decide the
        database for the root instance that is the explicit argument to
        <methodname>EntityManager.persist()</methodname> call.
        Slice will ensure that all other related instances that get persisted by cascade
        are assigned to the same database slice as that of the root instance.
        However, the user-defined distribution policy must return the
        same slice identifier for the instances that are logically related but
        not cascaded for persist.
        </para>
    </section>

    <section id="replication_policy">
       <title>Implement ReplicationPolicy interface</title>
		<para>
			The entities that are enumerated in <classname>openjpa.slice.ReplicatedTypes</classname>
			property can be stored in multiple slices as identical copies.
        Specify the implementation class of <classname>ReplicationPolicy</classname> in configuration as
        <programlisting>
         <![CDATA[ <property name="openjpa.slice.ReplicationPolicy" value="com.acme.foo.MyReplicationPolicy"/>]]>
        </programlisting>
		</para>
    </section>
  </section>


  <section>
  <title>Configuration Properties</title>
    <para>
    The properties to configure Slice can be classified in two broad groups.
The <emphasis>global</emphasis> properties apply to all the slices, for example,
the thread pool used to execute the queries in parallel or the transaction
manager used to coordinate transaction across multiple slices.
The <emphasis>per-slice</emphasis> properties apply to individual slice, for example,
the JDBC connection URL of a slice.
   </para>

   <section>
     <title>Global Properties</title>

     <section>
        <title>openjpa.slice.DistributionPolicy</title>
        <para>
         This <emphasis>mandatory</emphasis> plug-in property determines how newly
         persistent instances are distributed across individual slices.
         The value of this property is a fully-qualified class name that implements
         <ulink url="../../apidocs/org/apache/openjpa/slice/DistributionPolicy.html">
         <classname>org.apache.openjpa.slice.DistributionPolicy</classname>
         </ulink> interface.
        </para>
     </section>

     <section><title>openjpa.slice.Lenient</title>
      <para>
        This boolean plug-in property controls the behavior when one or more slice
        can not be connected or unavailable for some other reasons.
        If <classname>true</classname>, the unreachable slices are ignored. If
        <classname>false</classname> then any unreachable slice will raise an exception
        during startup.
        </para>
        <para>
        By default this value is set to <classname>false</classname> i.e. all configured
        slices must be available.
        </para>
     </section>

     <section>
      <title>openjpa.slice.Master</title>
		 <para>
			 The user application often directs OpenJPA to generate primary keys
			 for persistence instances automatically or from a specific database
			 sequence. For such primary key value generation strategy where
			 a database instance is required, Slice uses a designated slice
			 referred to as <emphasis>master</emphasis> slice.
		 </para>
         <para>
			 The master slice can be specified explicitly via
			 <classname>openjpa.slice.Master</classname> property and whose value is one
			 of the configured slice names. If this property is not explicitly
			 specified then, by default, the master slice is the first slice
			 in the list of configured slice names.
       </para>
       <para>
              <warning>
              Currently, there is no provision to use sequence from
              multiple slices.
              </warning>
       </para>
     </section>

     <section>
        <title>openjpa.slice.Names</title>
        <para>
         This plug-in property can be used to register the logical slice names.
         The value of this property is comma-separated list of slice names.
         The ordering of the names in this list is
         <emphasis>significant</emphasis> because
         <link linkend="distribution_policy">DistributionPolicy</link> and
		<link linkend="replication_policy">ReplicationPolicy</link> receive
         the input argument of the slice names in the same order.
        </para>
        <para>
        If logical slice names are not registered explicitly via this property,
        then all logical slice names available in the persistence unit are
        registered. The ordering of the slice names in this case is alphabetical.
        </para>
        <para>
        If logical slice names are registered explicitly via this property, then
        any logical slice that is available in the persistence unit but excluded
        from this list is ignored.
        </para>
     </section>

     <section>
        <title>openjpa.slice.ThreadingPolicy</title>
        <para>
        This plug-in property determines the nature of thread pool being used
        for database operations such as query or flush on individual slices.
        The value of the property is a
        fully-qualified class name that implements
        <ulink url="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html">
        <classname>java.util.concurrent.ExecutorService</classname>
        </ulink> interface.
        Two pre-defined pools can be chosen via their aliases namely
        <classname>fixed</classname> or <classname>cached</classname>.
        </para>
        <para>
        The pre-defined alias <classname>cached</classname> activates a
        <ulink url="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool()">cached thread pool</ulink>.
        A cached thread pool creates new threads as needed, but will reuse
        previously constructed threads when they are available. This pool
        is suitable in scenarios that execute many short-lived asynchronous tasks.
        The way Slice uses the thread pool to execute database operations is
        akin to such scenario and hence <classname>cached</classname> is the default
        value for this plug-in property.
        </para>
        <para>
        The <classname>fixed</classname> alias activates a
        <ulink url="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)">fixed thread pool</ulink>.
        The fixed thread pool can be further parameterized with
        <classname>CorePoolSize</classname>, <classname>MaximumPoolSize</classname>,
        <classname>KeepAliveTime</classname> and <classname>RejectedExecutionHandler</classname>.
        The meaning of these parameters are described in
        <ulink url="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html">JavaDoc</ulink>.
        The users can exercise finer control on thread pool behavior via these
        parameters.
        By default, the core pool size is <classname>10</classname>, maximum pool size is
        also <classname>10</classname>, keep alive time is <classname>60</classname> seconds and
        rejected execution is
        <ulink url="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.AbortPolicy.html">aborted</ulink>.
        </para>
        <para>
        Both of the pre-defined aliases can be parameterized with a fully-qualified
        class name that implements
        <ulink url="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadFactory.html">
        <classname>java.util.concurrent.ThreadFactory</classname>
        </ulink> interface.
        </para>
     </section>

     <section>
      <title>openjpa.slice.TransactionPolicy</title>
      <para>
      This plug-in property determines the policy for transaction commit
      across multiple slices. The value of this property is a fully-qualified
      class name that implements
      <ulink url="http://download.oracle.com/javaee/6/api/javax/transaction/TransactionManager.html">
      <classname>javax.transaction.TransactionManager</classname>
      </ulink> interface.
      </para>
      <para>
      Three pre-defined policies can be chosen
      by their aliases namely <classname>default</classname>,
      <classname>xa</classname> and <classname>jndi</classname>.
      </para>
      <para>
      The <classname>default</classname> policy employs
      a Transaction Manager that commits or rolls back transaction on individual
      slices <emphasis>without</emphasis> a two-phase commit protocol.
      It does <emphasis>not</emphasis>
      guarantee atomic nature of transaction across all the slices because if
      one or more slice fails to commit, there is no way to rollback the transaction
      on other slices that committed successfully.
      </para>
      <para>
      The <classname>xa</classname> policy employs a Transaction Manager that that commits
      or rolls back transaction on individual
      slices using a two-phase commit protocol. The prerequisite to use this scheme
      is, of course, that all the slices must be configured to use
      XA-compliant JDBC driver.
      </para>
      <para>
      The <classname>jndi</classname> policy employs a Transaction Manager by looking up the
      JNDI context. The prerequisite to use this transaction
      manager is, of course, that all the slices must be configured to use
      XA-compliant JDBC driver.
      <warning>This JNDI based policy is not available currently.</warning>
      </para>
    </section>
   </section>

   <section>
     <title>Per-Slice Properties</title>
     <para>
     Any OpenJPA property can be configured for each individual slice. The property name
     is of the form <classname>openjpa.slice.[Logical slice name].[OpenJPA Property Name]</classname>.
     For example, <classname>openjpa.slice.One.ConnectionURL</classname> where <classname>One</classname>
     is the logical slice name and <classname>ConnectionURL</classname> is an OpenJPA property
     name.
     </para>
     <para>
     If a property is not configured for a specific slice, then the value for
     the property equals to the corresponding <classname>openjpa.*</classname> property.
     </para>
   </section>

  </section>

</chapter>

