Download and Build Jackrabbit

Please refer to the README.txt to find details on how to build Jackrabbit using Maven.

Run Jackrabbit

The following code provides a brief introduction to using Jackrabbit in a simple application. Please note that this example is meant to be as short and simple as possible, rather than usable as a real application, and should not be interpreted as best practice.

JCRTest.java

import java.util.Hashtable;

import javax.jcr.*;

import javax.naming.Context;
import javax.naming.InitialContext;

import org.apache.jackrabbit.core.jndi.RegistryHelper;

public class JCRTest {

  public static void main(String[] args) {
    try {
      String configFile = "repotest/repository.xml";
      String repHomeDir = "repotest";
      
      Hashtable env = new Hashtable();
      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 r = (Repository) ctx.lookup("repo");
      Session session = r.login(new SimpleCredentials("userid", "".toCharArray()), null);
      Node rn=session.getRootNode();
      
      System.out.println(rn.getPrimaryNodeType().getName());
      
      
    } catch (Exception e){
      System.err.println(e);
    }
  }
}
    

The configFile variable points to a file, named repository.xml by convention, that contains the repository configuration. An example repository.xml might look like this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Repository>
    <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
        <param name="path" value="${rep.home}/repository"/>
    </FileSystem>
    <Security appName="Jackrabbit">
        <AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager"/>
    </Security>
    <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default" />
    <Workspace name="${wsp.name}">
        <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
            <param name="path" value="${wsp.home}"/>
        </FileSystem>
        <PersistenceManager class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager" />
        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
            <param name="path" value="${wsp.home}/index"/>
        </SearchIndex>
    </Workspace>
    <Versioning rootPath="${rep.home}/versions">
        <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
            <param name="path" value="${rep.home}/versions"/>
        </FileSystem>
        <PersistenceManager class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager" />
    </Versioning>
</Repository>   
    

The keyword ${rep.home} refers to the repository home directory, which is used as the root directory for all of the information that the repository persists. The directory can be empty; after initial startup, the repository will be filled with file structure similar to this:

repository.xml

repository/
   meta/
   namespaces/
   nodetypes/
   versions/

tx/

workspaces/
   default/
      workspace.xml
      blobs/
      data/
      index/
    

In addition to the repository configuration file, you also need to create a JAAS configuration file used for Jackrabbit login settings. The contents of a simple configuration file named jaas.config is shown below. The configuration for the SimpleLoginModule also contains an optional module option to configure the user id of the anonymous user with read-only access to the repository. If the option is omitted the anoymous user id default to 'anonymous'.

Jackrabbit {
org.apache.jackrabbit.core.security.SimpleLoginModule required anonymousId="anonymous";
};
     

Make sure that all of the dependencies are added to your classpath, as well as the Jackrabbit repository implementation (named something like jackrabbit-x.xx-xxx-dev.jar) that has been built by Maven into the target directory of your checkout. By executing maven copy-deps all dependencies except the optional runtime cqfs-* libaries are being copied to the target/lib directory. I addition to setting up the classpath, you need to include the JAAS configuration option -Djava.security.auth.login.config==jaas.config (note the double equal sign ==) to the java command when running the example code.

Now you should be ready to compile the above JCRTest class and run it, which should produce the following output:

rep:root
    

Adding Content

Since an empty repository is not very useful, add the following code to the above test class JCRTest to create content inside Jackrabbit.

JCRTest.java

import java.util.Hashtable;

import javax.jcr.*;

import javax.naming.Context;
import javax.naming.InitialContext;

import org.apache.jackrabbit.core.jndi.RegistryHelper;

public class JCRTest {

  public static void main(String[] args) {
    try {
      String configFile = "repotest/repository.xml";
      String repHomeDir = "repotest";
      
      Hashtable env = new Hashtable();
      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 r = (Repository) ctx.lookup("repo");
      Session session = r.login(new SimpleCredentials("userid", "".toCharArray()), null);
      Node rn=session.getRootNode();
      
      System.out.println(rn.getPrimaryNodeType().getName());
        
      if (!rn.hasNode("testnode")) {
        System.out.println("creating testnode");
        Node n=rn.addNode("testnode", "nt:unstructured");
        n.setProperty("testprop", session.getValueFactory().createValue("Hello, World."));
        session.save();
      }

      System.out.println(rn.getProperty("testnode/testprop").getString());
      
    } catch (Exception e){
      System.err.println(e);
    }
  }
}
    
which should produce the following output (possibly surrounded by log messages, depending on settings) when started for the first time:
rep:root
creating testnode
Hello, World.   
    

To add content a bit more efficiently, you may want to try JCR's import facilities, such as Session.importXML. The following XML document by Elliotte Rusty Harold provides an interesting example that demonstrates a repository's namespace capabilities:

<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml"
            xmlns:mathml="http://www.w3.org/1998/Math/MathML">
  <xhtml:head><xhtml:title>Three Namespaces</xhtml:title></xhtml:head>
  <xhtml:body>
    <xhtml:h1 align="center">An Ellipse and a Rectangle</xhtml:h1>
    <svg:svg xmlns:svg="http://www.w3.org/2000/svg" 
             width="12cm" height="10cm">
      <svg:ellipse rx="110" ry="130" />
      <svg:rect x="4cm" y="1cm" width="3cm" height="6cm" />
    </svg:svg>
    <xhtml:p>The equation for ellipses</xhtml:p>
<mathml:math>
  <mathml:apply>
    <mathml:eq/>
    <mathml:cn> 1 </mathml:cn>
    <mathml:apply>
      <mathml:plus/>
      <mathml:apply>
        <mathml:divide/>
        <mathml:apply>
          <mathml:power/>
          <mathml:ci> x </mathml:ci>
          <mathml:cn> 2 </mathml:cn>
        </mathml:apply>
        <mathml:apply>
          <mathml:power/>
          <mathml:ci> a </mathml:ci>
          <mathml:cn> 2 </mathml:cn>
        </mathml:apply>
      </mathml:apply>
      <mathml:apply>
        <mathml:divide/>
        <mathml:apply>
          <mathml:power/>
          <mathml:ci> y </mathml:ci>
          <mathml:cn> 2 </mathml:cn>
        </mathml:apply>
        <mathml:apply>
          <mathml:power/>
          <mathml:ci> b </mathml:ci>
          <mathml:cn> 2 </mathml:cn>
        </mathml:apply>        
      </mathml:apply>
    </mathml:apply>
 </mathml:apply>
</mathml:math>
    <xhtml:hr/>
    <xhtml:p>Last Modified January 10, 2002</xhtml:p>    
  </xhtml:body>
</xhtml:html>
    

The JCRTest class is then extended with Session.importXml() to import the XML file named repotest/test.xml, and a simple dump() method is added to display the content of the repository.

import java.io.FileInputStream;
import java.util.Hashtable;

import javax.jcr.*;
import javax.naming.Context;
import javax.naming.InitialContext;

import org.apache.jackrabbit.core.jndi.RegistryHelper;

public class JCRTest {

  public static void main(String[] args) {
    try {
      String configFile = "repotest/repository.xml";
      String repHomeDir = "repotest";

      Hashtable env = new Hashtable();
      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 r = (Repository) ctx.lookup("repo");
      Session session = r.login(new SimpleCredentials("userid", "".toCharArray()), null);
      Node rn=session.getRootNode();

      System.out.println(rn.getPrimaryNodeType().getName());
      
      if (!rn.hasNode("testnode")) {
        System.out.println("creating testnode");
        Node n=rn.addNode("testnode", "nt:unstructured");
        n.setProperty("testprop", session.getValueFactory().createValue("Hello, World."));
        session.save();
      }
      
      if (!rn.hasNode("importxml")) {
        System.out.println("importing xml");
        Node n=rn.addNode("importxml", "nt:unstructured");
        session.importXML("/importxml", new FileInputStream("repotest/test.xml"), ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
        session.save();
      }
      dump(rn);
    } catch (Exception e){
      System.err.println(e);
    }
  }
  public static void dump (Node n) throws RepositoryException {
    System.out.println(n.getPath());
    PropertyIterator pit=n.getProperties();
    while (pit.hasNext()) {
      Property p=pit.nextProperty();
      System.out.print(p.getPath() + "=");
      if (p.getDefinition().isMultiple()) {
        Value[] values = p.getValues();
        for (int i = 0; i < values.length; i++) {
          if (i > 0) System.out.println(",");
          System.out.println(values[i].getString());
        }
      } else {
        System.out.print(p.getString());
      }
      System.out.println();
    }
    NodeIterator nit=n.getNodes();
    while (nit.hasNext()) {
      Node cn=nit.nextNode();
      dump (cn);
    }
  }
}
    
Which should output something along the lines of:
rep:root
/
/jcr:primaryType=rep:root
/jcr:system
/jcr:system/jcr:primaryType=rep:system
/jcr:system/jcr:versionStorage
/jcr:system/jcr:versionStorage/jcr:primaryType=rep:versionStorage
/jcr:system/jcr:versionStorage/jcr:mixinTypes=
/testnode
/testnode/jcr:primaryType=nt:unstructured
/testnode/testprop=Hello, World.
/importxml
/importxml/jcr:primaryType=nt:unstructured
/importxml/xhtml:html
/importxml/xhtml:html/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:head
/importxml/xhtml:html/xhtml:head/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:head/xhtml:title
/importxml/xhtml:html/xhtml:head/xhtml:title/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:head/xhtml:title/jcr:xmltext
/importxml/xhtml:html/xhtml:head/xhtml:title/jcr:xmltext/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:head/xhtml:title/jcr:xmltext/jcr:xmlcharacters=Three Namespaces
/importxml/xhtml:html/xhtml:body
/importxml/xhtml:html/xhtml:body/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:body/xhtml:h1
/importxml/xhtml:html/xhtml:body/xhtml:h1/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:body/xhtml:h1/align=center
/importxml/xhtml:html/xhtml:body/xhtml:h1/jcr:xmltext
/importxml/xhtml:html/xhtml:body/xhtml:h1/jcr:xmltext/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:body/xhtml:h1/jcr:xmltext/jcr:xmlcharacters=An Ellipse and a Rectangle
/importxml/xhtml:html/xhtml:body/svg:svg
/importxml/xhtml:html/xhtml:body/svg:svg/jcr:primaryType=nt:unstructured
/importxml/xhtml:html/xhtml:body/svg:svg/width=12cm
/importxml/xhtml:html/xhtml:body/svg:svg/height=10cm
.
.
.