SeamFramework.orgCommunity Documentation

Seam JCR

If you are using Maven as your build tool, you can add the following single dependency to your pom.xml file to include Seam JCR:



Substitute the expression ${seam.jcr.version} with the most recent or appropriate version of Seam JCR. Alternatively, you can create a Maven user-defined property to satisfy this substitution so you can centrally manage the version.

Alternatively, you can use the API at compile time and only include the implementation at runtime. This protects you from inadvertantly depending on an implementation class.



In addition to your Seam JCR dependencies, you must also declare a dependency on a JCR Implementation.

Seam JCR provides functionality to fire CDI Events based on events found in JCR. The rules of how events are fired are based around the underlying implementation.


You will not have an active JCR Session during the event firing, a new one will need to be created.


Some JCR implementations, like Modeshape fires events on a separate thread, so probably you will get errors if your observer method is declared on a @RequestScoped object, for example.

To observe an event, use the @Observes and the additional qualifiers on seam-jcr-api module (Check package If you need to watch any JCR event, then avoid using any Qualifier at all.

    import javax.jcr.observation.Event;
    public void observeAdded(@Observes @NodeAdded Event evt) {
    	// Called when a node is added
    public void observeAll(@Observes javax.jcr.observation.Event evt) {
    	// Called when any node event occurs 

The mapping API is very simple and designed to be clean. In order to define an entity, you simply need to use the annotation org.jboss.seam.jcr.annotations.ocm.JcrNode to define that this is an entity to map. All fields by default will be mapped to their field names. You can override this behavior by using the annotation org.jboss.seam.jcr.annotations.ocm.JcrProperty which will map the property to a different property name. The JcrProperty annotation can be placed on both field and getter method. You can define a special property uuid of type String that will represent the identifier for the node. This is a sample node mapping:

public class BasicNode implements {
    private String value;
    private String uuid;
    private String lordy;
    public String getValue() {
        return value;
    public void setValue(String value) {
        this.value = value;
    public String getUuid() {
        return uuid;
    public void setUuid(String uuid) {
        this.uuid = uuid;
    public String getLordy() {
        return lordy;
    public void setLordy(String lordy) {
        this.lordy = lordy;

The simplest way to convert entities is to use CDI Events. There are two event objects that can be fired to support parsing, org.jboss.seam.jcr.ocm.ConvertToNode and org.jboss.seam.jcr.ocm.ConvertToObject. By passing in a node and a pre-constructed object you can convert the full node to object or object to node depending on your need. Here is a sample parsing (from our test cases):

        @Inject Event<ConvertToObject< objectEvent;
        @Inject Event<ConvertToNode< nodeEvent;
        Node root = session.getRootNode();
        Node ocmnode1 = root.addNode("ocmnode1","nt:unstructured");
        BasicNode bn = new BasicNode();
        bn.setValue("Hello, World!");
        bn.setLordy("this was saved."); ConvertToNode(bn,ocmnode1));
        Node hello2 = root.getNode("ocmnode1");
        BasicNode bn2 = new BasicNode(); ConvertToObject(hello2,bn2));

If you have ever worked with entities, the term DAO should be very familiar to you. Seam JCR OCM supports DAOs in a highly automated fashion. Using annotations and interfaces only, you can automate querying, finds and saving entities into their mapped node types. There are four annotations to support DAOs:

Here is a sample definition of an interface, describing the objects that can be used:

        import static org.jboss.seam.jcr.ConfigParams.MODESHAPE_URL;
import java.util.List;
import org.jboss.seam.jcr.annotations.JcrConfiguration;
import org.jboss.seam.jcr.annotations.ocm.JcrDao;
import org.jboss.seam.jcr.annotations.ocm.JcrFind;
import org.jboss.seam.jcr.annotations.ocm.JcrQuery;
import org.jboss.seam.jcr.annotations.ocm.JcrSave;
import org.jboss.seam.jcr.test.ocm.BasicNode;
    @JcrConfiguration(name = MODESHAPE_URL, 
        value = "file:target/test-classes/modeshape.xml?repositoryName=CarRepo")
public interface BasicNodeDAO {
    public BasicNode findBasicNode(String uuid);
    @JcrQuery(query="select * from [nt:unstructured]",language="JCR-SQL2",resultClass=BasicNode.class)
    public List<BasicNode> findAllNodes();
    public String save(String path, BasicNode basicNode);

In this case, we are telling the JcrDao BasicNodeDAO to use the JCR Session based on the annotated JcrConfiguration noted. Since BasicNode is mapped to nt:unstructured, we can map any nt:unstructured to it by calling findAllNodes. We can save a basic node to a given path as well as find based on uuid. The best part is that there is no implementation necessary on your side. You can use this interface as is.

    BasicNodeDAO basicDAO;
        BasicNode bn = new BasicNode();
        bn.setValue("this is my node.");
        String uuid ="/anypathone",bn);
        System.out.println("The UUID is: "+uuid);
        BasicNode bn2 = basicDAO.findBasicNode(uuid);
        System.out.printf("The original node was %s and the new node is \n",bn.getValue(), bn2.getValue());
        List<BasicNode> nodes = basicDAO.findAllNodes();