Please refer to the README.txt to find details on how to build Jackrabbit using Maven.
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
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); } } }
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); } } }
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 . . .