Fun with Jahia's REST API (tutorial using JQuery and Bootstrap)

Jahia’s REST API is a simple yet powerful API that provides you with basic CRUD operations on the underlying content repository. As almost everything in Jahia is stored in the Jackrabbit content repository (using the Java Content Repository API), being able to use a simple REST API makes it possible to perform a lot of changes inside Jahia. The REST API may even be extended using action classes, but in this article we will first look at the basics of interfacing with the API.

As most REST APIs, Jahia exposes objects mapped at specific URLs on which you can perform HTTP operations to interact with them. Most REST operations will use the POST HTTP operation, in order to indicate that this operation is unique and shouldn’t be cached by proxy servers or other cache servers (HTTP GET operations on the other hand are usually cacheable, and may be interesting to retrieve views of a specific object in the system).

In the example we will be detailing, we will not use any server-side technologies, we will simply show how you can use HTML and Javascript to interface with Jahia’s REST API, which will make it easy to understand how things are set up even if you intend to use the API with other technologies such as Java code (server side, Android devices), PHP, C# (Windows destop, Windows Mobile phones and tablets), Objective C (iOS devices such as the iPhone or the iPad, Mac OS X) or any other language that can talk to HTTP sockets (which by definition includes a lot of programming languages).

The HTML file we will build here is intended to be hosted on any HTTP server such as Apache or IIS, but as our relative URLs point to a Jahia installation it should be deployed inside the tomcat/webapps/ROOT directory. So the first step is to create a rest.html file with the following basic structure:

<html>
<head>
   <title>Jahia REST API JQuery examples</title>
   <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
   <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
   <script type="text/javascript" src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
</head>
<body>
</body>
</html>

As you can see in the above code, we will be using the following HTML frameworks to build our example:

- Twitter Bootstrap : this is a Javascript and CSS framework that makes basic HTML look good. We use a hosted version of Bootstrap so that we don’t have to include it as a separate file. Everything gets pulled directly from a CDN (content delivery network), reducing the load on our own server. The flipside of using a CDN is that we depend on the public internet so if you intend to build a solution that will not have access to the internet you will probably prefer to host the files yourself.

- JQuery : the famous Javascript framework, that makes it really easy to manipulate DOM objects by using CSS-like queries. If you’re not familiar with this framework yet, I highly recommend you check it out before going any further, since we will be assuming that readers are at least familiar with it in this tutorial. We include the framework from Google’s CDN this time.

Now that we have the basics in place, let’s dive in and start integrating with Jahia’s API. The first thing we will develop is a login form, in order to make sure that we can use an authenticated session to connect with our Jahia server. Although Jahia supports multiple authentication systems (container-based, SSO, Kerberos, NTLM or you can even plug in your own !), having a simple form-based authentication makes it easy for very light clients to open a session in Jahia. Sessions are server-based objects, and they are tracked on the client side using a cookie named JSESSIONID, so we are assuming that whatever client you will be using will properly receive and send cookies, which is an important requirement for proper session tracking. Of course this is the default behavior of a web browser so we won’t have to deal with this, but it might be interesting to remember if you are writing your own custom HTTP client.

Accord to the REST API reference documentation, for the login action we will need to set up a few request parameters. We can simply use an HTML form to do so:

  <form name='loginForm' action="/cms/login">
       <fieldset>
           <legend>Login</legend>
           <label for="UserName">User name:</label>
           <input id="UserName" type="text" name="username"/>
           <label for="Password">Password:</label>
           <input id="Password" type="password" name="password"/>
           <input type="hidden" name="redirectActive" value="false"/>
           <input type="hidden" name="restMode" value="false"/>
           <button class="btn btn-primary" type="submit">Login</button>
       </fieldset>
   </form>

As you can see this form is quite basic. It has a unique name that we will use later when adding the JQuery code, as well as an action URL that points to a Jahia installation running on the same server as the HTML file is hosted on. Of course should you want to separate the two simply adjust the action URL to add a full absolute URL such as https://myserver:myport/cms/login (although you might have to be careful about same origin policy issues, which might require some adjustments on the example we provide here, for example by using JSONP or CORS, but this might require adding a filter on the server side to support it. Here’s one for CORS). In general you should try to use the same domain to simplify deployments, and possibly use a front-end server to dispatch internally, but if you cannot get around this limitation, implementing JSONP or CORS could be interesting solutions.

Submitting the form as-is will work, but will redirect the browser to the /cms/login URL which is not a very nice experience since we will want to stay on the same HTML page for all our REST operations. In order to do this we could either use the redirect parameters that are described in the reference documentation, or use an AJAX request to submit the form asynchronously, while staying on the same HTML page. JQuery provides a very elegant and compact way of performing AJAX requests and therefore we will use it to implement our form submission code:

  <script type="text/javascript">
       $(document).ready(function () {

           var loggedIn = false;

           $('form[name=loginForm]').submit(function () {
               $.post($(this).attr('action'), $(this).serialize(), function (res) {
                   if (res == 'OK') {
                       loggedIn = true;
                   } else {
                       alert("Couldn't log you in, please check the user name and password!")
                   }
               });
               return false; // prevent default action
           });

       });
   </script>

The above snippet is placed in the HTML’s head tag, just before the body tag. It defines a variable that tracks the session status (loggedIn), that we set to true if the login was successful. The $.post is where all the magic happens. This JQuery function actually performs the AJAX request and upon return it calls the callback function we defined that checks the resulting body to see if the login information was validated or not by the Jahia server.

So that’s all there is to the login, simply using a basic HTML form and a small JQuery code snippet we have defined an interface for logging into Jahia using the REST API. The actual form looks like this thanks to Bootstrap’s nice CSS:

Much in the same way, we can implement the logout form:

  <form name='logoutForm' action="/cms/logout">
       <fieldset>
           <legend>Logout</legend>
           <input type="hidden" name="redirectActive" value="false"/>
           <input type="hidden" name="restMode" value="false"/>
           <button class="btn btn-primary" type="submit">Logout</button>
       </fieldset>
   </form>

and the corresponding JQuery javascript snippet, to be inserted just after the login form’s $.post function call:

          $('form[name=logoutForm]').submit(function () {
               $.post($(this).attr('action'), $(this).serialize(), function (res) {
                   loggedIn = false;
               });
               return false; // prevent default action
           });

The form will simply display a blue logout button that will send a request to logout the user currently tracked in the server-side session.

Unfortunately right now in our HTML file we have two forms that are displayed at once, one for the login and the other for the logout, which do not really reflect the actual state of the server side session. Fortunately using JQuery we can very easily show and hide sections of the HTML to make sure that we don’t display both forms simultaneously. First we will start by adding a default style to hide the logout form :

  <form name='logoutForm' action="/cms/logout" style="display:none">

And then we will control the showing and hiding of the forms by adding the following code in the login function callback (after the loggedIn=true statement):

                      $("form[name=logoutForm]").show();
                       $("form[name=loginForm]").hide();

and for the logout call back (after the loggedIn=false statement):

                  $("form[name=loginForm]").show();
                   $("form[name=logoutForm]").hide();

Now the forms will show alternatively, depending on whether the user is logged in or not.

Now that we have properly integrated session authentication, we will now look at content retrieval and creation. First we will retrieve a content “folder” that exists on any Jahia 6.5+ system that is available at the following URL:

/cms/render/live/en/sites/systemsite/contents

Jahia uses URL file extensions to control the rendering format of the object it is generating, so if we want to retrieve an HTML page rendering of the above object we will use :

/cms/render/live/en/sites/systemsite/contents.html

But as in our tutorial we are working with AJAX requests we will instead use JSON output. We will use Jahia’s built-in JSON rendering views that may be accessed using an URL similar to this one:

/cms/render/live/en/sites/systemsite/contents.full.json?prettyPrint=true

The “prettyPrint=true” parameter is optional but quite useful when debugging requests since it will use indenting to make sure the JSON output is easy to read. This parameter should of course be removed once the development is completed in order to reduce the size of the JSON response.

Now that we know which URL to used to retrieve a content object using the REST API, we will put all this together by rendering the retrieved data in our HTML page. First we setup a DIV we will use to mark where we want to render the data. We simply place the following DIV tag below the two login and logout forms:

<div id="contentList"></div>

Note that we use an “open” div as we will be adding content beneath it (it seems browser behave differently with a closed DIV tag).

Here is the JQuery call that will perform the AJAX request for the JSON view of the content object:

          function refreshList() {
               $("#contentList").html("Loading...");
               $.ajax({
                   url: "/cms/render/live/en/sites/systemsite/contents.full.json?prettyPrint=true",
                   cache: false
               }).done(function (json) {
                           var listNode = $("#contentList");
                           var listHTML = '<table class="table table-striped">';
                           listHTML += "<thead><tr><th>Node name</th><th>Type</th><th>Text</th></tr></thead>"
                           if (json.hasChildren) {
                               $.each(json.childNodes, function (index, data) {
                                   listHTML += '<tr><td>' + data['j:nodename'] +
                                           '</td><td>' + data['jcr:primaryType'] +
                                           '</td><td>' + data['text'] + '</td></tr>';
                               });
                           }
                           listHTML += '</table>';
                           listNode.html(listHTML);
                       });
           }

Although it looks more complex than the other AJAX calls, it is actually quite simple, most of the code is there to generate the HTML table code that will display the retrieved results. Basically we access the child nodes of the content object and render them in a table. Here is a screenshot of the resulting table:

Again you can see why Bootstrap is a very useful framework, using simply a few predefined classes (“table table-striped”) it renders a very clean looking table. Here we have chosen to display a limitated selection of the content node’s attribute but as the JSON view returns all the node’s properties you could display a lot more.

As you may have noticed the rendering AJAX call is actually included inside a function we called “refreshList”. This makes it easy to refresh the list from any call back, and therefore we can simply add it to our login call back after the calls to show and hide the forms:

                       refreshList();

In the same manner we can refresh the list after a logout, making sure it is up to date with the permissions of the users (see full source code for the example).

The last piece of the puzzle we will show in this tutorial is how to create a new content object using the REST API and AJAX requests. In order to do this we will first select the type of content object we want to create. We will use one of the basic types defined in Jahia’s default module (in the modules/default/META-INF/definitions.cnd) file:

[jnt:text] > jnt:content, jmix:basicContent, jmix:editorialContent

- text (string) i18n

As you can see this very simple content node type definition includes only one property that is a text string. We can therefore easily setup the form that will be used to populate it:

<form name='newNodeForm' action='/cms/render/live/en/sites/systemsite/contents/*' style="display:none">
   <fieldset>
       <legend>New node</legend>
       <label for="nodeText">Text:</label>
       <input id="nodeText" type="text" name="text" placeholder="Enter your text here..."/>
       <label for="jcrNodeName">Node name:</label>
       <input id="jcrNodeName" type="text" name="jcrNodeName" placeholder="Enter a node name here (optional)..."/>
       <input type="hidden" name="jcrNodeType" value="jnt:text"/>
       <input type="hidden" name="jcrReturnContentType" value="json"/>
       <button class="btn btn-primary" type="submit">Create</button>
   </fieldset>
</form>

As you can see if the above form code, we need to setup a few hidden fields that help control the node creation. The most important one is the “jcrNodeType” that specifies the content type definition that will be used to create the new content node. Another important thing to note is the format of the action URL that uses a “*” character to indicate that we are creating a sub node of the “contents” object. The “jcrReturnContentType” parameter has two purposes: to indicate that we want to receive a result in JSON format and also to deactivate the default redirect that Jahia performs after a content creation operation.

Submitting the form using an AJAX request is therefore performed by adding the following JQuery code:

          $('form[name=newNodeForm]').submit(function () {
               $.post($(this).attr('action'), $(this).serialize(), function (res) {
                   alert('Content created successfully');
                   refreshList();
               });
               return false; // prevent default action
           });

As you can see upon content creation we perform a call to the “refreshList” method to make sure that the list is reloaded to display the newly created content object.

This concludes our tutorial on using Jahia’s REST API using HTML, JQuery and Bootstrap. As you have seen, despite the simplicity of the API, it is possible to build powerful web solutions with very little code, and in this case, entirely on the client. The example we have provided shows how to authenticate, render and create new content. Of course there are other functions available in the REST API such as the possibility to delete content objects, search for content objects or users and groups, or even to define your own custom actions to be performed on a REST action. Stay tuned for upcoming blog posts, we might expand on this example to go into more advanced uses of this API.

The full source code of this example is available on Jahia's Github repository.

Serge Huber
Serge Huber

Serge Huber est co-fondateur et directeur technique de Jahia. Il est membre de l'Apache Software Foundation et président du comité de gestion du projet Apache Unomi, ainsi que co-président de l'OASIS Customer Data Platform Specification.

Retour