Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Contents
Table of Contents

Overview (from SLING-1438)

...

See http://tinyurl.com/asfgsoc for the full list of GSoC 2010 projects at the ASF, and http://community.apache.org/gsoc for general GSoC information.

Introduction

Apache Sling is an opensource project with a lot of technologies and features. The goal of this project is to create a mini-CMS, that developers can use to understand how to develop a simple application with Sling. So it is necessary to know a little about two main topics: OSGi and JCR. The following links are useful resources to read something about these technologies.

...

The repository for this project can be found at http://code.google.com/p/davidgsoc2010/.

Some words about David Mini CMS

This project shows some features of Apache Sling and can be used for educational purpose to move your first steps with this framework.

David uses the following opensource library/technologies: 

...

Node creation is a simple task, but you must understand how you can render the information stored in the nodes using Sling.
The first document you can read is the next one: http://dev.day.com/content/ddc/blog/2008/07/cheatsheet/_jcr_content/par/download/file.res/cheatsheet.pdf
It . It simply describes how content resolution works in Sling. 

...

Content loading

You can setup some initial contents that can be used in your application. It is a useful thing, because with a simple configuration you have some nodes already created when your application starts.

...

JSON isn't the only way to load initial content. Further informations about content loading can be found in the Content Loading Bundle Documentation.

Create new entry

There is a script that provide this basic function, /apps/david/new.esp. As you can see in David I choose the ESP scripting language, but as we already said, you can choose among a lot of scripting engines with Sling. This script loads two other script files, used in every script of David: /apps/david/header.esp and /apps/david/menu.esp. These scripts, as the name suggests, contain header informations and the menu for David. 

...

So we loaded these two scripts in new.esp. In addition to this, in this script we defined a simple form, with some input text texts and a CKEditor panel. 

Once the user fills the input, the page is like in the following image

...

If we click on the button and everything goes well, we will see a popup with the text "Entry saved" and our article will be in the repository at the path /content/david/YEAR/MONTH/DAY/somethingliketitle.

As you can see, there isn't a definition for the name of the entry but anyway we will have this entry saved...how is it possible?

...

If the resource doesn't exist, a new item is created. If the resource name ends with /* or /, the name of the item will be created using an algorith that also uses the name of new node. The creation of the new node goes through the SlingPostServlet , a frontend for the content manipulation. This servlet provides also other content operations, as described here.

Authentication

You can submit new entry only if you have already authenticated with Sling. So you can see that on the /apps/david/menu.esp script there is a check for the credentials

In the HTTP POST request there are also some others fields:

  • sling:resourceType=david : This information is stored on the new node, so when we will retrieve this node from the browser, using any extension (for example .article provided by /apps/david/article.esp ) Sling will search under the folder /apps/david. 
  • jcr:mixinTypes=mix:referenceable : Another information that will be stored. In that way this node can be referenceable. This feature will be useful for the tags management.

Authentication

You can submit new entry only if you have already authenticated with Sling. So you can see that on the /apps/david/menu.esp script there is a check for the credentials

Code Block

......
...
Code Block

......
...
<td width="33%" align="right">
	Logged as: <b id="username">????</b>
</td>
</tr>
</table>
<script language="javascript">
	var info = Sling.getSessionInfo();
	if (info.userID=="anonymous")
		document.getElementById("username").innerHTML = 
			info.userID+"<a href='/system/sling/form/login?resource=/content/david.html'>Login</a>";
	else
		document.getElementById("username").innerHTML = info.userID;
</script>
...
...

Let's now explain this code. Using the sling.js, system utility defined in Sling, we can get the session information object. If the userid of this object is anonymous we put a link to the authentication form.

...

The authentication form receives a resource parameter, that is the resource where the user will go after the authentication. This sort of authentication is a basic one, if you want to know more about authentication in Apache Sling you can read the authentication documentation on Sling website.

...

The delete operation is an easy task, because we only have to make a HTTP POST request to the article URL, with a special parameter :operation=delete.

This request is made with a jQuery function bounded to the DELETE link, as you can see in the /apps/david/list.esp script

...

Being an OSGi Component there is the implementation of activate and deactivate methods, which is called when the component is activated/deactivated.

TagGenerator class implements EventListener interface, so in the onEvent method we add the tags of the created node to the tagging structure.

When we delete a node, we can see that there is another AJAX call in the /apps/david/list.esp script before the real removal. There is a call which uses the :operation=deletetag parameter.

This operation is implemented by David, using the sling.gsoc.david.operation.DeleteTagOperation class. In Sling you can define new operations extending SlingPostOperation. The new operation is defined with the constant sling.post.operation as we can see in the next code

Code Block
@Property(value = "deletetag")
static final String OPERATION = "sling.post.operation";

...

To create this XML there is another registered component, which manages the cloud resource type. This component is sling.gsoc.david.servlet.CloudExtension , which extends SlingAllMethodsServlet to manage this new resource type. In the following code of this component you can see how it is used the @Property annotation to configure it

...

Code Block
<h3>Entries</h3><h3>Entries</h3>
	<div>
        <%
        var uuids=tagNode.getProperty("UUIDs").getValues();
        for(var i =0; i<uuids.length; i++) {
        	var uuid=uuids[i];
                var nodeR=session.getNodeByUUID(uuid.getString());
        %>

        	<a href='<%=nodeR.getPath() %>.article'><%=nodeR.title%></a><br>

        <%
        }

        %>

Search for entries

...

You can see in this script as ESP language can be used to manage object related to JCR. Using the method getNodeByUUID of Session we have the node related to a particular UUID, so we can print it in the list.

Search for entries

Also the search is based on ESP script, /apps/david/search.esp . The user can make three different type of search: by title, by text and by tag. The search with title or text are executed using a XPATH query like this

Code Block

var query = queryManager.createQuery(
	"/jcr:root/content/david/*/*/*/element(*, nt:unstructured)[jcr:like(@title, '%"+request.getParameter("qtitle")+"%')] 
	order by @created descending", "xpath");

This query searches the entry with title LIKE (as in SQL) the parameter submitted.

The tag search is a bit different, because the structure of tags in David make it possible to search under the root node /content/tags, where we save the tags informations. So the query is like the following one

Code Block

var searchString =  
"/jcr:root/content/tags//element(*,nt:unstructured)[fn:name()= '"+request.getParameter("qtag")+"'] order by @created descending";

The initial form to perform the search is a simple HTML one, as you can see in the following image

Image Added

Create PDF renditions

Every node in David is an article and it's an easy task to render it as PDF file.

First of all there is a link on every articles and on the main list that links to

Code Block

http://localhost:8080/content/david/2010/08/14/myarticle.pdf

So it's a new extension called for the node. This extension, as we already have seen, can be managed by a Java class defined in our bundle and deployed on Sling. In David the PDF Extension is managed by sling.gsoc.david.servlet.PdfExtension. In this component there is the rendering of the node using iText library and the node, for which this component can be activated, can be a standard article or the root node. 

If this extension is used with a standard article, the following image is what we will give

Image Added

In the other case, we will have a PDF with the list of articles in David.

Image Added

Scheduler service

Every Sling application can use the opensource scheduler Quartz, provided by the Commons Scheduler bundle (this requires also another bundle, org.apache.sling.commons.threads).

Based on this scheduler there is a simple service, implemented by sling.gsoc.job.JobScheduler and sling.gsoc.job.SendTask. The first is the class that creates a SendTask and schedules it with Quartz. The second one is a simple class that send informations about David (the number of articles and tags available) with an email.