Thursday, August 9, 2012

JCR project - part 2

In this post I'll show how to instantiate a repository using a repo home directory and a repository.xml file. To focus on the actual code and project configuration I am using the xml generated by Jackrabbit when instantiating an Automatic and Transient repository as shown in the previous post.

These are the steps:

1) Create src/repository directory in your project folder
2) Create repository.xml in the directory at point 1
3) Paste the content below in the file at point 2


<?xml version="1.0"?>
<!-- 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. -->

<!DOCTYPE Repository
          PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 2.0//EN"
          "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">

<!-- Example Repository Configuration File Used by - org.apache.jackrabbit.core.config.RepositoryConfigTest.java
- -->
<Repository>
<!-- virtual file system where the repository stores global state (e.g.
registered namespaces, custom node types, etc.) -->
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
<param name="path" value="${rep.home}/repository" />
</FileSystem>

<!-- data store configuration -->
<DataStore class="org.apache.jackrabbit.core.data.FileDataStore" />

<!-- security configuration -->
<Security appName="Jackrabbit">
<!-- security manager: class: FQN of class implementing the JackrabbitSecurityManager
interface -->
<SecurityManager class="org.apache.jackrabbit.core.DefaultSecurityManager"
workspaceName="security"
>
<!-- workspace access: class: FQN of class implementing the WorkspaceAccessManager
interface -->
<!-- <WorkspaceAccessManager class="..."/> -->
<!-- <param name="config" value="${rep.home}/security.xml"/> -->
</SecurityManager>

<!-- access manager: class: FQN of class implementing the AccessManager
interface -->
<AccessManager
class="org.apache.jackrabbit.core.security.DefaultAccessManager"
>
<!-- <param name="config" value="${rep.home}/access.xml"/> -->
</AccessManager>

<LoginModule
class="org.apache.jackrabbit.core.security.authentication.DefaultLoginModule"
>
<!-- anonymous user name ('anonymous' is the default value) -->
<param name="anonymousId" value="anonymous" />
<!-- administrator user id (default value if param is missing is 'admin') -->
<param name="adminId" value="admin" />
</LoginModule>
</Security>

<!-- location of workspaces root directory and name of default workspace -->
<Workspaces rootPath="${rep.home}/workspaces"
defaultWorkspace="default" />
<!-- workspace configuration template: used to create the initial workspace
if there's no workspace yet -->
<Workspace name="${wsp.name}">
<!-- virtual file system of the workspace: class: FQN of class implementing
the FileSystem interface -->
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
<param name="path" value="${wsp.home}" />
</FileSystem>
<!-- persistence manager of the workspace: class: FQN of class implementing
the PersistenceManager interface -->
<PersistenceManager
class="org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager"
>
<param name="url" value="jdbc:derby:${wsp.home}/db;create=true" />
<param name="schemaObjectPrefix" value="${wsp.name}_" />
</PersistenceManager>
<!-- Search index and the file system it uses. class: FQN of class implementing
the QueryHandler interface -->
<SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
<param name="path" value="${wsp.home}/index" />
<param name="supportHighlighting" value="true" />
</SearchIndex>
</Workspace>

<!-- Configures the versioning -->
<Versioning rootPath="${rep.home}/version">
<!-- Configures the filesystem to use for versioning for the respective
persistence manager -->
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
<param name="path" value="${rep.home}/version" />
</FileSystem>

<!-- Configures the persistence manager to be used for persisting version
state. Please note that the current versioning implementation is based on
a 'normal' persistence manager, but this could change in future implementations. -->
<PersistenceManager
class="org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager"
>
<param name="url" value="jdbc:derby:${rep.home}/version/db;create=true" />
<param name="schemaObjectPrefix" value="version_" />
</PersistenceManager>
</Versioning>

<!-- Search index for content that is shared repository wide (/jcr:system
tree, contains mainly versions) -->
<SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
<param name="path" value="${rep.home}/repository/index" />
<param name="supportHighlighting" value="true" />
</SearchIndex>

<!-- Run with a cluster journal -->
<Cluster id="node1">
<Journal class="org.apache.jackrabbit.core.journal.MemoryJournal" />
</Cluster>
</Repository>


4) Edit your pom.xml in order to instruct maven to copy the repository directory and its content in target/. You simply need to specify the resource in the build part of the pom.


<build>
<resources>
<resource>
<directory>src/repository</directory>
<includes>
<include>*/**</include>
</includes>
<targetPath>repository</targetPath>
</resource>
</resources>
</build>


If you now run: mvn clean test-compile you should see these two entries:

  • target//classes/repository
  • target//classes/repository/repository.xml


5) If you have an interface that your repository initializer implements then change the initializeRepository method in order to add the (String configFile, String repHomeDir) parameters. 
The configFile points to the repository.xml file, relative path from your project home is enough for test purposes, while the repoHomeDir points to the repository directory.

6) The last step is instructing the creation of the repository using the RegistryHelper. Note that the code leverages the Java Naming and Directory Interface. 
Now rather than creating a repository automatically with the TransientRepository as follows:

repository = new TransientRepository(new File("target"));

You need to execute this code:

Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.jackrabbit.core.jndi"
+ ".provider.DummyInitialContextFactory");

env.put(Context.PROVIDER_URL, "localhost");

InitialContext ctx = new InitialContext(env);

RegistryHelper.registerRepository(ctx, "repo", configFile, repHomeDir,
true);

repository = (Repository) ctx.lookup("repo");

Note that the automatic way needs the directory where the repository.xml file and the repository directory will be created to be passed as a parameter.

Run your test everything should work without any problem. This is one of the big advantage of using JCR: changing the underlying storage implementation does not require any change to your business logic!

You can now try to play with the repository DataStore for the binary files or the PersistanceStorage in order to use different implementation. This link may be handy.

The source code is here (branch: manual_transient)

No comments:

Post a Comment