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 Tue, 10 Aug 2010 10:18: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 (2)</h4>
                                 
    
<div id="page-diffs">
            <table class="diff" cellpadding="0" cellspacing="0">
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h1.
<br> <br> <br>h1. <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" > <br>!http://davidgsoc.files.wordpress.com/2010/08/new.png!
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
<br>The submit button of this page is bounded to a jQuery function defined in the [header.esp|http://code.google.com/p/davidgsoc2010/source/browse/trunk/core/src/main/resources/initial-content/apps/david/header.esp]
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:
<br> <br>{code} <br>...... <br>... <br>//Function called when
there is a click of the <br>//submit button in new.esp page <br>$(&#39;#button&#39;).click(function()
{ <br> <br>    //Retrieve the input texts from the HTML <br>    var title
= $(&quot;#title&quot;).val(); <br>    var text = $(&quot;#editor1&quot;).val();
<br>    var editor_data = CKEDITOR.instances.editor1.getData(); <br>    text=editor_data;
<br>    var tagValues = $(&quot;#tags&quot;).val(); <br> <br>  
 //Now create a list with tags <br>    tagValues=tagValues.split(&quot;,&quot;);
<br> <br> <br>    for(var i=0; i&lt;tagValues.length; i++) { <br>
tagValues[i] = tagValues[i].replace(/ /g,&#39;&#39;); <br>    } <br> <br>
   var token = new Array(); <br>    for(var i=0; i&lt;tagValues.length; i++) <br>
	if(tagValues[i] != &quot;&quot;) <br>			token.push(tagValues[i]); <br>
<br>    //Every information is stored in the &quot;data&quot; variable <br>
   var data=&quot;title=&quot;+title+&quot;&amp;text=&quot;+text+&quot;&amp;sling:resourceType=david&amp;jcr:mixinTypes=mix:referenceable&quot;;
<br> <br>    for (var j = 0 ; j &lt; token.length ; j++){ <br>		data=data.concat(&quot;&amp;tag=&quot;+token[j]);
<br>    } <br> <br>    //The current date will be used to create the folders
<br>    //in the Sling repository where we will put the content <br>    var currentDate
= new Date(); <br>    var year = currentDate.getYear()+1900; <br>    var month
= currentDate.getMonth()+1; <br>    var day = currentDate.getDate()+1; <br> <br>
   if (month&lt;10) <br>	month = &quot;0&quot; + month; <br>    if
(day&lt;10) <br>	day = &quot;0&quot; + day; <br> <br> <br>
   //The url is under the David root node /content/david <br>    //created during the
initial content loading <br>    var url=&quot;/content/david/&quot;+year+&quot;/&quot;+month+&quot;/&quot;+day+&quot;/&quot;;
<br> <br>    //Simple AJAX call to create a HTTP POST request <br>    $.ajax({
<br>	type: &quot;POST&quot;, <br>	url: url, <br>	data: data, <br>
success: function(msg){ <br>		alert(&quot;Entry saved&quot;); <br>		window.location
= &quot;/content/david.html&quot;; <br>	}, <br>	error: function(msg){
<br>		alert(&quot;Error during save&quot;); <br>	} <br>    }); <br>});
<br>... <br>... <br>... <br>{code} <br>LOL <br></td></tr>
        </table>
</div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h1><a name="GSoC2010mini-CMSproject-"></a></h1>


<h1><a name="GSoC2010mini-CMSproject-"></a></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-"></a><font color="#003366"><b>Introduction</b></font></h1>

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

<p>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-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>LOL</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=14&originalVersion=13">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