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 > Default Mapping and Rendering
Date Thu, 04 Feb 2010 10:51:00 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1519/1/1/_/styles/combined.css?spaceKey=SLING&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="http://cwiki.apache.org/confluence/display/SLING/Default+Mapping+and+Rendering">Default
Mapping and Rendering</a></h2>
    <h4>Page  <b>added</b> by             <a href="http://cwiki.apache.org/confluence/display/~bdelacretaz">Bertrand
Delacretaz</a>
    </h4>
         <br/>
    <div class="notificationGreySide">
         <div class='panelMacro'><table class='noteMacro'><colgroup><col
width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/warning.gif"
width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Page
Status</b><br /><p>This is obsolete content copied from the Sling website
on 2010-02-04.</p></td></tr></table></div>
<h1><a name="DefaultMappingandRendering-DefaultContentMappingandRequestRendering"></a>Default
Content Mapping and Request Rendering</h1>



<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/warning.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td><b>Page Status</b><br
/><p>2008-02-13: this page is <b>out of sync</b> with the current codebase,
needs to be reviewed and updated.</p></td></tr></table></div>


<p>One of the big obstacles in quick adoption of Sling might arguably be the requirement
for multiple developments, such as...</p>

<ol>
	<li>Creating a <tt>Content</tt> implementation (or decide on reusing an
existing implementation)</li>
	<li>Defining the mapping descriptor to map the repository contents to the <tt>Content</tt>
object and vice versa</li>
	<li>Optionally create a node type defintion file in <em>CND</em> format</li>
	<li>Creating a <tt>Component</tt> implementation (or decide on reusing
an existing implementation)</li>
	<li>Package this all up into an OSGi Bundle for deployment</li>
</ol>


<p>While these steps make sense in an ideal world we all know does not exist (with the
exception of Utopia, but there are no computers in Utopia), helpers for rapid development
are needed. These helpers come in the form of usefull defaults on various levels.</p>



<h2><a name="DefaultMappingandRendering-DefaultContentMapping"></a>Default
Content Mapping</h2>

<p>When a request is processed by Sling, one step is to resolve the request URL into
a <tt>Content</tt> object. This works by checking the request URL for the longest
match with an existing JCR repository node. The path of this node is then used to load the
<tt>Content</tt> object through the <tt>ContentManager.load(String)</tt>
method. If no mapping exists for the given node, an exception is thrown and the request fails.</p>

<p>In such a case of missing content mapping, a default <tt>Content</tt>
mapping is defined in the form of the <tt>org.apache.sling.content.jcr.DefaultContent</tt>
class. This mapping has the following features:</p>

<ul>
	<li>The <tt>DefaultContent</tt> class is a <tt>java.util.Map</tt>.
Thus all properties may be accessed using the familiar <tt>Map</tt> API.</li>
	<li>All non-protected properties of the node are loaded. Single value properties become
scalar objects, while multi value properties become <tt>java.util.List</tt> objects.</li>
	<li>The types of the repository values are mapped according to the JCR specification
for mapping between Property types and Java types.</li>
	<li>A few properties have special significance. See below.</li>
	<li>Creating new instances of this class and inserting these into the repository creates
nodes of type <tt>nt:unstructured</tt>. When loading instances of this class the
actual primary type of the node does not matter.</li>
</ul>



<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Property </th>
<th class='confluenceTh'> Type </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>path</tt> </td>
<td class='confluenceTd'> String </td>
<td class='confluenceTd'> The path of the node from which the content was loaded. This
must not be modified by application programs, unless you are prepared for unexpected behaviour
when storing the object. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>primaryType</tt> </td>
<td class='confluenceTd'> String </td>
<td class='confluenceTd'> The primary node type of the (existing) node. This property
is purely informational and will never be used when inserting new content or writing back
content. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>mixinTypes</tt> </td>
<td class='confluenceTd'> List of String </td>
<td class='confluenceTd'> The mixin node types of the (existing) node. This property
is purely informational and will never be used when inserting new content or writing back
content. If the node has no mixin node types, this property does not exist. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>sling:componentId</tt> </td>
<td class='confluenceTd'> String </td>
<td class='confluenceTd'> The component ID of the component used to handle requests
to this content. This property may be modified by application programs (though you should
be aware of the consequences) and is used as the result of the <tt>Content.getComponentId()</tt>
method. </td>
</tr>
</tbody></table>



<h2><a name="DefaultMappingandRendering-DefaultComponentSelection"></a>Default
Component Selection</h2>

<p>After having mapped the JCR repository node into the <tt>Content</tt>
object the <tt>Component</tt> to actually handle the request must be resolved.
This is done by calling the <tt>Content.getComponentId()</tt> method and looking
up this component ID in an internal table. If either the <tt>Content.getComponentId()</tt>
method returns <tt>null</tt> or no component is registered with the requested
component ID a default resolution processing takes place as follows:</p>

<ol>
	<li>Let <tt>cid</tt> be the result of calling <tt>Content.getComponentId()</tt></li>
	<li>If <tt>cid</tt> is <tt>null</tt>, let <tt>cid</tt>
be the result of calling <tt>Content.getPath()</tt> (this is never <tt>null</tt>}</li>
	<li>Check for a component with the given <tt>cid</tt> and use it if existing</li>
	<li>Otherwise, remove any leading slash from <tt>cid</tt> and replace slashes
by dots and check for a component with this modified <tt>cid</tt> and use it if
existing</li>
	<li>Otherwise, let <tt>cid</tt> be the fully qualified name of the <tt>Content</tt>
object class and check for a component with this modified <tt>cid</tt> and use
it if existing</li>
	<li>Otherwise and if <tt>cid</tt> ends with the string <em>Content</em>,
remove that suffix and check for a component with this modified <tt>cid</tt> and
use it if existing</li>
	<li>Otherwise, append <tt>Component</tt> to the end of <tt>cid</tt>
and and check for a component with this modified <tt>cid</tt> and use it if existing</li>
	<li>Otherwise, let <tt>cid</tt> be the value of the <tt>org.apache.sling.components.DefaultComponent.ID</tt>
field and check for a component with this modified <tt>cid</tt> and use it if
existing</li>
	<li>Finally, fail without having found a component to use - this is highly unlikely,
though, because the default component is part of the Sling Core bundle and should always be
available.</li>
</ol>



<h3><a name="DefaultMappingandRendering-DefaultComponent"></a>DefaultComponent</h3>

<p>The default component first checks whether the request is sent with parameters and
will update the <tt>Content</tt> object with the parameters as follows:</p>

<ul>
	<li>If the <tt>Content</tt> object is a <tt>java.util.Map</tt>
(such as is the case for the <tt>DefaultContent</tt>) the properties will directly
accessed through the <tt>Map</tt>} API. Otherwise, the <tt>Content</tt>
object is wrapped inside a <tt>org.apache.commons.collections.BeanMap</tt> to
access the fields through the <tt>Map</tt> API.</li>
	<li>Any properties listed in the <tt>&#95;delete</tt> parameter are
removed. The <tt>&#95;delete</tt> parameter may contain a comma-separated
list of property names and may occurr multiple times.</li>
	<li>All other parameters are used to set property values, where any existing properties
will be replaced and all properties not listed in the parameters remain unmodified. If a parameter
occurrs only once a single value property is set, if  parameter occurrs multiple times, a
multi value property is set as a list of strings. Note, that any data type conversion may
happen only by the <tt>BeanMap</tt> as required and thus lead to failure to update
a single proeperty.</li>
</ul>


<p>After the optional update phase, the fields of the <tt>Content</tt> object
are written back. Again, the <tt>Content</tt> object is either accessed as a <tt>Map</tt>
directly if it is a <tt>Map</tt> or packed in a <tt>BeanMap</tt> otherwise.
The format of the output is deduced from the request URL's extension as returned by the <tt>ComponentRequest.getExtension()</tt>
method:</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Extension </th>
<th class='confluenceTh'> Format </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>html</tt>, <tt>htm</tt> </td>
<td class='confluenceTd'> HTML, UTF-8 encoded </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>xml</tt> </td>
<td class='confluenceTd'> XML, UTF-8 encoded </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>txt</tt> </td>
<td class='confluenceTd'> Plain text, UTF-8 encoded </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>properties</tt> </td>
<td class='confluenceTd'> Java Properties file format suitable for a normal properties
file </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>json</tt> </td>
<td class='confluenceTd'> JSON, UTF-8 encoded  </td>
</tr>
</tbody></table>


<h3><a name="DefaultMappingandRendering-DefaultScript"></a>Default Script</h3>

<p>The easiest way to develop and deploy a component is to create a scripted component
in the repository by just creating a node of type <tt>sling:scriptedComponent</tt>
and creating a single JSP script at <tt>jsp/start.jsp</tt> below the component
node. After that you can refer to that component by the path of the component node and get
the <tt>start.jsp</tt> script called.</p>

<p>For more more elaborate script selection you may of course create more scripts and
refer to them below the <tt>sling:scripts</tt> node of the component node.</p>


<h2><a name="DefaultMappingandRendering-RapidDevelopmentPrimer"></a>Rapid
Development Primer</h2>

<p>To summarize, for rapid development you will have to execute the following steps:</p>

<ol>
	<li>Create a <tt>sling:ScriptedComponent</tt> node, for example at <tt>/some/sample/component</tt></li>
	<li>Create a JSP script file at <tt>jsp/start.jsp</tt> below that node;
that would be <tt>/some/sample/component/jsp/start.jsp</tt> in the example</li>
	<li>Create one or more nodes of any type, for example <tt>nt:unstructured</tt>,
which have a single value string property named <tt>sling:componentId</tt> referring
to the component via its path</li>
	<li>Request the node by typing its path in your browser's address field</li>
</ol>

    </div>
    <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href="http://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
       </div>
       <a href="http://cwiki.apache.org/confluence/display/SLING/Default+Mapping+and+Rendering">View
Online</a>
              |
       <a href="http://cwiki.apache.org/confluence/display/SLING/Default+Mapping+and+Rendering?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
           </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message