<?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="user_manual">
  <title>User Manual</title>
  <para>
  Slice allows any OpenJPA based application to work with data from 
  multiple databases within the same transaction. Slice does not require
  any change to the existing OpenJPA application. The features offered in
  Slice can be available to any OpenJPA application by simply configuring
  a persistence unit in <code>META-INF/persistence.xml</code>.
  </para>
  
  <section id="configuration">
    <title>Configuration</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 factory class aliased
       as <code>slice</code> to create 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 <code>slice.Names</code> property.
      For example, specify three slices named <code>"One"</code>, 
      <code>"Two"</code> and <code>"Three"</code> as follows:
      <programlisting>
      <![CDATA[ <property name="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
      of the form <code>slice.XYZ.abc</code> will register a slice with logical
      name <code>"XYZ"</code>.
      </para>
      <para>
      The order of the names can be significant if no <code>slice.Master</code>
      property is specified. 
      </para>
      
      <para>
       Each database slice can be configured independently. For example, the
       following configuration will register two slices with logical name 
       <code>One</code> and <code>Two</code>.
       <programlisting> 
        <![CDATA[<property name="slice.One.ConnectionURL" value="jdbc:mysql:localhost//slice1"/>
        <property name="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 <code>One</code> and <code>Two</code>.
       <programlisting> 
        <![CDATA[<property name="slice.One.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
        <property name="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="slice.One.ConnectionURL"          value="jdbc:mysql:localhost//slice1"/>
         <property name="slice.Two.ConnectionURL"          value="jdbc:mysql:localhost//slice2"/>
         <property name="slice.Three.ConnectionURL"        value="jdbc:oracle:localhost//slice3"/>

         <property name="openjpa.ConnectionDriverName"     value="com.mysql.jdbc.Driver"/>
         <property name="slice.Three.ConnectionDriverName" value="oracle.jdbc.Driver"/>]]>
        </programlisting> 
        In this example, <code>Three</code> will use slice-specific
        <code>oracle.jdbc.Driver</code> driver while slice
        <code>One</code> and <code>Two</code> will use
        the driver <code>com.mysql.jdbc.Driver</code> as 
        specified by <code>openjpa.ConnectionDriverName</code> 
        property value.
      </para>
    </section>
     
    <section>
       <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 <code>One</code>,
        all the rest goes to slice <code>Two</code>). This is why
        the application has to implement 
        <code>org.apache.openjpa.slice.DistributionPolicy</code> and
        specify the implementation class in configuration
        <programlisting> 
         <![CDATA[ <property name="slice.DistributionPolicy" value="com.acme.foo.MyOptimialDistributionPolicy"/>]]>
        </programlisting>
       </para>
       
       <para>
        The interface <code>org.apache.openjpa.slice.DistributionPolicy</code>
        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 opaque context for future use.
     * 
     * @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 
        <code>EntityManager.persist()</code> call.
        Slice will ensure that all other related instances that gets persisted by cascade
        is 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>
    </section>
  </section>
  &homer;
</chapter>
  