You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by co...@apache.org on 2008/02/08 10:49:00 UTC
[CONF] Apache Jackrabbit: 5' with Jackrabbit OCM (page edited)
5' with Jackrabbit OCM (JCR) edited by Christophe Lombart
Page: http://cwiki.apache.org/confluence/display/JCR/5%27+with+Jackrabbit+OCM
Changes: http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=75934&originalVersion=1&revisedVersion=2
Content:
---------------------------------------------------------------------
This very small tutorial describes how to create an application with Jackrabbit OCM.
In short, you have to :
* Create one or more persistent classes.
* Create the OCM node type called _ocm:discriminator_.
* Initialize the JCR repository.
* Instantiate an [Object Content Manager] component.
* Use the [Object Content Manager] to persist your data.
The node type creation is specific to the JCR implementation. So, the code used in this tutorial works only with Jackrabbit.
h2. Create a persistent class
This tutorial is using the annotation support to define a persistent class. Your data objects are simple pojos with some OCM annotations.
Here is a example of a PressRelease class.
{code}
package org.apache.jackrabbit.ocm.model;
import java.util.Date;
import org.apache.jackrabbit.ocm.mapper.impl.annotation.Field;
import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
@Node
public class PressRelease
{
@Field(path=true) String path;
@Field String title;
@Field Date pubDate;
@Field String content;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getPubDate() {
return pubDate;
}
public void setPubDate(Date pubDate) {
this.pubDate = pubDate;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
{code}
The annotation {code}@Node{code} has to be added on the top of the class.
Each persistent class must have a *path field* which will be mapped into the JCR Node path. This can be specify with the annotation {code}@Field(path=true){code}.
Other persistent fields can be defined with the annotation {code}@Field{code}
That's all for the class definition. In other tutorials, we will see how to map advanced fields like collections or custom objects.
h2. Create the node type _ocm:discriminator_
The mixin node type _ocm:discriminator_ is used internally by the [Object Content Manager] to store the classname of the object to persist. You have to create a new xml file which contains the following structure :
{code:xml}
<?xml version="1.0" encoding="UTF-8"?>
<nodeTypes xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
xmlns:sv="http://www.jcp.org/jcr/sv/1.0"
xmlns:test="http://www.apache.org/jackrabbit/test"
xmlns:mix="http://www.jcp.org/jcr/mix/1.0"
xmlns:ocm="http://jackrabbit.apache.org/ocm">
<nodeType name="ocm:discriminator" isMixin="true">
<supertypes>
<supertype>nt:base</supertype>
</supertypes>
<propertyDefinition name="ocm:classname" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="false" multiple="false" />
</nodeType>
</nodeTypes>
{code}
You can save this file as "custom_nodetypes.xml". You can also use the CND notation.
{info:title= When is the node type _ocm:discriminator_ used ? }
With Jackrabbit OCM, it is possible to map different classes to the same node type. For example, it is possible to map severals java classes into the node type _nt:unstructured_. So, when the [Object Content Manager] retrieves a node based on this kind of generic type, he has to know the class to instantiate. Then, it uses the ocm:classname property stored in the _ocm:discriminator_ mixin type.
{info}
h2. Initialize the JCR repository
You have to import the xml file created in the previous step and create the namespace _ocm_ into the JCR repository.
You can use the following utility class :
{code}
package org.apache.jackrabbit.ocm.util;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Workspace;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeTypeManager;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.core.jndi.RegistryHelper;
import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader;
import org.apache.jackrabbit.ocm.exception.RepositoryException;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.jackrabbit.util.Text;
/**
* Utility class for managing JCR repositories.
* <b>Note</b>: most of the utility methods in this class can be used only with Jackrabbit.
*
* @author <a href="mailto:christophe.lombart@sword-technologies.com">Lombart Christophe </a>
* @version $Id: Exp $
*/
public class RepositoryUtil
{
/** namespace prefix constant */
public static final String OCM_NAMESPACE_PREFIX = "ocm";
/** namespace constant */
public static final String OCM_NAMESPACE = "http://jackrabbit.apache.org/ocm";
/** Item path separator */
public static final String PATH_SEPARATOR = "/";
private final static Log log = LogFactory.getLog(RepositoryUtil.class);
/**
* Register a new repository
*
* @param repositoryName The repository unique name
* @param configFile The JCR config file
* @param homeDir The directory containing the complete repository settings (workspace, node types, ...)
*
* @throws RepositoryException when it is not possible to register the repository
*/
public static void registerRepository(String repositoryName, String configFile, String homeDir) throws RepositoryException
{
try
{
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, repositoryName, configFile, homeDir, true);
}
catch (Exception e)
{
throw new RepositoryException("Impossible to register the respository : " +
repositoryName + " - config file : " + configFile, e);
}
}
/**
* Unregister a repository
*
* @param repositoryName The repository unique name
*
* @throws RepositoryException when it is not possible to unregister the repository
*/
public static void unRegisterRepository(String repositoryName) throws RepositoryException
{
try
{
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.unregisterRepository(ctx, repositoryName);
}
catch (Exception e)
{
throw new RepositoryException("Impossible to unregister the respository : " +
repositoryName , e);
}
}
/**
* Get a repository
*
* @param repositoryName The repository name
* @return a JCR repository reference
*
* @throws RepositoryException when it is not possible to get the repository.
* Before calling this method, the repository has to be registered (@see RepositoryUtil#registerRepository(String, String, String)
*/
public static Repository getRepository(String repositoryName) throws RepositoryException
{
try
{
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);
Repository repository = (Repository) ctx.lookup(repositoryName);
return repository;
}
catch (Exception e)
{
throw new RepositoryException("Impossible to get the repository : " + repositoryName, e);
}
}
/**
* Connect to a JCR repository
*
* @param repository The JCR repository
* @param user The user name
* @param password The password
* @return a valid JCR session
*
* @throws RepositoryException when it is not possible to connect to the JCR repository
*/
public static Session login(Repository repository, String user, String password) throws RepositoryException
{
try
{
Session session = repository.login(new SimpleCredentials(user, password.toCharArray()), null);
return session;
}
catch (Exception e)
{
throw new RepositoryException("Impossible to login ", e);
}
}
public static Session login(Repository repository, String user, String password, String workspace) throws RepositoryException
{
try
{
Session session = repository.login(new SimpleCredentials(user, password.toCharArray()), workspace);
return session;
}
catch (Exception e)
{
throw new RepositoryException("Impossible to login ", e);
}
}
/**
* Create the ocm namespace
*
*/
public static void createNamespace(Session session) throws RepositoryException
{
try
{
log.info("Setup Jcr session setup ...");
String[] jcrNamespaces = session.getWorkspace().getNamespaceRegistry().getPrefixes();
boolean createNamespace = true;
for (int i = 0; i < jcrNamespaces.length; i++)
{
if (jcrNamespaces[i].equals(OCM_NAMESPACE_PREFIX))
{
createNamespace = false;
log.debug("Jackrabbit OCM namespace exists.");
}
}
if (createNamespace)
{
session.getWorkspace().getNamespaceRegistry().registerNamespace(OCM_NAMESPACE_PREFIX, OCM_NAMESPACE);
log.info("Successfully created Jackrabbit OCM namespace.");
}
if (session.getRootNode() != null)
{
log.info("Jcr session setup successfull.");
}
}
catch (Exception e)
{
log.error("Error while setting up the jcr session.", e);
throw new RepositoryException(e.getMessage());
}
}
public static void registerNodeTypes(Session session, String nodeTypeFile)
{
try {
InputStream xml = new FileInputStream(nodeTypeFile);
NodeTypeDef[] types = NodeTypeReader.read(xml);
Workspace workspace = session.getWorkspace();
NodeTypeManager ntMgr = workspace.getNodeTypeManager();
NodeTypeRegistry ntReg = ((NodeTypeManagerImpl) ntMgr).getNodeTypeRegistry();
for (int j = 0; j < types.length; j++) {
NodeTypeDef def = types[j];
try {
ntReg.getNodeTypeDef(def.getName());
}
catch (NoSuchNodeTypeException nsne) {
// HINT: if not already registered than register custom node type
ntReg.registerNodeType(def);
}
}
}
catch (Exception e)
{
throw new RepositoryException("Impossible to register node types", e);
}
}
/**
* Encode a path
* @TODO : drop Jackrabbit dependency
*
* @param path the path to encode
* @return the encoded path
*
*/
public static String encodePath(String path)
{
String[] pathElements = Text.explode(path, '/');
for (int i=0;i<pathElements.length;i++)
{
pathElements[i] = ISO9075.encode(pathElements[i]);
}
return "/" + Text.implode(pathElements, "/");
}
}
{code}
Now, you can use this utility class like this :
{code}
Session session = ... // get a JCR Session
RepositoryUtil.createNamespace(session);
RepositoryUtil.registerNodeTypes(session, "[full path]/custom_nodetypes.xml");
{code}
The method call *RepositoryUtil.createNamespace(session)* will create the _ocm_ namespace and the other one *RepositoryUtil.registerNodeTypes(...)* will import the node type ocm:descriminator (defined in the file custom_nodetypes.xml).
h2. Instantiate an Object Content Manager component
In order to save a PressRelease object, you have to instantiate an [Object Content Manager] component :
{code}
List<Class> classes = new ArrayList<Class>();
classes.add(PressRelease.class); // Call this method for each persistent class
Mapper mapper = new AnnotationMapperImpl(classes);
ObjectContentManager ocm = new ObjectContentManagerImpl(session, mapper);
{code}
h2. Use the Object Content Manager to persist your data
Now, you are ready to create a new PressRelease and use the [Object Content Manager] to persist it into the JCR repository.
{code}
// Insert an object
System.out.println("Insert a press release in the repository");
PressRelease pressRelease = new PressRelease();
pressRelease.setPath("/newtutorial");
pressRelease.setTitle("This is the first tutorial on OCM");
pressRelease.setPubDate(new Date());
pressRelease.setContent("Many Jackrabbit users ask to the dev team to make a tutorial on OCM");
ocm.insert(pressRelease);
ocm.save();
// Retrieve
System.out.println("Retrieve a press release from the repository");
pressRelease = (PressRelease) ocm.getObject("/newtutorial");
System.out.println("PressRelease title : " + pressRelease.getTitle());
// Delete
System.out.println("Remove a press release from the repository");
ocm.remove(pressRelease);
ocm.save();
{code}
---------------------------------------------------------------------
CONFLUENCE INFORMATION
This message is automatically generated by Confluence
Unsubscribe or edit your notifications preferences
http://cwiki.apache.org/confluence/users/viewnotifications.action
If you think it was sent incorrectly contact one of the administrators
http://cwiki.apache.org/confluence/administrators.action
If you want more information on Confluence, or have a bug to report see
http://www.atlassian.com/software/confluence