ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

What is Java Content Repository
Pages: 1, 2, 3, 4

Developing a Blogging Application

With our Apache Jackrabbit installation built and configured, it's time to take the next step and build a sample application. In this section, we will develop a sample blogging application using the JCR-170 API. We need two things for developing this sample application: a backend to add, update, delete, and remove content in the content repository, and a client to provide a UI for performing these operations.

First we create clear-cut separation between these two parts by defining a DAO interface for the backend layer. So, create BlogEntryDAO.java interface like this

public interface BlogEntryDAO {
    public void insertBlogEntry(BlogEntryDTO blogEntryDTO)
        throws BlogApplicationException;
    public void updateBlogEntry(BlogEntryDTO blogEntryDTO)
        throws BlogApplicationException;
    public ArrayList getBlogList()
        throws BlogApplicationException;
    public BlogEntryDTO getBlogEntry(String blogTitle)
        throws BlogApplicationException;
    public void removeBlogEntry(String blogTitle)
        throws BlogApplicationException;
    public ArrayList searchBlogList(String userName)
        throws BlogApplicationException;
    public void attachFileToBlogEntry(String blogTitle, InputStream uploadInputStream)
        throws BlogApplicationException;
    public InputStream getAttachedFile(String blogTitle)
        throws BlogApplicationException;

As you can see, this class has methods for adding, updating, searching for blog entries, and two methods for dealing with binary content. Next, we need a DTO class that will be used for carrying data between the web layer and backend layer. Create the BlogEntryDTO class like this:

public class BlogEntryDTO {

    private String userName;
    private String title;
    private String blogContent;
    private Calendar creationTime;

    //Getter and setter methods for each of these properties        

Every blog entry will have four properties associated with it: userName, title, blogContent, and creationTime. With this interface between the UI layer and backend layer in place we can implement either layer. Because of space constraint, we have decided not to spend time talking about the UI layer; instead you can download sample code for this application from the resources section, where you'll find a sample Struts-based UI for BlogEntryDAO. The next section describes implementing the backend for the blogging application by implementing BlogEntryDAO.

Connecting to Jackrabbit

The first thing that we want to do in developing the backend is to write the component that gets a connection to Jackrabbit. To keep things simple, we will get the connection to Jackrabbit at application startup time and drop that connection when the application shuts down. Since we are developing a Struts application, we need to create our own PlugIn class that gets control at application startup and shutdown times, like this:

public class JackrabbitPlugin implements PlugIn{
    public static Session session;
    public void destroy() {
    public void init(ActionServlet actionServlet, ModuleConfig moduleConfig) 
    throws ServletException {
        try {
            Repository repository = new TransientRepository();
            session = repository.login(new SimpleCredentials("username",
        } catch (LoginException e) {
            throw new ServletException(e);
        } catch (IOException e) {
            throw new ServletException(e);
        } catch (RepositoryException e) {
            throw new ServletException(e);            
    public static Session getSession() {
        return session;

The init() method of JackrabbitPlugin class will get called at application startup and destroy() method will get called at shutdown. The code inside the init() method is used for getting the connection to Jackrabbit. The first thing we do is set the org.apache.jackrabbit.repository.home system property to point to c:/temp/blogging, indicating where Jackrabbit should store its data. Next, create a new instance of TransientRepository. This is a class provided by Apache Jackrabbit, offering a proxy to the repository. It starts up the repository automatically when the first session is opened, and automatically stops the repository when the last session is closed.

Once you have a repository object, you can call its login() method to open a connection. login() takes an object of type Credential as an and argument; if this is null, it is assumed that authentication is handled by mechanism external to the repository itself (for example, the JAAS framework). Since we are not passing a workspace name argument to login(), Jackrabbit will create default a workspace and return a Session object for that particular workspace. The Session object encapsulates both the authorization settings of a particular user and a binding to the workspace specified by the workspaceName passed on login. Please note that there is a one-to-one mapping between session and workspace.

Add Content

With Apache Jackrabbit set up properly and our code to connect to it, we can implement the methods of BlogEntryDAO. The first method that we want to implement is insertBlogEntry(), which is used for adding new blogEntry nodes:

public void insertBlogEntry(BlogEntryDTO blogEntryDTO)
            throws BlogApplicationException {
        Session session = JackrabbitPlugin.getSession();
        Node rootNode = session.getRootNode();
        Node blogEntry = rootNode.addNode("blogEntry");
        blogEntry.setProperty("title", blogEntryDTO.getTitle());
        blogEntry.setProperty("blogContent", blogEntryDTO.getBlogContent());
        blogEntry.setProperty("creationTime", blogEntryDTO.getCreationTime());
        blogEntry.setProperty("userName", blogEntryDTO.getUserName());            

The first thing that we are doing in this method is getting an instance of the session object initialized in the JackrabbitPlugin class. After that, we call getRootNode() on the session object, which returns root node ("/") of the workspace. Once we have an object pointing to the root node, we can add a new child node to it by calling addNode() method on rootNode; this will create a new child node named blogEntry. After that, we can set the actual content of blogEntry as properties of the node. You might remember from the discussion on the repository model that properties are leaves and are used for storing actual content. In the case of blogEntery, every blogEntry will have four properties: title, blogContent, creationTime, and userName, each of which can be set by calling setProperty() on the newly created blogEntry node.

Notice the use of the method session.save() in the insertBlogEntry() method. This method is needed because changes made through methods of Session, Node, or Property are not immediately reflected in the persistent workspace. The changes are held in the transient storage associated with the Session object until they are either persisted using either session.save() or item.save(). Also, Session.save() validates changes and if this validation succeeds, it persists all pending changes currently stored in the Session object. Until this is done, changes made using one session are not made visible to other sessions. Conversely, Session.refresh(false) discards all pending changes currently stored in session. For more fine-grained control over which changes are persisted or discarded, the method Item.save() and Item.refresh() are also provided. Item.save() saves all pending changes in the Session that apply to a particular item or its subtree. Analogously, Item.refresh(false) discards all pending changes that apply to that item.

In the web UI you can post a new blog entry by going to the http://localhost:8080/<contentroot> page and clicking on "Add node" link, fill out that form, and click submit to invoke the insertBlogEntry() method.

Pages: 1, 2, 3, 4

Next Pagearrow