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 > Supporting CRUD
Date Wed, 25 Jul 2012 16:09:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/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/Supporting+CRUD">Supporting
CRUD</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~cziegeler@apache.org">Carsten
Ziegeler</a>
    </h4>
        <br/>
                         <h4>Changes (7)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h3. Delete <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">We
add a _delete_ method to the *Resource* interface, so deleting a resource is a two way step:
first getting the resource from the resource resolver and then deleting it.  <br>There
is no benefit in having a _delete(String path)_ method on the resource resolver. This would
internally get the resource first anyway in order to delegate to the proper resource provider.
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">There
are basically two options for a delete: <br>* add a _delete_ method to the *Resource*
interface <br>* add a _delete(Resource)_ method to the *ResourceResolver* interface
<br> <br>While the first option seems to be more logical, it has the disadvantage
that we have to enhance the *Resource* interface. Therefore I opt for the second option. <br></td></tr>
            <tr><td class="diff-unchanged" >See section about persisting changes
belowe. <br> <br>h3. Create <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >We add a new method <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">_create(String
absolutePath,</span> <span class="diff-added-words"style="background-color: #dfd;">_addChild(Resource
parent, String name,</span> ValueMap properties)_ to the resource resolver, where the
value map is optional. This will create the resource at the given <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">path</span>
<span class="diff-added-words"style="background-color: #dfd;">parent with the given
name</span> and add the provided properties. <br></td></tr>
            <tr><td class="diff-changed-lines" >In the case of a JCR backed repository,
the properties might contain _jcr:primaryType_ and _jcr:mixins_ - which are used to set the
node <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">node</span>
<span class="diff-added-words"style="background-color: #dfd;">type</span> and
mixins. Otherwise the defaults apply. <br></td></tr>
            <tr><td class="diff-unchanged" >See section about persisting changes
belowe. <br> <br>h3. Update <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >We currently have the PersistableValueMap
which is an easy way of modifying a resource. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">As
we have modifications now as a first class feature, we should add an _update(ValueMap props)_
method to the *Resource* interface.</span> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
<br>Like with delete, we have different options: <br>* add an _update(ValueMap)_
method on the *Resource* interface <br>* provide a new _ModifiableValueMap_ interface
<br> <br>The first option would require a new method on the *Resource* interface
and has usability options, like how to get a changeable value map, how to ensure that a value
map get from resource A might not be used to update resource B etc. <br>A new _ModifiableValueMap_
is the easier approach. As the operations on a map usually do not throw exceptions, the modifiable
map will store the changes locally and get an _update_ method which pushes the changes into
the resource provider. <br></td></tr>
            <tr><td class="diff-unchanged" >See section about persisting changes
belowe. <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>The second approach is
more like people are used to when they are familiar with JCR and it allows to do bulk changes
to the persistence. The first approach without using a transaction is easier to implement
inside the resource providers and for many use cases sufficient as usually just a single resource
is affected by REST calls. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">For
now, we don&#39;t have any transaction support, so if a save call goes to several resource
providers, the first provider saves but the second fails, then the changes can&#39;t be
rolled back from the first provider. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-unchanged" >h2. Resource Providers <br>
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p>The current Sling resource API only allows reading of resources - with the
PersistableValueMap we have a simple mechanism to support updates, however this approach comes
with some problems (see below).</p>

<p>This is a concept how to fully implement CRUD via the resource API. As a first step
we angle the problem from the users via: the API to be used by Sling applications. (SLING-2530)</p>

<h2><a name="SupportingCRUD-ClientAPI"></a>Client API</h2>

<h3><a name="SupportingCRUD-Read"></a>Read</h3>

<p>The support for read is sufficient, we don't need to change that much.</p>

<h3><a name="SupportingCRUD-Delete"></a>Delete</h3>

<p>There are basically two options for a delete:</p>
<ul>
	<li>add a <em>delete</em> method to the <b>Resource</b> interface</li>
	<li>add a <em>delete(Resource)</em> method to the <b>ResourceResolver</b>
interface</li>
</ul>


<p>While the first option seems to be more logical, it has the disadvantage that we
have to enhance the <b>Resource</b> interface. Therefore I opt for the second
option.<br/>
See section about persisting changes belowe.</p>

<h3><a name="SupportingCRUD-Create"></a>Create</h3>

<p>We add a new method <em>addChild(Resource parent, String name, ValueMap properties)</em>
to the resource resolver, where the value map is optional. This will create the resource at
the given parent with the given name and add the provided properties.<br/>
In the case of a JCR backed repository, the properties might contain <em>jcr:primaryType</em>
and <em>jcr:mixins</em> - which are used to set the node type and mixins. Otherwise
the defaults apply.<br/>
See section about persisting changes belowe.</p>

<h3><a name="SupportingCRUD-Update"></a>Update</h3>

<p>We currently have the PersistableValueMap which is an easy way of modifying a resource.
</p>

<p>Like with delete, we have different options:</p>
<ul>
	<li>add an <em>update(ValueMap)</em> method on the <b>Resource</b>
interface</li>
	<li>provide a new <em>ModifiableValueMap</em> interface</li>
</ul>


<p>The first option would require a new method on the <b>Resource</b> interface
and has usability options, like how to get a changeable value map, how to ensure that a value
map get from resource A might not be used to update resource B etc.<br/>
A new <em>ModifiableValueMap</em> is the easier approach. As the operations on
a map usually do not throw exceptions, the modifiable map will store the changes locally and
get an <em>update</em> method which pushes the changes into the resource provider.<br/>
See section about persisting changes belowe.</p>

<p>We should deprecate the <em>PersistableValueMap</em> as a <em>save()</em>
call saves the whole session and this might include changes made through any other means to
the session.(see SLING-1391 for some discussion about this)</p>

<h3><a name="SupportingCRUD-PersistingChanges"></a>Persisting Changes</h3>

<p>There are two possibilities to handle changes:</p>

<ol>
	<li>A call to one of the methods, modifying a resource as outlined above are persisted
immediately and <b>JTA</b> transactions will be supported</li>
	<li>Changes are not persisted immediately but stored transient. When all changes are
done, a <em>save</em>/<em>commit</em> calls needs to be done trying
to persist all changes to all resource providers.</li>
</ol>


<p>The second approach is more like people are used to when they are familiar with JCR
and it allows to do bulk changes to the persistence. The first approach without using a transaction
is easier to implement inside the resource providers and for many use cases sufficient as
usually just a single resource is affected by REST calls.<br/>
For now, we don't have any transaction support, so if a save call goes to several resource
providers, the first provider saves but the second fails, then the changes can't be rolled
back from the first provider.</p>

<h2><a name="SupportingCRUD-ResourceProviders"></a>Resource Providers</h2>

<p>A resource provider is mounted into the resource tree. In general, the providers
are processed ordered by service ranking, highest first. A service provider gets a service
property specifying the sub tree it is claiming to use. For example, a service provider might
be mounted at /a/some/path. Everything below this path is processed by this resource resolver.
However another resource provider might claim /a/some/path/and/down. So the longest matching
path wins.</p>

<p>We need to add a new interface which can be implemented by a <em>ResourceProvider</em>.
It gets a create method. Update and delete are directly handled by the resource.</p>

<h3><a name="SupportingCRUD-AccessControl"></a>Access Control</h3>

<p>It's the task of a resource resolver to check if the current user is able/allowed
to access a resource. If this is not possible, the corresponding action is denied.<br/>
As resource providers are mounted at a path (see above), the resource resolver delegates to
a resource provider for a given path. If the user is not allowed to perform the action, the
processing is stopped. There is no fallback to another resource provider. This avoids the
problem that different users might see different resources (provided by different providers)
depending on their rights.</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/Supporting+CRUD">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=27844051&revisedVersion=6&originalVersion=5">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/SLING/Supporting+CRUD?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message