In this tutorial we will show how to run ModeShape from within a Java EE application deployed on JBoss AS 7, as a back-end for a PrimeFaces GUI component (The FileUpload).

Installing ModeShape on JBoss AS 7

The first thing we will need to do is downloading the latest ModeShape AS7 kit (version 3.1.2.Final or later).

This kit is a ZIP archive that is intended to be unzipped directly into the AS7 installation. Doing so will not override any of the files in a standard AS7 installation.

 Once unzipped the ModeShape AS7 kit into your AS7 distribution you will get the following upgrades:

  • ModeShape schema (modeshape_1_0.xsd)
  • ModeShape modules (javax/jcr/, org/modeshape,org/hibernate/search-engine/4.1/,org/apache/lucene/3.5/)
  • ModeShape configuration (standalone-modeshape.xml)

Besides this, the kit also deploys the "modeshape-rest" web application as an exploded WAR file. This web application provides the RESTful API to all of the repositories and their workspaces. If you don't plan to use the RESTful API, simply undeploy it or remove it.

Finally, regarding security, one of the ModeShape modules contains two files (under modules/org/modeshape/main/conf) that define the users and roles for the default security domain used by ModeShape:

modeshape-users.properties
modeshape-roles.properties

You can edit these files to add users, or define your different security domain by defining for each user the ModeShape roles found in the modeshape-roles.properties file.

ModeShape in action !

Now let's test ModeShape with an AS7 application which uses PrimeFaces to pickup a file to be uploaded. In our case, instead of copying the file into the Server filesystem, we will upload it into the JCR repository.
Here's the sample upload.xhtml page: (Please refer to this tutorial for more information about this component)

 <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" >

        <p:fileUpload fileUploadListener="#{fileUploadController.upload}"
      allowTypes="/(\.|\/)(gif|jpe?g|png)$/" sizeLimit="100000" description="Select Images"/>

    </h:form>
    <h:message />
  </h:body>
</html>

And this is the FileUploadController ManagedBean which performs the Job:

package com.mastertheboss;
import java.io.*;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.jcr.*;
import org.modeshape.jcr.api.JcrTools;
import org.primefaces.event.FileUploadEvent;
 
@ManagedBean(name="fileUploadController")
public class FileUploadController {
   
   @Resource(mappedName="java:/jcr/sample")
   private Repository repository; 
   private JcrTools tools = new JcrTools();
   
    public void upload(FileUploadEvent event) {  
        String fileNamePath =  event.getFile().getFileName(); 
        String fileName = fileNamePath.substring(fileNamePath.lastIndexOf(File.separatorChar) + 1);
        
        try {
            copyFile(fileName, event.getFile().getInputstream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        FacesMessage msg = new FacesMessage("Success! ", fileName + " is uploaded.");  
        FacesContext.getCurrentInstance().addMessage(null, msg);
        // Do what you want with the file      
    }  
    
    public void copyFile(String fileName, InputStream in) {
        String workspaceName = "default";
        Session session = null;
        try {
            session = repository.login(workspaceName);
            // Create the '/files' node that is an 'nt:folder' ...
            Node root = session.getRootNode();
    
            Node filesNode = root.addNode("files", "nt:folder");
                            
            InputStream stream = 
                    new BufferedInputStream(in);
            // Create an 'nt:file' node at the supplied path ...
            Node fileNode = filesNode.addNode(fileName,"nt:file");
            
 
            // Upload the file to that node ...
            Node contentNode = fileNode.addNode("jcr:content", "nt:resource");
            Binary binary = session.getValueFactory().createBinary(stream);
            contentNode.setProperty("jcr:data", binary);
            
            session.save();
                      
        } catch ( Exception e1) {
            e1.printStackTrace();
        } finally {
            // Always close the session ...
            if ( session != null ) session.logout()
        }           
    }

    public void copyFile2(String fileName, InputStream in) {
        String workspaceName = "default";
        Session session = null;
        try {
            session = repository.login(workspaceName);
            
            // Most of the above code could be replaced with a single call to
            // our JcrTools utility. This will create any missing intermediate
            // nodes (such as "/files" the first time this call is made)
            // using a primary type of "nt:folder". If the latter is not ideal,
            // you can use the "findOrCreateNode(...)" method to do the same            
            // but specify the primary type for the missing nodes.
            // This utility method will update the file node if it is already
            // there (rather than always create it).
            tools.uploadFile(session,"/files/" + fileName, stream);
            
            session.save();
                      
        } catch ( Exception e1) {
            e1.printStackTrace();
        } finally {
            // Always close the session ...
            if ( session != null ) session.logout()
        }           
    }
}

Two things to notice: the first is that we are injecting the JCR Repository directly in our application which avoids us lots of headaches (starting/stopping the engine)
 
   @Resource(mappedName="java:/jcr/sample")
   private Repository repository; 

Next, as you can see, there's one more copyFile2 method which shows how to performs uploading with a single call using the JcrTools utility class.
If you are curious to know where the sample JCR repository stores its data, just have a look at the modeshape subsystem:

 <local-cache name="sample">
                    <transaction mode="NON_XA"/>
                    <file-store relative-to="jboss.server.data.dir" path="modeshape/store/sample" passivation="false" purge="false"/>
 </local-cache>


As you can see this basic repository uses as file store the folder JBOSS_HOME/standalone/data and runs in NON_XA mode.
That's all. In order to compile and package your application, we need to include in our pom.xml, the required JBoss AS (and Java EE) + ModeShape + PrimeFaces dependencies and a couple of additional dependencies such as org.apache.commons and commons-fileupload which are required for running PrimeFaces' file uploader

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mastertheboss</groupId>
    <artifactId>modeshape-webapp</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>modeshape-webapp Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <version.org.richfaces>4.2.0.Final</version.org.richfaces>

        <version.org.jboss.bom>1.0.0.Final</version.org.jboss.bom>

        <modeshape.version>3.1.1.Final</modeshape.version>
        <!-- other plugin versions -->
        <version.compiler.plugin>2.3.1</version.compiler.plugin>
        <version.surefire.plugin>2.4.3</version.surefire.plugin>
        <version.war.plugin>2.1.1</version.war.plugin>

        <!-- maven-compiler-plugin -->
        <maven.compiler.target>1.6</maven.compiler.target>
        <maven.compiler.source>1.6</maven.compiler.source>
    </properties>

    <dependencyManagement>
        <dependencies>

            <dependency>
                <groupId>org.jboss.bom</groupId>
                <artifactId>jboss-javaee-6.0-with-tools</artifactId>
                <version>1.0.0.M11</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <dependency>
                <groupId>org.modeshape.bom</groupId>
                <artifactId>modeshape-bom-jbossas</artifactId>
                <version>3.1.0.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- Import the Common Annotations API (JSR-250), we use provided scope 
            as the API is included in JBoss AS 7 -->
        <dependency>
            <groupId>org.jboss.spec.javax.annotation</groupId>
            <artifactId>jboss-annotations-api_1.1_spec</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.spec.javax.faces</groupId>
            <artifactId>jboss-jsf-api_2.1_spec</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.jcr</groupId>
            <artifactId>jcr</artifactId>
        </dependency>
        <!-- Directly depend on ModeShape's public API -->
        <dependency>
            <groupId>org.modeshape</groupId>
            <artifactId>modeshape-jcr-api</artifactId>
        </dependency>


        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>3.5</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>modeshape-webapp</finalName>
    </build>
    <repositories>

        <repository>
            <id>prime-repo</id>
            <name>PrimeFaces Maven Repository</name>
            <url>http://repository.primefaces.org</url>
            <layout>default</layout>
        </repository>

        <repository>
            <id>JBoss-Releases</id>
            <url>https://repository.jboss.org/nexus/content/repositories/releases/</url>
        </repository>
    </repositories>
</project>



Here's the application GUI in action:

modeshape jboss as7 tutorial
As you can see, once you have gone through some uploads, the filestore's binary subfolder gets crowded with the pictures you have uploaded.

modeshape jboss as 7 primefaces tutorial

 


 

Now that we have learnt how to store images in the JCR repository, we will show how to display the uploaded images. For this purpose let's add one more page which will display the single images using a Primefaces component named graphicImage.

The graphicImage is a simple but effective component which uses the StreamedContent API to display any binary image easily. This binary image could be images stored in a database, in a JCR Repository (like in our example) or images can be created programmatically on-the-fly.

Add the following display.xhtml image to your project:

<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>Dynamic Image Display</h3>
        <p:dataTable value="#{dynamicImageController.list}" var="item"
            id="mydata">
            <p:column>
                <f:facet name="header">Image</f:facet>
                <h:outputText value="#{item.name}" />
            </p:column>
            <p:column>
                <f:facet name="header">View</f:facet>
                <h:commandButton id="book"
                    action="#{dynamicImageController.showImage(item.name)}"
                    value="Show Image" />
            </p:column>
        </p:dataTable>
        <br />
        <p:graphicImage value="#{dynamicImageController.image}" />
    </h:form>
</h:body>
</html>

And here's the DynamicImageController, which gets injected the Repository, populates a datatable in the @Postconstruct init() method and uses the method showImage to stream the Image content:
package com.mastertheboss;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import javax.jcr.*;

import org.modeshape.jcr.api.JcrTools;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
@ManagedBean 
@SessionScoped
public class DynamicImageController {


    @Resource(mappedName="java:/jcr/sample")
    private Repository repository; 
    private JcrTools tools = new JcrTools();

    List<Image> list = new ArrayList();

    Session session = null;

    public List<Image> getList() {
        return list;
    }

    public void setList(List<Image> list) {
        this.list = list;
    }


    @PostConstruct
    public void init() {
        try {
            // Create a session ...
            session = repository.login("default");

            Node doc = session.getNode("/files/");
            tools.printNode(doc);
            NodeIterator nodeList = doc.getNodes();
            while (nodeList.hasNext()) {
                Node nodeImage = nodeList.nextNode();
                list.add(new Image(nodeImage.getName()));
            } 
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            // Always close the session ...
            if ( session != null ) session.logout();
        }    

    }

    private StreamedContent image;

    public DynamicImageController() {


    }

    public StreamedContent getImage() {
        return image;
    }

    public void showImage(String name) {


        try {
            Node doc = session.getNode("/files/"+name);
            Node imageContent = doc.getNode("jcr:content");
            Binary content = imageContent.getProperty("jcr:data").getBinary();
            InputStream is = content.getStream();

            image = new DefaultStreamedContent(is, "image/png");

        } catch (PathNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (RepositoryException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

Once launched the display.xhtml displays the list of available pictures in the JCR Repository:

modeshape jboss as 7 tutorial

By clicking on the "Show Image", the Image is streamed and loaded into the graphicImage as shown by the following picture:

modeshape tutorial jboss as 7

I want to thank Randall Hauch (leader of the ModeShape project) for providing great tips and suggestions to this article!

Download the sample code for this article.

0
0
0
s2smodern