<?xml version="1.0" encoding="UTF-8"?>
<chapter id="jcr">
  <title>Java Content Repository (JSR-170)</title>

  <sect1>
    <title>Introduction</title>

    <para>JSR-170 defines "a standard, implementation independent, way to
    access content bi-directionally on a granular level within a content
    repository. A Content Repository is a high-level information management
    system that is a superset of traditional data repositories. A content
    repository implements "content services" such as: author based versioning,
    full textual searching, fine grained access control, content
    categorization and content event monitoring. It is these "content
    services" that differentiate a Content Repository from a Data Repository."
    (taken from the JSR-170 description page).</para>

    <para>More information about Java Content Repository (from here on refered
    as JCR) can be found at <ulink
    url="http://www.jcp.org/en/jsr/detail?id=170">here</ulink>.</para>

    <para>The package has been designed to resemble as much as possible the
    ORM packages from the main Spring distribution. Users familiar with these
    can start using the JCR-support right away without much hassle; the
    documentation resembles the main documentation structure also. For those
    who haven't used them, please refer to the main Spring documentation,
    mainly <ulink
    url="http://static.springframework.org/spring/docs/1.2.x/reference/orm.html">chapter
    12 (Data Access using O/R Mappers)</ulink> as the current documentation
    focuses on the JCR specific details, the Spring infrastructure being
    outside the scope of this document. As the ORM package, the main reason
    for the JCR support is to ease development using Spring unchecked
    DAOexception hierarchy, integrated transaction management, ease of
    testing.</para>

    <para>Before going any further I would like to thank Guillaume Bort
    &lt;guillaume.bort@zenexity.fr&gt; and Brian Moseley
    &lt;bcm@osafoundation.org&gt; which worked on some implementation of their
    own and were kind enough to provide their code and ideas when I started
    working on this package.</para>
  </sect1>

  <sect1>
    <title>JSR standard support</title>

    <para>The standard support works only with the JSR-170 API (represented
    by<literal> javax.jcr</literal> package) without making any use of
    specific features of the implementations (which we will discuss
    later).</para>

    <sect2>
      <title>SessionFactory</title>

      <para>JSR-170 doesn't provide a notion of
      <literal>SessionFactory</literal> but rather a repository which based on
      the credentials and workspace provided returnes a session. The
      <literal>SessionFactory</literal> interface describes a basic contract
      for retrieving session without any knowledge of credentials, it's
      implementation acting as a wrapper around the
      <literal>javax.jcr.Repository</literal>:<programlisting>&lt;bean id="sessionFactory" class="org.springmodules.jcr.JcrSessionFactory"&gt;
 &lt;property name="repository" ref="repository"/&gt;
&lt;/bean&gt;</programlisting>The only requirement for creating a
      sessionFactory is the repository (which will be discussed later). There
      are cases were credentials have to be submitted. One problem that new
      users have is that <literal>javax.jcr.SimpleCredentials</literal>
      requires a char array (char[]) as constructor parameter and not a String
      and the current Spring distribution (1.2.5) does not contains a
      <literal>PropertyEditor</literal> for char arrays. The following
      examples (taken from the sample) shows how we can use String statical
      methods to obtain a char array:<programlisting>&lt;bean id="sessionFactory" class="org.springmodules.jcr.JcrSessionFactory"&gt;
  &lt;property name="repository" ref="repository"/&gt;
  &lt;property name="credentials"&gt;
   &lt;bean class="javax.jcr.SimpleCredentials"&gt;
    &lt;constructor-arg index="0" value="bogus"/&gt;
    &lt;!-- create the credentials using a bean factory --&gt;
    &lt;constructor-arg index="1"&gt;
     &lt;bean factory-bean="password"
          factory-method="toCharArray"/&gt;
    &lt;/constructor-arg&gt;
   &lt;/bean&gt;
  &lt;/property&gt;
&lt;/bean&gt;

&lt;!-- create the password to return it as a char[] --&gt;
&lt;bean id="password" class="java.lang.String"&gt;
  &lt;constructor-arg index="0" value="pass"/&gt;
&lt;/bean&gt;</programlisting>Using the static <literal>toCharArray</literal>
      (from <literal>java.lang.String</literal>) we transformed the String
      supplied as password (with value 'pass') to
      <literal>SimpleCredentials</literal> for user 'bogus'. Note that
      <literal>JcrSessionFactory</literal> can also register namespaces, add
      listeners and has utility methods for determing the underlying
      repository properties - see the javadoc and the samples for more
      information.</para>

      <sect3>
        <title>Namespace registration</title>

        <para>The <literal>JcrSessionFactory</literal> allows namespace
        registration based on the standard JSR-170 API. It is possible to
        override the existing namespaces (if any) and register namespaces just
        during the existence of the <literal>JcrSessionFactory</literal>. By
        default, the given namespaces are registered only if they occupy free
        prefixes and be kept in the repository even after the
        <literal>SessionFactory</literal> shuts down.</para>

        <para>To register the namespaces, simply pass them as a property
        object, with the key representing the prefix and the value,
        representing the namespace:</para>

        <programlisting>&lt;bean id="sessionFactory" class="org.springmodules.jcr.JcrSessionFactory"&gt;
  ...
 &lt;property name="namespaces"&gt;
  &lt;props&gt;
    &lt;prop key="foo"&gt;http://bar.com/jcr&lt;/prop&gt;
    &lt;prop key="hocus"&gt;http://pocus.com/jcr&lt;/prop&gt;
   &lt;/props&gt;
 &lt;/property&gt;
&lt;/bean&gt;</programlisting>

        <para>One can customize the behavior of the
        <literal>JcrSessionFactory</literal> using 3 flags:</para>

        <itemizedlist>
          <listitem>
            <para><emphasis>forceNamespacesRegistration</emphasis> - indicates
            if namespaces already registered under the given prefixes will be
            overridden or not(default). If <literal>true</literal>, the
            existing namespaces will be unregistered before registering the
            new ones. Note however that most (if not all) JCR implementations
            do not support namespace registration.</para>
          </listitem>

          <listitem>
            <para><emphasis>keepNewNamespaces</emphasis> - indicates if the
            given namespaces are kept, after being registered (default) or
            unregistered on the <literal>SessionFactory</literal> destruction.
            If <literal>true</literal>, the namespaces unregistered during the
            registration process will be registered back on the repository.
            Again, as noted above, this requires the JCR implementation to
            support namespace un-registration.</para>
          </listitem>

          <listitem>
            <para><emphasis>skipExistingNamespaces</emphasis> - indicates if
            the during the registration process, the existing namespaces are
            being skipped (default) or not. This flag is used as a workaround
            for repositories that don't support namespace un-registration
            (which render the <emphasis>forceNamespacesRegistration</emphasis>
            and <emphasis>keepNewNamespaces</emphasis> useless). If
            <literal>true</literal>, will allow registration of new namespaces
            only if they use a free prefix; if the prefix is taken, the
            namespace registration is skipped.</para>
          </listitem>
        </itemizedlist>
      </sect3>

      <sect3>
        <title>Event Listeners</title>

        <para>JSR-170 repositories which support
        <emphasis>Observation</emphasis>, allow the developer to monitor
        various event types inside a workspace. However, any potential
        listener has to be register per-session basis which makes the session
        creation difficult. <literal>JcrSessionFactory</literal> eases the
        process by supporting global (across all sessions) listeners through
        its <literal>EventListenerDefinition</literal>, a simple wrapper class
        which associates a JCR <literal>EventListener</literal> with event
        types, node paths and uuids (which allows, if desired, the same
        <literal>EventListener</literal> instance to be reused across the
        sessions and event types).</para>

        <para>Configuring the listener is straight forward:</para>

        <programlisting>&lt;bean id="sessionFactory" class="org.springmodules.jcr.JcrSessionFactory"&gt;
  ...
  &lt;property name="eventListeners"&gt;
   &lt;list&gt;
    &lt;bean class="org.springmodules.jcr.EventListenerDefinition"&gt;
     &lt;property name="listener"&gt;
      &lt;bean class="org.springmodules.examples.jcr.DummyEventListener"/&gt;
     &lt;/property&gt;
     &lt;property name="absPath" value="/rootNode/someFolder/someLeaf"/&gt;
    &lt;/bean&gt;
   &lt;/list&gt;
  &lt;/property&gt;
&lt;/property&gt;</programlisting>
      </sect3>

      <sect3>
        <title>NodeTypeDefinition registration</title>

        <para>JCR 1.0 specifications allows custom node types to be registered
        in a repository but it doesn't standardises the process, thus each JCR
        implementation comes with its own approach. For Jackrabbit, the JCR
        module provides a dedicated <literal>SessionFactory</literal>, the
        <literal>JackrabbitSessionFactory</literal> which allows node type
        definitions in the <ulink
        url="http://jackrabbit.apache.org/doc/nodetype/cnd.html">CND</ulink>
        format, to be added to the repository:</para>

        <programlisting>&lt;bean id="jackrabbitSessionFactory" class="org.springmodules.jcr.jackrabbit.JackrabbitSessionFactory"&gt;
  ...
  &lt;property name="nodeDefinitions"&gt;
    &lt;list&gt;
     &lt;value&gt;classpath:/nodeTypes/wikiTypes.cnd&lt;/value&gt;
     &lt;value&gt;classpath:/nodeTypes/clientATypes.cnd&lt;/value&gt;
    &lt;/list&gt;
  &lt;/property&gt;
&lt;/bean&gt;</programlisting>

        <para>If there is no need to register any custom node types, it's
        recommended that the <literal>JcrSessionFactory</literal> is used
        since it works on all JCR repositories.</para>
      </sect3>
    </sect2>

    <sect2>
      <title>Inversion of Control: JcrTemplate and JcrCallback</title>

      <para>Most of the work with the JCR will be made through the
      <literal>JcrTemplate</literal> itself or through a
      <literal>JcrCallback</literal>. The template requires a
      <literal>SessionFactory</literal> and can be configured to create
      sessions on demand or reuse them (thread-bound) - the default
      behavior.<programlisting>&lt;bean id="jcrTemplate" class="org.springmodules.jcr.JcrTemplate"&gt;
  &lt;property name="sessionFactory" ref="sessionFactory"/&gt;
  &lt;property name="allowCreate" value="true"/&gt;
&lt;/bean&gt;</programlisting><literal>JcrTemplate</literal> contains many of
      the operations defined in <literal>javax.jcr.Session</literal> and
      <literal>javax.jcr.query.Query</literal> classes plus some convenient
      ones; however there are cases when they are not enought. With
      <literal>JcrCallback</literal>, one can work directly with the
      <literal>Session</literal>, the callback begin thread-safe, opens/closes
      sessions and deals with exceptions:<programlisting>    public void saveSmth() {
        template.execute(new JcrCallback() {

            public Object doInJcr(Session session) throws RepositoryException {
                Node root = session.getRootNode();
                log.info("starting from root node " + root);
                Node sample = root.addNode("sample node");
                sample.setProperty("sample property", "bla bla");
                log.info("saved property " + sample);
                session.save();
                return null;
            }
        });
    } </programlisting></para>

      <sect3>
        <title>Implementing Spring-based DAOs without callbacks</title>

        <para>The developer can access the repository in a more 'traditional'
        way without using <literal>JcrTemplate</literal> (and
        <literal>JcrCallback</literal>) but still use Spring DAO exception
        hierarchy. SpringModules <literal>JcrDaoSupport</literal> offers base
        methods for retrieving <literal>Session</literal> from the
        <literal>SessionFactory</literal> (in a transaction-aware manner is
        transactions are supported) and for converting exceptions (which use
        <literal>SessionFactoryUtils</literal> static methods). Note that such
        code will usually pass "false" into <literal>getSession</literal>'s
        the "allowCreate" flag, to enforce running within a transaction (which
        avoids the need to close the returned <literal>Session</literal>, as
        it its lifecycle is managed by the transaction):</para>

        <para><programlisting>public class ProductDaoImpl extends JcrDaoSupport {

    public void saveSmth()
            throws DataAccessException, MyException {

        Session session = getSession();
        try {
                Node root = session.getRootNode();
                log.info("starting from root node " + root);
                Node sample = root.addNode("sample node");
                sample.setProperty("sample property", "bla bla");
                log.info("saved property " + sample);
                session.save();
                return null;
        }
        catch (RepositoryException ex) {
            throw convertJcrAccessException(ex);
        }
    }
}</programlisting>The major advantage of such direct JCR access code is that
        it allows any checked application exception to be thrown within the
        data access code, while <literal>JcrTemplate</literal> is restricted
        to unchecked exceptions within the callback. Note that one can often
        defer the corresponding checks and the throwing of application
        exceptions to after the callback, which still allows working with
        <literal>JcrTemplate</literal>. In general,
        <literal>JcrTemplate's</literal> convenience methods are simpler and
        more convenient for many scenarios.</para>
      </sect3>
    </sect2>

    <sect2>
      <title>RepositoryFactoryBean</title>

      <para>Repository configuration have not been discussed by JSR-170 and
      every implementation has a different approach. The JCR-support provides
      an abstract repository factory bean which defined the main functionality
      leaving subclasses to deal only with the configuration issues. The
      current version supports jackrabbit and jeceira as repository
      implementations but adding new ones is very easy. Note that through
      Spring, one can configure a repository without the mentioned
      <literal>RepositoryFactoryBean</literal>.</para>

      <sect3>
        <title>Jackrabbit</title>

        <para><ulink
        url="http://incubator.apache.org/jackrabbit/">JackRabbit</ulink> is
        the default implementation of the JSR-170 and it's part of the Apache
        Foundation. The project has graduated from the incubator and had an
        initial 1.0 release in early 2006. JackRabbit support both levels and
        all the optional features described in the specifications.</para>

        <para><programlisting>&lt;!-- configuring the default repository --&gt;
&lt;bean id="repository" class="org.springmodules.jcr.jackrabbit.RepositoryFactoryBean"&gt;
  &lt;!-- normal factory beans params --&gt;
  &lt;property name="configuration" value="classpath:jackrabbit-repo.xml"/&gt;
  &lt;property name="homeDir" value="/repo"/&gt;
&lt;/bean&gt;</programlisting>-- or --</para>

        <programlisting>&lt;!-- configuring a 'transient' repository (automatically starts when a session is opened 
     and shutdowns when all sessions are closed) --&gt;
&lt;bean id="repository" class="org.springmodules.jcr.jackrabbit.TransientRepositoryFactoryBean"&gt;
  &lt;!-- normal factory beans params --&gt;
  &lt;property name="configuration" value="classpath:jackrabbit-repo.xml"/&gt;
  &lt;property name="homeDir" value="/repo"/&gt;
&lt;/bean&gt;</programlisting>

        <para>Note that <literal>RepositoryFactoryBean</literal> makes use of
        Spring Resource to find the configuration file.</para>
      </sect3>

      <sect3>
        <title>Jackrabbit RMI support</title>

        <para>Jackrabbit's RMI server/client setup is provided through
        <literal>org.springmodules.jcr.jackrabbit.RmiServerRepositoryFactoryBean</literal>
        though Spring itself can handle most of the configuration without any
        special support:</para>

        <programlisting>&lt;!-- normal repository --&gt;
&lt;bean id="repository" class="org.springmodules.jcr.jackrabbit.RepositoryFactoryBean"&gt;
   &lt;!-- normal factory beans params --&gt;
   &lt;property name="configuration" value="/org/springmodules/jcr/jackrabbit/jackrabbit-repo.xml" /&gt;
   &lt;!-- use the target folder which will be cleaned  --&gt;
   &lt;property name="homeDir" value="file:./target/repo" /&gt;
&lt;/bean&gt;
  
&lt;!-- rmi server --&gt;
  
&lt;!-- use Spring's RMI classes to retrieve the RMI registry --&gt;
&lt;bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"/&gt;
  
&lt;bean id="rmiServer" class="org.springmodules.jcr.jackrabbit.RmiServerRepositoryFactoryBean"&gt;
  &lt;property name="repository" ref="repository"/&gt;
  &lt;property name="remoteAdapterFactory"&gt;
    &lt;bean class="org.apache.jackrabbit.rmi.server.ServerAdapterFactory"/&gt;
  &lt;/property&gt;
    
  &lt;property name="registry" ref="rmiRegistry"/&gt;
  &lt;property name="rmiName" value="jackrabbit"/&gt;
&lt;/bean&gt;
  
&lt;!-- rmi client --&gt;
&lt;bean id="rmiClientFactory" class="org.apache.jackrabbit.rmi.client.ClientRepositoryFactory"/&gt;

&lt;bean id="rmiClient" factory-bean="rmiClientFactory" factory-method="getRepository" 
                   depends-on="rmiServer"&gt;
  &lt;constructor-arg value="rmi://localhost:1099/jackrabbit"/&gt;
&lt;/bean&gt;</programlisting>
      </sect3>

      <sect3>
        <title>Jeceira</title>

        <para><ulink url="http://www.jeceira.com/">Jeceira</ulink> is another
        JSR-170 open-source implementation though as not as complete as
        Jackrabbit. Support for it can be found under
        <literal>org.springmodules.jcr.jeceira</literal> package:</para>

        <programlisting>&lt;bean id="repository" class="org.springmodules.jcr.jeceira.RepositoryFactoryBean"&gt;
  &lt;property name="repositoryName" value="myRepository"/&gt;
&lt;/bean&gt;</programlisting>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <title>Extensions support</title>

    <para>JSR-170 defines 2 levels of complaince and a number of optional
    features which can be provided by implementations, transactions being one
    of them.</para>

    <sect2>
      <title>Transaction Manager</title>

      <para>One of the nicest features of the JCR support in Spring Modules is
      transaction management (find out more about Spring transaction
      management in <ulink
      url="http://static.springframework.org/spring/docs/1.2.x/reference/transaction.html">Chapter
      8</ulink> of the Spring official reference documentation). At the
      moment, only Jackrabbit is known to have dedicated transactional
      capabilities. One can use <literal>LocalTransactionManager</literal> for
      local transactions or Jackrabbit's JCA connector to enlist the
      repository in a XA transaction through a JTA transaction manager. As a
      side note the JCA scenario can be used within an application server
      along with a specific descriptor or using a portable JCA connector (like
      <ulink url="http://www.jencks.org">Jencks</ulink>) which can work
      outside or inside an application server.</para>

      <sect3>
        <title>LocalTransactionManager</title>

        <para>For local transaction the
        <literal>LocalTransactionManager</literal> should be
        used:<programlisting>&lt;bean id="jcrTransactionManager"
 class="org.springmodules.jcr.jackrabbit.LocalTransactionManager"&gt;
   &lt;property name="sessionFactory" ref="jcrSessionFactory"/&gt;
&lt;/bean&gt;

&lt;!-- transaction proxy for Jcr services/facades --&gt;
&lt;bean id="txProxyTemplate" abstract="true" 
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
 &lt;property name="proxyTargetClass" value="true"/&gt;
 &lt;property name="transactionManager" ref="jcrTransactionManager"/&gt;
 &lt;property name="transactionAttributes"&gt;
   &lt;props&gt;
      &lt;prop key="save*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
      &lt;prop key="*"&gt;PROPAGATION_REQUIRED, readOnly&lt;/prop&gt;
   &lt;/props&gt;
 &lt;/property&gt;
&lt;/bean&gt;

&lt;bean id="jcrService" parent="txProxyTemplate"&gt;
 &lt;property name="target"&gt;
  &lt;bean class="org.springmodules.examples.jcr.JcrService"&gt;
   &lt;property name="template" ref="jcrTemplate"/&gt;
  &lt;/bean&gt;
 &lt;/property&gt;
&lt;/bean&gt;</programlisting>for which only the
        <literal>sessionFactory</literal> is required.</para>

        <para>Note that when using transactions in most cases you want to
        reuse the session (which means <literal>allowCreate</literal> property
        on <literal>jcrTemplate</literal> should be false (default)).</para>
      </sect3>

      <sect3>
        <title>JTA transactions</title>

        <para>For distributed transactions, using JCA is recommend in
        JackRabbit's case. An example is found inside the sample. You are free
        to use your application server JCA support; Jencks is used only for
        demonstrative purpose, the code inside the jackrabbit support having
        no dependency on it.</para>
      </sect3>

      <sect3>
        <title>SessionHolderProviderManager and SessionHolderProvider</title>

        <para>Because JSR-170 doesn't directly address transaction, details
        vary from repository to repository; JCR module contains (quite a lot
        of) classes to make this issue as painless as possible. Normally users
        should not be concern with these classes,however they are the main
        point for adding support for custom implementations.</para>

        <para>In order to plug in extra capabilities one must supply a
        <literal>SessionHolderProvider</literal> implementation which can take
        advantage of the underlying JCR session feature.
        <literal>SessionHolderProviderManager</literal> acts as a registry of
        <literal>SessionHolderProvider</literal>s for different repositories
        and has several implementations that return user defined provider or
        discover them automatically.</para>

        <para><literal>By default,
        ServiceSessionHolderProviderManager</literal> is used, which is
        suitable for most of cases. It uses <ulink
        url="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">JDK
        1.3+ Service Provider specification</ulink> (also known as
        <emphasis>META-INF/services</emphasis>) for determining the holder
        provider. The class looks on the classpath under META-INF/services for
        the file named
        "<literal>org.springmodules.jcr.SessionHolderProvider</literal>"
        (which contains the fully qualified name of a
        <literal>SessionHolderProvider</literal> implementation). The
        providers found are instantiated and registered and later on used for
        the repository they support. The distribution for example, contains
        such a file to leverage Jackrabbit's transactional
        capabilities.</para>

        <para>Besides <literal>ServiceSessionHolderProviderManager</literal>,
        one can use <literal>ListSessionHolderProviderManager</literal> to
        manually associate a <literal>SessionHolder</literal> with a certain
        repository:</para>

        <para><programlisting>&lt;bean id="sessionFactory" class="org.springmodules.jcr.JcrSessionFactory"&gt;
  &lt;property name="repository" ref="repository"/&gt;
  &lt;property name="credentials"&gt;
  ...
  &lt;/property&gt;
  &lt;property name="sessionHolderProviderManager"&gt;
    &lt;bean class="org.springmodules.jcr.support.ListSessionHolderProviderManager"&gt;
     &lt;list&gt;
      &lt;bean class="foo.bar.CustomSessionHolderProvider"/&gt;
      &lt;bean class="my.custom.AnotherSessionHolderProvider"/&gt;
     &lt;/list&gt;
    &lt;/bean&gt;
  &lt;/property&gt;
&lt;/bean&gt;</programlisting></para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <title>Mapping support</title>

    <para>Working with the JCR resembles to some degree to working with JDBC.
    Mapping support for the JCR seems to be the next logical step but the
    software market doesn't seem to offer any mature solution. The current
    package offers support for <ulink
    url="http://incubator.apache.org/graffito/project-structure.html">jcr-mapping</ulink>
    which is part of <ulink
    url="http://incubator.apache.org/graffito/">Graffito project</ulink> which
    belongs to the Apache foundation. However, Graffito itself is still in the
    incubator and the jcr-mapping is described as a prototype. The current
    support provides some base functionality taken from a snapshot which can
    be found inside the distribtution which most probably is old.</para>

    <para>Moreover as jcr-mapping is clearly in alpha stage and a work in
    progress, users should not invest too much in this area but are encouraged
    to experiment and provide feedback. At the moment, the support contains a
    <literal>JcrMappingCallback</literal> and <literal>Template</literal> plus
    a <literal>FactoryBean</literal> for creating
    <literal>MappingDescriptors</literal> (which allows using more then one
    mapping file which is not possible at the moment in the jcr-mapping
    project).</para>
  </sect1>

  <sect1>
    <title>Working with JSR-170 products</title>

    <para>Even though the documentation uses as examples stand-alone JSR-170
    implementations, the JCR module can work against any library/product which
    supports the JCR API. The only difference is that the JCR repository
    retrieval, which has to be changed based on the product used settings.
    Usually, reading the product documentation suffices however, to ease
    integration, this documentation includes hints for major JCR-compatible
    products (if you are working with a major product which is not mentioned
    below, please contribute the instructions through the project <ulink
    url="http://opensource.atlassian.com/projects/spring/browse/MOD">issue
    tracker</ulink>).</para>

    <sect2>
      <title>Alfresco</title>

      <para><ulink url="http://www.alfresco.com/">Alfresco</ulink> is an
      open-source enterprise content managment system which uses <ulink
      url="http://www.springframework.org">Spring framework</ulink> as its
      core. To get a hold of the JCR connector, one can:</para>

      <para>bootstrap Alfresco application context and do a dependency
      lookup:</para>

      <programlisting>ApplicationContext context = new ClassPathXmlApplicationContext("classpath:alfresco/application-context.xml");
Repository repository = (Repository)context.getBean("JCR.Repository");</programlisting>

      <para>- or -</para>

      <para>let the container inject the dependency:</para>

      <programlisting>&lt;bean id="myBean" class="myBeanImplementation"&gt;
  &lt;property name="JCRRepository"&gt;&lt;ref bean="JCR.Repository"/&gt;&lt;/property&gt;
  ...
&lt;/bean&gt;</programlisting>

      <para>For more information, see Alfresco <ulink
      url="http://wiki.alfresco.com/wiki/Introducing_the_Alfresco_Java_Content_Repository_API#Repository_Configuration">JCR
      documentation</ulink>.</para>
    </sect2>

    <sect2>
      <title>Magnolia</title>

      <para><ulink url="http://www.magnolia.info/">Magnolia</ulink> aims to
      make Enterprise Content Management simple by being user-friendly,
      battle-tested, enterprise-ready and open-source. Mangnolia itself is not
      a repository and replies on a JCR implementation(Jackrabbit in
      particular) for its backend. Thus, connecting through JSR-170 to
      Magnolia is identical to connecting to a Jackrabbit repository. See
      Magnolia <ulink
      url="http://www.magnolia.info/en/products/faq.html">FAQ</ulink>, for
      <ulink
      url="http://www.magnolia.info/en/products/faq.html#DoyouprovideaJCRJSR170level2readw">more
      information</ulink>.</para>
    </sect2>
  </sect1>
</chapter>