incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Sling > GSoC 2010 mini-CMS project
Date Sat, 14 Aug 2010 18:04:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1810/9/1/_/styles/combined.css?spaceKey=SLING&amp;forWysiwyg=true" type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/SLING/GSoC+2010+mini-CMS+project">GSoC 2010 mini-CMS project</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~fpaparoni">Federico Paparoni</a>
    </h4>
        <br/>
                         <h4>Changes (12)</h4>
                                 
    
<div id="page-diffs">
            <table class="diff" cellpadding="0" cellspacing="0">
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h1. {toc} <br> <br> <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h1. Overview (from SLING-1438) <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >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. <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h1. Introduction <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h1. {color:#003366}{*}Introduction{*}{color} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{color:#000000}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.&amp;nbsp;{color}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. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">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.&amp;nbsp; <br> <br>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. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >*{_}OSGi{_}* <br>* [http://en.wikipedia.org/wiki/OSGi|http://en.wikipedia.org/wiki/OSGi] <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >        %&gt; <br>{code} <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">\\ <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">You can see in this script as ESP language can be used to manage object related to JCR. Using the method getNodeByUUID of [Session|http://www.day.com/maven/jsr170/javadocs/jcr-2.0/javax/jcr/Session.html]&amp;nbsp;we have the node related to a particular UUID, so we can print it in the list. <br></td></tr>
            <tr><td class="diff-unchanged" > <br> <br>h1. Search for entries <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Also the search is based on ESP script, [/apps/david/search.esp|http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/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 <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{code} <br>var query = queryManager.createQuery( <br>	&quot;/jcr:root/content/david/*/*/*/element(*, nt:unstructured)[jcr:like(@title, &#39;%&quot;+request.getParameter(&quot;qtitle&quot;)+&quot;%&#39;)]  <br>	order by @created descending&quot;, &quot;xpath&quot;); <br>{code} <br>This query searches the entry with title LIKE (as in SQL) the parameter submitted. <br> <br>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 <br> <br>{code} <br>var searchString =   <br>&quot;/jcr:root/content/tags//element(*,nt:unstructured)[fn:name()= &#39;&quot;+request.getParameter(&quot;qtag&quot;)+&quot;&#39;] order by @created descending&quot;; <br>{code} <br>The initial form to perform the search is a simple HTML one, as you can see in the following image <br> <br> <br>!http://davidgsoc.files.wordpress.com/2010/08/search.png! <br> <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h1. Create PDF renditions <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Every node in David is an article and it&#39;s an easy task to render it as PDF file. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">First of all there is a link on every articles and on the main list that links to <br> <br>{code} <br>http://localhost:8080/content/david/2010/08/14/myarticle.pdf <br>{code} <br>So it&#39;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|http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/servlet/PdfExtension.java]. In this component there is the rendering of the node using [iText library|http://itextpdf.com/]&amp;nbsp;and the node, for which this component can be activated, can be a standard article or the root node.&amp;nbsp; <br> <br>If this extension is used with a standard article, the following image is what we will give <br> <br> <br>!http://davidgsoc.files.wordpress.com/2010/08/pdf.png! <br> <br>In the other case, we will have a PDF with the list of articles in David. <br> <br>!http://davidgsoc.files.wordpress.com/2010/08/pdflist.png! <br> <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h1. Scheduler service <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br>Every Sling application can use the opensource scheduler [Quartz|http://www.quartz-scheduler.org/], provided by the [Commons Scheduler bundle|http://sling.apache.org/site/scheduler-service-commons-scheduler.html]&amp;nbsp;(this requires also another bundle,&amp;nbsp;[org.apache.sling.commons.threads|http://svn.apache.org/repos/asf/sling/trunk/bundles/commons/threads/]). <br> <br>Based on this scheduler there is a simple service, implemented by [sling.gsoc.job.JobScheduler|http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/job/JobScheduler.java] and [sling.gsoc.job.SendTask|http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/job/SendTask.java]. 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.&amp;nbsp; <br></td></tr>
        </table>
</div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h1><a name="GSoC2010mini-CMSproject-"></a><div>
<ul>
    <li><a href='#GSoC2010mini-CMSproject-'></a></li>
    <li><a href='#GSoC2010mini-CMSproject-Overview%28fromSLING1438%29'>Overview (from SLING-1438)</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Introduction'>Introduction</a></li>
    <li><a href='#GSoC2010mini-CMSproject-'> <span style="color: #003366"><b>Some words about David Mini CMS</b></span></a></li>
    <li><a href='#GSoC2010mini-CMSproject-FirststepsintoSling'> <b>First steps into Sling</b></a></li>
    <li><a href='#GSoC2010mini-CMSproject-'> <span style="color: #003366"><b>Content loading</b></span></a></li>
    <li><a href='#GSoC2010mini-CMSproject-'> <span style="color: #003366"><b>Create new entry</b></span></a></li>
    <li><a href='#GSoC2010mini-CMSproject-Authentication'>Authentication</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Editexistingentry'>Edit existing entry</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Listexistingentries'>List existing entries</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Deleteexistingentry'>Delete existing entry</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Generatethetagscontentstructure'>Generate the tags content structure</a></li>
    <li><a href='#GSoC2010mini-CMSproject-DisplaytagsusingtheFlashbasedanimation'>Display tags using the Flash-based animation</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Listentriesbytags'>List entries by tags</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Searchforentries'>Search for entries</a></li>
    <li><a href='#GSoC2010mini-CMSproject-CreatePDFrenditions'>Create PDF renditions</a></li>
    <li><a href='#GSoC2010mini-CMSproject-Schedulerservice'>Scheduler service</a></li>
</ul></div></h1>



<h1><a name="GSoC2010mini-CMSproject-Overview%28fromSLING1438%29"></a>Overview (from SLING-1438)</h1>

<p>This is a Google Summer of Code 2010, Federico Paparoni has been accepted as a student to work on it, mentored by Bertrand Delacretaz</p>

<p>The goal is to create a mini-CMS with Sling, that demonstrates Sling best practices.</p>

<p>See <a href="http://tinyurl.com/asfgsoc" class="external-link" rel="nofollow">http://tinyurl.com/asfgsoc</a> for the full list of GSoC 2010 projects at the ASF, and <a href="http://community.apache.org/gsoc" class="external-link" rel="nofollow">http://community.apache.org/gsoc</a> for general GSoC information.</p>

<h1><a name="GSoC2010mini-CMSproject-Introduction"></a>Introduction</h1>

<p><font color="#000000">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.&nbsp;</font>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.</p>

<p><b><em>OSGi</em></b></p>
<ul>
	<li><a href="http://en.wikipedia.org/wiki/OSGi" class="external-link" rel="nofollow">http://en.wikipedia.org/wiki/OSGi</a></li>
	<li><a href="http://felix.apache.org/" class="external-link" rel="nofollow">http://felix.apache.org/</a></li>
	<li><a href="http://www.osgi.org/Links/BasicEducation" class="external-link" rel="nofollow">http://www.osgi.org/Links/BasicEducation</a></li>
</ul>


<p><b><em>JCR</em></b></p>
<ul>
	<li><a href="http://jackrabbit.apache.org/" class="external-link" rel="nofollow">http://jackrabbit.apache.org/</a></li>
	<li><a href="http://www.ibm.com/developerworks/java/library/j-jcr/" class="external-link" rel="nofollow">http://www.ibm.com/developerworks/java/library/j-jcr/</a></li>
	<li><a href="http://wiki.apache.org/jackrabbit/DavidsModel" class="external-link" rel="nofollow">http://wiki.apache.org/jackrabbit/DavidsModel</a></li>
</ul>


<p>The repository for this project can be found at&nbsp;<a href="http://code.google.com/p/davidgsoc2010/" class="external-link" rel="nofollow">http://code.google.com/p/davidgsoc2010/</a>.</p>

<h1><a name="GSoC2010mini-CMSproject-"></a><font color="#003366"><b>Some words about David Mini CMS</b></font></h1>

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

<p>David uses the following opensource library/technologies:</p>

<p><font color="#000000">&nbsp;</font></p>

<ul>
	<li><font color="#003366"><a href="http://jquery.com/" class="external-link" rel="nofollow">jQuery&nbsp;</a></font> 1.4.2</li>
	<li><a href="http://jqueryui.com/" class="external-link" rel="nofollow">jQueryUI&nbsp;</a> 1.8</li>
	<li><a href="http://gmarwaha.com/blog/?p=7" class="external-link" rel="nofollow">LavaLamp </a> &#45; A menu plugin for jQuery with cool hover effects&nbsp;</li>
	<li><a href="http://www.roytanck.com/2008/03/06/wordpress-plugin-wp-cumulus-flash-based-tag-cloud/" class="external-link" rel="nofollow">WP-Cumulus SWF</a> &#45;&nbsp;used to display tag cloud</li>
	<li><a href="http://itextpdf.com/" class="external-link" rel="nofollow">iText&nbsp;</a></li>
	<li><a href="http://ckeditor.com/" class="external-link" rel="nofollow">CKEditor&nbsp;</a></li>
</ul>


<p>The available features are</p>
<ul>
	<li>CRUD (Create, Read, Update and Delete) for the content</li>
	<li>Full HTML creation of article</li>
	<li>Creation of PDF rappresentation of a single post or the entire list of contents available</li>
	<li>Tagging system</li>
	<li>Search by title,text,tag</li>
	<li>Send email to someone with the link of article</li>
	<li>Background service that checks number of articles/tags in the repository</li>
</ul>


<p>These aren't space age features, but are useful to understand how to create an application using Apache Sling</p>

<h1><a name="GSoC2010mini-CMSproject-FirststepsintoSling"></a><b>First steps into Sling</b></h1>

<p>Firstly you must setup the environment for Sling, so you can follow the guide at&nbsp;<a href="http://sling.apache.org/site/getting-and-building-sling.html" class="external-link" rel="nofollow">http://sling.apache.org/site/getting-and-building-sling.html</a>.</p>

<p>Now that you created your environment, you can setup some other tools that can be useful during the development:</p>
<ul>
	<li><a href="http://curl.haxx.se/" class="external-link" rel="nofollow">cURL</a> : Command line tool to send HTTP request</li>
	<li><a href="http://svn.apache.org/repos/asf/sling/trunk/contrib/explorers/jquery/" class="external-link" rel="nofollow">JCR Explorer</a> : Extension that create a useful explorer for the JCR repository you are working in</li>
	<li><a href="http://www.bitkinex.com/" class="external-link" rel="nofollow">BitKinex</a> :&nbsp;FTP/SFTP/HTTP/WebDAV Client that can be used to manage the files you uploaded in Sling</li>
</ul>


<p>It's time to make our "Hello world" in Apache Sling.&nbsp;<br/>
Open a console and simply launch the next command:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">curl -F<span class="code-quote">"sling:resourceType=foo/bar"</span> -F<span class="code-quote">"title=Hello world"</span> http:<span class="code-comment">//admin:admin@localhost:8080/content/myfirstnode</span>
</pre>
</div></div>

<p>This is a simple HTTP request, where you pass some parameters and values. Using it you have created a first resource under Sling.&nbsp;<br/>
The resource is a JCR node, as every resource in Sling, put under folder /content. This node has two parameters, title and sling:resourceType.&nbsp;</p>

<p>Node creation is a simple task, but you must understand how you can render the information stored in the nodes using Sling.<br/>
The first document you can read is the next one:&nbsp;<a href="http://dev.day.com/content/ddc/blog/2008/07/cheatsheet/_jcr_content/par/download/file.res/cheatsheet.pdf" class="external-link" rel="nofollow">http://dev.day.com/content/ddc/blog/2008/07/cheatsheet/_jcr_content/par/download/file.res/cheatsheet.pdf</a><br/>
It simply describes how content resolution works in Sling.&nbsp;</p>

<p>Another important information to better understand Sling, is that a resource is rendered by a script.<br/>
Script files are stored under the folders /apps or /libs and there is a wide choice of possible scripting engine:&nbsp;</p>
<ul>
	<li>ESP</li>
	<li>JSP</li>
	<li>Java Servlet</li>
	<li>Scala</li>
	<li>Python</li>
	<li>Groovy</li>
	<li>Ruby</li>
</ul>


<p>To select a script, Sling uses the node's sling:resourceType property. So if we say that&nbsp;sling:resourceType is foo/bar, Sling will search under the /apps/foo/bar/ folder.<br/>
The following links describes how the scripts work and what type of variables we have during the script execution:</p>
<ul>
	<li><a href="https://cwiki.apache.org/SLING/scripting-variables.html" class="external-link" rel="nofollow">https://cwiki.apache.org/SLING/scripting-variables.html</a></li>
	<li><a href="https://cwiki.apache.org/SLING/url-to-script-resolution.html" class="external-link" rel="nofollow">https://cwiki.apache.org/SLING/url-to-script-resolution.html</a></li>
</ul>


<h1><a name="GSoC2010mini-CMSproject-"></a><font color="#003366"><b>Content loading</b></font></h1>

<p>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.</p>

<p>In David there are two different nodes created when you deploy your application: <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/content/david.json" class="external-link" rel="nofollow">/content/david</a> and <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/content/tags.json" class="external-link" rel="nofollow">/content/tags</a> .</p>

<p>These nodes are defined in the application folders, using a JSON format. Every information stored in these JSON will be a property of the created nodes.&nbsp;</p>

<p>The most important property is the next one</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-quote">"sling:resourceType"</span>: <span class="code-quote">"david"</span>
</pre>
</div></div>
<p>This property defines "david" as resource type, so Sling knows that it will search under the folder /apps/david to find the scripts that will be called on this node.</p>

<p>These JSON files are loaded using the <a href="http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html" class="external-link" rel="nofollow">Maven Bundle Plugin</a> , as you can see in the David <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/pom.xml" class="external-link" rel="nofollow">core/pom.xml</a> file&nbsp;</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">&lt;!-- initial content to be loaded on bundle installation --&gt;
&lt;Sling-Initial-Content&gt;
	initial-content;overwrite:=<span class="code-keyword">true</span>;uninstall:=<span class="code-keyword">true</span>
&lt;/Sling-Initial-Content&gt;                 
</pre>
</div></div>
<p>JSON isn't the only way to load initial content. Further informations about content loading can be found in the <a href="http://sling.apache.org/site/content-loading-jcrcontentloader.html" class="external-link" rel="nofollow">Content Loading Bundle Documentation</a>.</p>

<h1><a name="GSoC2010mini-CMSproject-"></a><font color="#003366"><b>Create new entry</b></font></h1>

<p>There is a script that provide this basic function, <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/new.esp" class="external-link" rel="nofollow">/apps/david/new.esp</a>. 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: <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/header.esp" class="external-link" rel="nofollow">/apps/david/header.esp</a> and <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/menu.esp" class="external-link" rel="nofollow">/apps/david/menu.esp</a>. These scripts, as the name suggests, contain header informations and the menu for David.&nbsp;</p>

<p>In the header there are jQuery functions and CSS definitions, useful for the whole CMS. In the menu script we can find the definition of a classic menu.</p>

<p>Turning back to the new.esp script, we can see in the following code as header and menu are loaded, using an ESP function.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">...
...
&lt;title&gt;David Mini CMS&lt;/title&gt;
&lt;%
load(<span class="code-quote">"header.esp"</span>);
%&gt;

&lt;/head&gt;
&lt;body onload=<span class="code-quote">"checkAuth()"</span>&gt;
	&lt;div id=<span class="code-quote">"lCenter"</span>&gt;
	&lt;div id=<span class="code-quote">"desktop"</span>&gt;
	&lt;%
	load(<span class="code-quote">"menu.esp"</span>);
	%&gt;
	&lt;div id=<span class="code-quote">"contentPanel"</span> class=<span class="code-quote">"centralPanel"</span>&gt;
...
...
</pre>
</div></div>
<p>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 and a CKEditor panel.&nbsp;</p>

<p>Once the user fills the input, the page is like in the following image</p>

<p><span class="image-wrap" style=""><img src="http://davidgsoc.files.wordpress.com/2010/08/new.png" style="border: 0px solid black" /></span></p>

<p>The submit button of this page is bounded to a jQuery function defined in the <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/header.esp" class="external-link" rel="nofollow">header.esp</a> file. To create a new entry we have only to create a HTTP POST request, including the informations the user put in the input texts. The function that create the new entry is the following:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">......
...
<span class="code-comment">//Function called when there is a click of the
</span><span class="code-comment">//submit button in <span class="code-keyword">new</span>.esp page
</span>$('#button').click(function() {

    <span class="code-comment">//Retrieve the input texts from the HTML
</span>    <span class="code-keyword">var</span> title = $(<span class="code-quote">"#title"</span>).val();
    <span class="code-keyword">var</span> text = $(<span class="code-quote">"#editor1"</span>).val();
    <span class="code-keyword">var</span> editor_data = CKEDITOR.instances.editor1.getData();
    text=editor_data;
    <span class="code-keyword">var</span> tagValues = $(<span class="code-quote">"#tags"</span>).val();

    <span class="code-comment">//Now create a list with tags
</span>    tagValues=tagValues.split(<span class="code-quote">","</span>);


    <span class="code-keyword">for</span>(<span class="code-keyword">var</span> i=0; i&lt;tagValues.length; i++) {
	tagValues[i] = tagValues[i].replace(/ /g,'');
    }

    <span class="code-keyword">var</span> token = <span class="code-keyword">new</span> Array();
    <span class="code-keyword">for</span>(<span class="code-keyword">var</span> i=0; i&lt;tagValues.length; i++)
		<span class="code-keyword">if</span>(tagValues[i] != "")
			token.push(tagValues[i]);

    <span class="code-comment">//Every information is stored in the <span class="code-quote">"data"</span> variable
</span>    <span class="code-comment">//sling:resourceType tells the repository that <span class="code-keyword">this</span> entry is a David one
</span>    <span class="code-comment">//jcr:mixinTypes=mix:referenceable defines <span class="code-keyword">this</span> entry as referenceable (see JCR)       
</span>    <span class="code-keyword">var</span> data=<span class="code-quote">"title="</span>+title+<span class="code-quote">"&amp;text="</span>+text+<span class="code-quote">"&amp;sling:resourceType=david&amp;jcr:mixinTypes=mix:referenceable"</span>;

    <span class="code-keyword">for</span> (<span class="code-keyword">var</span> j = 0 ; j &lt; token.length ; j++){
		data=data.concat(<span class="code-quote">"&amp;tag="</span>+token[j]);
    }

    <span class="code-comment">//The current date will be used to create the folders
</span>    <span class="code-comment">//in the Sling repository where we will put the content
</span>    <span class="code-keyword">var</span> currentDate = <span class="code-keyword">new</span> Date();
    <span class="code-keyword">var</span> year = currentDate.getYear()+1900;
    <span class="code-keyword">var</span> month = currentDate.getMonth()+1;
    <span class="code-keyword">var</span> day = currentDate.getDate()+1;

    <span class="code-keyword">if</span> (month&lt;10)
	month = <span class="code-quote">"0"</span> + month;
    <span class="code-keyword">if</span> (day&lt;10)
	day = <span class="code-quote">"0"</span> + day;


    <span class="code-comment">//The url is under the David root node /content/david
</span>    <span class="code-comment">//created during the initial content loading
</span>    <span class="code-keyword">var</span> url=<span class="code-quote">"/content/david/"</span>+year+<span class="code-quote">"/"</span>+month+<span class="code-quote">"/"</span>+day+<span class="code-quote">"/"</span>;

    <span class="code-comment">//Simple AJAX call to create a HTTP POST request
</span>    $.ajax({
	type: <span class="code-quote">"POST"</span>,
	url: url,
	data: data,
	success: function(msg){
		alert(<span class="code-quote">"Entry saved"</span>);
		window.location = <span class="code-quote">"/content/david.html"</span>;
	},
	error: function(msg){
		alert(<span class="code-quote">"Error during save"</span>);
	}
    });
});
...
...
...
</pre>
</div></div>
<p>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 <font color="#3366ff"><b><em>/content/david/YEAR/MONTH/DAY/somethingliketitle</em></b></font><em>.</em></p>

<p>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?</p>

<p>The request URL we created is where we would like to insert our entry. If this URL already exist, we will only update properties of this node (and so you can already understand that the edit page will be equal to this one).</p>

<p>If the resource doesn't exist, a new item is created. If the resource name ends with /&#42; 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 <a href="http://svn.apache.org/repos/asf/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java" class="external-link" rel="nofollow">SlingPostServlet</a> , a frontend for the content manipulation. This servlet provides also other content operations, as described <a href="http://sling.apache.org/site/manipulating-content-the-slingpostservlet-servletspost.html" class="external-link" rel="nofollow">here</a>.</p>

<h1><a name="GSoC2010mini-CMSproject-Authentication"></a>Authentication</h1>

<p>You can submit new entry only if you have already authenticated with Sling. So you can see that on the <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/menu.esp" class="external-link" rel="nofollow">/apps/david/menu.esp</a> script there is a check for the credentials</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">......
...
&lt;td width=<span class="code-quote">"33%"</span> align=<span class="code-quote">"right"</span>&gt;
	Logged as: &lt;b id=<span class="code-quote">"username"</span>&gt;????&lt;/b&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;script language=<span class="code-quote">"javascript"</span>&gt;
	<span class="code-keyword">var</span> info = Sling.getSessionInfo();
	<span class="code-keyword">if</span> (info.userID==<span class="code-quote">"anonymous"</span>)
		document.getElementById(<span class="code-quote">"username"</span>).innerHTML = 
			info.userID+<span class="code-quote">"&lt;a href='/system/sling/form/login?resource=/content/david.html'&gt;Login&lt;/a&gt;"</span>;
	<span class="code-keyword">else</span>
		document.getElementById(<span class="code-quote">"username"</span>).innerHTML = info.userID;
&lt;/script&gt;
...
...
</pre>
</div></div>
<p>Let's now explain this code. Using the <a href="http://svn.apache.org/repos/asf/sling/trunk/bundles/servlets/post/src/main/resources/system/sling.js" class="external-link" rel="nofollow">sling.js</a>, system utility defined in Sling, we can get the session information object. If the userid of this object is <font color="#3366ff"><b><em>anonymous</em></b></font>&nbsp;we put a link to the authentication form.</p>

<p>Otherwise we simply print the userid.</p>

<p>The authentication form receives a <font color="#3366ff"><b><em>resource</em></b></font>&nbsp;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 <a href="http://sling.apache.org/site/authentication.html" class="external-link" rel="nofollow">the authentication documentation on Sling website</a>.</p>

<h1><a name="GSoC2010mini-CMSproject-Editexistingentry"></a>Edit existing entry</h1>

<p>As said before, the update operation is really similar to the creation of new content. Anyway in David there a separated script to handle this operation, <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/edit.esp" class="external-link" rel="nofollow">/apps/david/edit.esp</a>.&nbsp;</p>

<p>It's an unuseful script, because also this operation can call <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/new.esp" class="external-link" rel="nofollow">new.esp</a>. There is a need of a bit refactory about it.</p>

<h1><a name="GSoC2010mini-CMSproject-Listexistingentries"></a>List existing entries</h1>

<p>Once you saved some entries in David, you can see a complete list of articles using the script <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/list.esp" class="external-link" rel="nofollow">/apps/david/list.esp</a>.</p>

<p>Firstly there is a JCR query to find all the items</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">var</span> queryManager = currentNode.getSession().getWorkspace().getQueryManager();  
<span class="code-keyword">var</span> query = queryManager.createQuery(<span class="code-quote">"/jcr:root/content/david/*/*/*/element(*, nt:unstructured) order by @created descending"</span>, <span class="code-quote">"xpath"</span>);
<span class="code-keyword">var</span> result = query.execute().getNodes();
</pre>
</div></div>
<p>In this way we have a variable <em>result</em> with a <a href="http://www.day.com/maven/javax.jcr/javadocs/jcr-2.0/javax/jcr/NodeIterator.html" class="external-link" rel="nofollow">NodeIterator</a>&nbsp;object. So we simply have to make a loop on this iterator and print its values</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">&lt;h3&gt;Entries&lt;/h3&gt;
&lt;div&gt;
	&lt;h3&gt;&lt;a href='/content/david.pdf'&gt;Export list&lt;/a&gt;&lt;/h3&gt;
	&lt;%
	<span class="code-keyword">while</span>(result.hasNext()) {
		post = result.nextNode()
	%&gt;

	&lt;h3&gt; &lt;a href=<span class="code-quote">"&lt;%= post.getPath() %&gt;.article"</span>&gt;&lt;%=post.title%&gt;&lt;/a&gt; -
	&lt;a href=<span class="code-quote">"&lt;%= post.getPath() %&gt;.edit"</span>&gt;EDIT&lt;/a&gt; -
	&lt;a id=<span class="code-quote">"&lt;%= post.getPath() %&gt;"</span> class=<span class="code-quote">"delete"</span> href=<span class="code-quote">"#"</span>&gt;DELETE&lt;/a&gt; -
	&lt;a href=<span class="code-quote">"&lt;%= post.getPath() %&gt;.pdf"</span>&gt;&lt;img alt=<span class="code-quote">"Get pdf"</span> src=<span class="code-quote">"/libs/images/pdf-icon.png"</span>&gt;&lt;/a&gt;
	&lt;/h3&gt;

	&lt;%
	}
	%&gt;

&lt;/div&gt;
</pre>
</div></div>
<p>The result is something like the following image</p>

<p><span class="image-wrap" style=""><img src="http://davidgsoc.files.wordpress.com/2010/08/list.png" style="border: 0px solid black" /></span></p>

<p>When you click on the article, you call the <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/article.esp" class="external-link" rel="nofollow">/apps/david/article.esp</a> script, that is a simple script where the contents of article are rendered. For the others links, read the following paragraphs.</p>

<h1><a name="GSoC2010mini-CMSproject-Deleteexistingentry"></a>Delete existing entry</h1>

<p>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 <font color="#3366ff"><b><em>:operation=delete</em></b></font>.</p>

<p>This request is made with a jQuery function bounded to the DELETE link, as you can see in the <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/list.esp" class="external-link" rel="nofollow">/apps/david/list.esp</a> script</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">$.ajax({$.ajax({
	type: <span class="code-quote">"POST"</span>,
   	url: id,
   	data: <span class="code-quote">":operation=delete"</span>,
   	success: function(msg){
        	$(<span class="code-keyword">this</span>).dialog('close');
        	location.reload();
   	},
        error: function(msg){
        	alert(msg);
                $(<span class="code-keyword">this</span>).dialog('close');
        }
});
</pre>
</div></div>


<h1><a name="GSoC2010mini-CMSproject-Generatethetagscontentstructure"></a>Generate the tags content structure</h1>

<p>David manages a simple tagging system for the articles.&nbsp;The tags related to the article, that user insert in the <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/new.esp" class="external-link" rel="nofollow">new.esp</a> page, are saved as a multi-value property on the article node.</p>

<p>In addition to this, there is also a redundant structure to achieve the tags information, as shown in the next image</p>


<p><span class="image-wrap" style=""><img src="http://davidgsoc.files.wordpress.com/2010/07/tag-jcr-structure.png" style="border: 0px solid black" /></span></p>


<p>So David must manage tags in the creation of the article and in its removal. To accomplish these tasks I used a two different approach.</p>

<p>For the creation of the article there is a component deployed in Apache Sling. This component listens for the creation of a new Node and manage the add of tag values.</p>

<p>This service is implemented in the class&nbsp;<a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/jcr/TagGenerator.java" class="external-link" rel="nofollow">sling.gsoc.david.jcr.TagGenerator</a>. This class is a OSGi component, with annotations that define it as a component (see <a href="http://felix.apache.org/site/apache-felix-maven-scr-plugin.html" class="external-link" rel="nofollow">Maven SCR Plugin</a> for more details)</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">@Component(metatype = <span class="code-keyword">false</span>, immediate = <span class="code-keyword">true</span>)
</pre>
</div></div>
<p>Using the annotations we have also the reference to <a href="http://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/SlingRepository.java" class="external-link" rel="nofollow">SlingRepository</a>, that will be used to gain access to Sling repository</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">@Reference@Reference
<span class="code-keyword">private</span> SlingRepository repository;
<span class="code-keyword">private</span> SlingRepository repository;<span class="code-keyword">private</span> SlingRepository repository;
</pre>
</div></div>

<p>Being an OSGi Component there is the implementation of&nbsp;<font color="#0000ff"><b><em>activate</em></b></font> and <font color="#0000ff"><b><em>deactivate</em></b></font> methods, which is called when the component is activated/deactivated.</p>

<p><a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/jcr/TagGenerator.java" class="external-link" rel="nofollow">TagGenerator </a> class implements <a href="http://www.day.com/maven/javax.jcr/javadocs/jcr-2.0/javax/jcr/observation/EventListener.html" class="external-link" rel="nofollow">EventListener </a> interface, so in the <font color="#0000ff"><b><em>onEvent</em></b></font> method we add the tags of the created node to the tagging structure.</p>

<p>When we delete a node, we can see that there is another AJAX call in the <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/list.esp" class="external-link" rel="nofollow">/apps/david/list.esp</a> script before the real removal. There is a call which uses the&nbsp;<font color="#0000ff"><b><em>:operation=deletetag</em></b></font> parameter.</p>

<p>This operation is implemented by David, using the&nbsp;<a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/operation/DeleteTagOperation.java" class="external-link" rel="nofollow">sling.gsoc.david.operation.DeleteTagOperation</a> class. In Sling you can define new operations extending <a href="http://svn.apache.org/repos/asf/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostOperation.java" class="external-link" rel="nofollow">SlingPostOperation</a>. The new operation is defined with the constant&nbsp;<font color="#0000ff"><b><em>sling.post.operation&nbsp;</em></b></font><font color="#000000">as we can see in the next code</font></p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">@Property(value = <span class="code-quote">"deletetag"</span>)
<span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> OPERATION = <span class="code-quote">"sling.post.operation"</span>;
</pre>
</div></div>
<p>When we deploy David, the new operation is registered and every request with this new operation will be managed by our class. When this operation is called, <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/operation/DeleteTagOperation.java" class="external-link" rel="nofollow">DeleteTagOperation</a>&nbsp;select the nodes related to the article tags and remove the UUID of the article from this list. Every operation, the add and the removal, based on the JCR repository must end with a call to the save method of the root node where we added/removed nodes.</p>

<h1><a name="GSoC2010mini-CMSproject-DisplaytagsusingtheFlashbasedanimation"></a>Display tags using the Flash-based animation</h1>

<p>The homepage of this CMS is related to the <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/html.esp" class="external-link" rel="nofollow">/apps/david/html.esp</a> script. From the script side, there is only the inclusion of WP-Cumulus, a flash based tag cloud. This engine requires an XML with tags informations and, as you can see in the script, it points to the next url:&nbsp;</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">so.addVariable(<span class="code-quote">"xmlpath"</span>, <span class="code-quote">"/content/tag.cloud"</span>);
</pre>
</div></div>
<p>To create this XML there is another registered component, which manages the <font color="#0000ff"><b><em>cloud</em></b></font> resource type. This component is <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/servlet/CloudExtension.java" class="external-link" rel="nofollow">sling.gsoc.david.servlet.CloudExtension</a> , which extends <a href="http://svn.apache.org/repos/asf/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/SlingAllMethodsServlet.java" class="external-link" rel="nofollow">SlingAllMethodsServlet </a> to manage this new resource type. In the following code of this component you can see how it is used the <a href="http://felix.apache.org/site/apache-felix-maven-scr-plugin.html#ApacheFelixMavenSCRPlugin-Property" class="external-link" rel="nofollow">@Property</a> annotation to configure it</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">...
...
@Component(metatype = <span class="code-keyword">false</span>, immediate = <span class="code-keyword">true</span>)
@Service(value = javax.servlet.Servlet.class)
<span class="code-keyword">public</span> class CloudExtension <span class="code-keyword">extends</span> SlingAllMethodsServlet {

    @Property(value = <span class="code-quote">"PDF Extension Servlet"</span>)
    <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> DESCRIPTION = <span class="code-quote">"service.description"</span>;
    @Property(value = <span class="code-quote">"David Mini CMS"</span>)
    <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> VENDOR = <span class="code-quote">"service.vendor"</span>;
    @Property(value = <span class="code-quote">"sling/servlet/<span class="code-keyword">default</span>"</span>)
    <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> RESOURCE_TYPES = <span class="code-quote">"sling.servlet.resourceTypes"</span>;
    @Property(value = <span class="code-quote">"cloud"</span>)
    <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> EXTENSIONS = <span class="code-quote">"sling.servlet.extensions"</span>;
...
...
</pre>
</div></div>
<p>This component scans the tag structure and creates the XML. The final result is showed in the next image</p>

<p><span class="image-wrap" style=""><img src="http://davidgsoc.files.wordpress.com/2010/08/tag.png" style="border: 0px solid black" /></span></p>

<h1><a name="GSoC2010mini-CMSproject-Listentriesbytags"></a>List entries by tags</h1>

<p>When you click on one tag of the previous flash tag cloud, you will land on the page created by <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/taglist.esp" class="external-link" rel="nofollow">/apps/david/taglist.esp</a> script. There using the relationship that there is between a tag and the UUID list of the articles, we have only to execute this simple search to print all the articles with the tag passed as parameter</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">&lt;h3&gt;Entries&lt;/h3&gt;&lt;h3&gt;Entries&lt;/h3&gt;
	&lt;div&gt;
        &lt;%
        <span class="code-keyword">var</span> uuids=tagNode.getProperty(<span class="code-quote">"UUIDs"</span>).getValues();
        <span class="code-keyword">for</span>(<span class="code-keyword">var</span> i =0; i&lt;uuids.length; i++) {
        	<span class="code-keyword">var</span> uuid=uuids[i];
                <span class="code-keyword">var</span> nodeR=session.getNodeByUUID(uuid.getString());
        %&gt;

        	&lt;a href='&lt;%=nodeR.getPath() %&gt;.article'&gt;&lt;%=nodeR.title%&gt;&lt;/a&gt;&lt;br&gt;

        &lt;%
        }

        %&gt;
</pre>
</div></div>
<p>You can see in this script as ESP language can be used to manage object related to JCR. Using the method getNodeByUUID of <a href="http://www.day.com/maven/jsr170/javadocs/jcr-2.0/javax/jcr/Session.html" class="external-link" rel="nofollow">Session</a>&nbsp;we have the node related to a particular UUID, so we can print it in the list.</p>


<h1><a name="GSoC2010mini-CMSproject-Searchforentries"></a>Search for entries</h1>

<p>Also the search is based on ESP script, <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/search.esp" class="external-link" rel="nofollow">/apps/david/search.esp</a> . 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</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">var</span> query = queryManager.createQuery(
	<span class="code-quote">"/jcr:root/content/david/*/*/*/element(*, nt:unstructured)[jcr:like(@title, '%"</span>+request.getParameter(<span class="code-quote">"qtitle"</span>)+"%')] 
	order by @created descending<span class="code-quote">", "</span>xpath");
</pre>
</div></div>
<p>This query searches the entry with title LIKE (as in SQL) the parameter submitted.</p>

<p>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</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">var</span> searchString =  
<span class="code-quote">"/jcr:root/content/tags<span class="code-comment">//element(*,nt:unstructured)[fn:name()= '"</span>+request.getParameter(<span class="code-quote">"qtag"</span>)+<span class="code-quote">"'] order by @created descending"</span>;</span>
</pre>
</div></div>
<p>The initial form to perform the search is a simple HTML one, as you can see in the following image</p>


<p><span class="image-wrap" style=""><img src="http://davidgsoc.files.wordpress.com/2010/08/search.png" style="border: 0px solid black" /></span></p>


<h1><a name="GSoC2010mini-CMSproject-CreatePDFrenditions"></a>Create PDF renditions</h1>

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

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

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">http:<span class="code-comment">//localhost:8080/content/david/2010/08/14/myarticle.pdf</span>
</pre>
</div></div>
<p>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 <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/servlet/PdfExtension.java" class="external-link" rel="nofollow">sling.gsoc.david.servlet.PdfExtension</a>. In this component there is the rendering of the node using <a href="http://itextpdf.com/" class="external-link" rel="nofollow">iText library</a>&nbsp;and the node, for which this component can be activated, can be a standard article or the root node.&nbsp;</p>

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


<p><span class="image-wrap" style=""><img src="http://davidgsoc.files.wordpress.com/2010/08/pdf.png" style="border: 0px solid black" /></span></p>

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

<p><span class="image-wrap" style=""><img src="http://davidgsoc.files.wordpress.com/2010/08/pdflist.png" style="border: 0px solid black" /></span></p>


<h1><a name="GSoC2010mini-CMSproject-Schedulerservice"></a>Scheduler service</h1>

<p>Every Sling application can use the opensource scheduler <a href="http://www.quartz-scheduler.org/" class="external-link" rel="nofollow">Quartz</a>, provided by the <a href="http://sling.apache.org/site/scheduler-service-commons-scheduler.html" class="external-link" rel="nofollow">Commons Scheduler bundle</a>&nbsp;(this requires also another bundle,&nbsp;<a href="http://svn.apache.org/repos/asf/sling/trunk/bundles/commons/threads/" class="external-link" rel="nofollow">org.apache.sling.commons.threads</a>).</p>

<p>Based on this scheduler there is a simple service, implemented by <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/job/JobScheduler.java" class="external-link" rel="nofollow">sling.gsoc.job.JobScheduler</a> and <a href="http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/java/sling/gsoc/david/job/SendTask.java" class="external-link" rel="nofollow">sling.gsoc.job.SendTask</a>. 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.&nbsp;</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/SLING/GSoC+2010+mini-CMS+project">View Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=20316370&revisedVersion=31&originalVersion=30">View Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/SLING/GSoC+2010+mini-CMS+project?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message