Modeshape 4 in action

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

This tutorial is a follow-up of our first introduction to Modeshape 4 NoSQL Data storage with Modeshape 4. Here we will learn how to deploy a simple Web application which inserts new Nodes into Modeshape JCR repository and display them with a nice Primefaces tree view.

Modeshape has an extensive set of API which can be used to programmatically access, find, update and query content of a Content Repository. It does also include extended JCR interfaces for managing additional node and event types or using sequencers and text SPIs.

In this tutorial we will see a simple basic JSF + CDI application which interacts with a Modeshape repository. Our application will be made up just of two simple JSF views:

  • One for inserting Nodes into the Repository
  • Another view for displaying a tree view of the repository

Let's start our journey. The first class we will include is a CDI Producer, which is responsible for creating instances of a JCR Session object:

public class SessionProducer {

    @Resource(mappedName = "java:/jcr/sample")
    private Repository sampleRepository;
 
    @RequestScoped
    @Produces
    public Session getSession() throws RepositoryException {
        System.out.println("Creating new session...");
        return sampleRepository.login();
    }
     
    public void logoutSession( @Disposes final Session session ) {
    	System.out.println("Closing session...");
        session.logout();
    }
}

The javax.jcr.Session object provides read and write access to the content of a particular workspace in the repository. In our example, the Session is bound to the repository named "sample" that is available under the JNDI tree as "java:/jcr/sample".

 The Session object will be injected into our main CDI Bean, which is in charge to insert new Nodes into the repository:

@Model
public class RepositoryManager {

	String node;
	String path;

	@Inject
	private Session jcrSession;

	public void add() {

		System.out.println("Session established successfully to repository at: "
						+ jcrSession.getRepository());
		try {   
		    //  Returns the node at the specified absolute path in the workspace.  
			Node rootNode = jcrSession.getNode(path);
			
            // Add a new Node under the path specified by rootNode 
			rootNode.addNode(node);

            // Validates all pending changes currently recorded in this Session. 
			jcrSession.save();
			FacesContext context = FacesContext.getCurrentInstance();     
	         context.addMessage(null, new FacesMessage("Info", "Added Node " + node ));

		} catch (Exception e) {
			System.out.println("Could not complete request" + e);
		}
	}
	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getNode() {
		return node;
	}

	public void setNode(String node) {
		this.node = node;
	}
}

As you can see from the above commented code, by using CDI Producers it is trivial to access to the JCR Session and manage the Nodes of the repository. 

And here is the first view that enables adding data via the RepositoryManager bean:

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">

<h:head></h:head>

<h:body>
	<p:growl id="growl" showDetail="true" sticky="true" />
	<h:form id="form">
		<h3>ModeShape 4 Demo</h3>
		<h:panelGrid columns="2" cellpadding="5">
			<h:outputText value="Path: " />
			<p:inputText id="path" value="#{repositoryManager.path}" />

			<h:outputText value="Node: " />
			<p:inputText id="node" value="#{repositoryManager.node}" />

		</h:panelGrid>

		<p:commandButton id="add" action="#{repositoryManager.add}"
			update=":growl" value="Add" />
		<p:commandButton id="display" action="display" value="View" />
		<br />

	</h:form>

</h:body>
</html>

The above code is pretty simple and includes the PrimeFaces library which is now the de facto standard for JSF applications. 

 modeshape 4 tutorial

So far we have covered Node insertion. What about having a look at our repository ? the PrimeFaces library has an awesome showcase of components for showing data. I have chosen the org.primefaces.model.TreeNode which reminds me of the good old Swing interfaces. By using the TreeNode with JCR API we can easily create a Bean which produces the content of the Repository tree:

@Model
public class TreeView implements Serializable {

	private TreeNode root;
	@Inject
	private Session jcrSession;

	@PostConstruct
	public void init() {
		root = new DefaultTreeNode("Root", null);

		try {
			Node rootNode = jcrSession.getRootNode();
			root = newNodeWithChildren(rootNode, null);

		} catch (Exception e) {

			e.printStackTrace();
		}

	}

	public TreeNode newNodeWithChildren(Node jcrNode, TreeNode parent)
			throws Exception {
		TreeNode newNode = new DefaultTreeNode(jcrNode.getName(), parent);
		NodeIterator nodeList = jcrNode.getNodes();
		while (nodeList.hasNext()) {
			Node tt = (Node) nodeList.next();
			TreeNode newNode2 = newNodeWithChildren(tt, newNode);

		}

		return newNode;
	}

	public TreeNode getRoot() {
		return root;
	}
}

 The second view, just contains as little as a tree elementm with a reference to our CDI Bean:

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">

<h:head></h:head>

<h:body>
	<h:form id="form">

		<h3 style="margin-top: 0">Repository</h3>
		<p:tree value="#{treeView.root}" var="node" orientation="horizontal">
			<p:treeNode>
				<h:outputText value="#{node}" />
			</p:treeNode>
		</p:tree>
		<h:commandButton id="Home" action="index" value="Home" />
	</h:form>
</h:body>
</html>

 And here is a view of our Repository which uses a client-based TreeNode:

modeshape 4 tutorial

Isn't it impressing how we can have a view of our JCR Repository with so few lines of code ?

Lastly, here is the pom.xml I have used to compile and deploy the Modeshape web application on WildFly:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.mastertheboss</groupId>
	<artifactId>modeshape-webapp</artifactId>
	<version>1.0</version>
	<packaging>war</packaging>

	<name>Basic Modeshape Example</name>

	<properties>
		<version.modeshape>4.1.0.Final</version.modeshape>
		<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<version.jboss.bom>8.0.0.Final</version.jboss.bom>
	</properties>

	<repositories>
		<repository>
			<id>JBoss Repository</id>
			<url>https://repository.jboss.org/nexus/content/groups/public/</url>
		</repository>
	</repositories>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.wildfly.bom</groupId>
				<artifactId>jboss-javaee-7.0-with-all</artifactId>
				<version>${version.jboss.bom}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.modeshape.bom</groupId>
				<artifactId>modeshape-bom-jbossas</artifactId>
				<version>${version.modeshape}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>

		<dependency>
			<groupId>javax.jcr</groupId>
			<artifactId>jcr</artifactId>
		</dependency>

		<dependency>
			<groupId>org.modeshape</groupId>
			<artifactId>modeshape-jcr-api</artifactId>
		</dependency>


		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>primefaces</artifactId>
			<version>5.1</version>
		</dependency>
		<dependency>
			<groupId>javax.enterprise</groupId>
			<artifactId>cdi-api</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.spec.javax.faces</groupId>
			<artifactId>jboss-jsf-api_2.2_spec</artifactId>
			<scope>provided</scope>
		</dependency>


	</dependencies>
	<build>

		<finalName>${project.artifactId}</finalName>

		<plugins>

			<plugin>
				<groupId>org.wildfly.plugins</groupId>
				<artifactId>wildfly-maven-plugin</artifactId>
				<version>1.0.2.Final</version>
			</plugin>
		</plugins>
	</build>
</project>

Since we have included the Maven WildFly plugin, you can deploy your application to WildFly with:

$ mvn clean install wildfly:deploy

 Download the source code of the Modeshape 4 in action tutorial.

Follow us on Twitter