You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jackrabbit.apache.org by Lars Janssen <la...@ukmix.net> on 2013/03/22 16:44:19 UTC

Preview workflow based on workspace clone/node update

Hi all,

Does anyone have any experience of using Workspace->clone() and
Node->update() to implement a preview capability? I'm looking at the
feasibility of establishing the following workflow for a CMS using
Jackrabbit:

1. Two workspaces, e.g. "preview" and "published".
2. Users make all their edits in the "preview" workspace.
3. To publish a new document, the node is cloned to the "published"
workspace.
4. To change a document, user first edits in the "preview" workspace. To
publish the change, we call the Node->update() method on that document's
node.

So far, so good, but the documents don't exist in isolation. We have two
types of document, "page" and "block" (both using node type nt:unstructured
at the moment).

A page can contain blocks OR pages, a block can only contain other blocks.
Here is the simplest possible example, showing the node paths:

/page1/
/page1/block1
/page1/subpage1

In our user interface, we will allow the user to edit page1 and block1
together (e.g. page1 might include the page title, and block 1 a block of
text for the page body).

My concern is what happens when we call the update method on page1. From
looking at the JCR 2.0 spec[1] and trying some working examples, it looks
like the node "/page1/subpage1" will also be updated. This could have
performance implications on larger trees, but it also has a workflow
implication: there might be changes on subpage1 that are not ready to be
published.

I can imagine a solution similar to "jcr:onParentVersion copy"[2] whereby
we could somehow control the update cascade (it might require us to use
different node types for blocks and pages of course), although I don't
think any such thing exists yet.

I guess we could also do a work-around at the application level, to copy
(merge?) the nodes over individually, but this would negate the benefit of
having the clone/update mechanism available, at least for this use case.

Is there a way to achieve this roughly as described, or a completely
different approach that's recommended?

Many thanks,

Lars.

[1]
http://www.day.com/specs/jcr/2.0/10_Writing.html#10.8.3%20Updating%20Nodes%20Across%20Workspaces
[2]
http://www.day.com/specs/jcr/2.0/3_Repository_Model.html#3.7.14.3%20nt:childNodeDefinition

Re: Preview workflow based on workspace clone/node update

Posted by David Buchmann <da...@liip.ch>.
> * when updating, jackrabbit at least is using this version history to
>> destroy as little information as possible. so if a field was updated in
>> the updating workspace but not in the one we update from, the changed
>> field is kept.
> 
> I'm not sure if I understand this. Presumably for non-versionable nodes,
> this simply doesn't apply. For versionable nodes, are you saying the update
> operation looks at the version history and doesn't just compare the base
> nodes in both workspaces?
> 
> Imagine this scenario:
> 
> - Create a (mix:referenceable, mix:versionable) Node N in workspace A
> - Create a new version of N (checkin), so you have version 1.1 and the base
> version (I think we can ignore the root version)
(yep, root version has no properties anyways)
> - Clone N into workspace B, giving a node N' in that workspace
>   (look at the version history for either N or N', and you'll see the same
> original version 1.1)
> - Change a property of N, change the same property of N' to a different
> value
> - Now try to update N' with the changes from N... what happens?
> 
> That last part is what I don't understand. I haven't tested it, but I
> thought that the changes from N would overwrite any changes in N'. Are you
> saying that actually the version history is used somehow?

not sure how "conflicts" are handled. but what would be handled
correctly is if after cloning i do N.b = "y" then N.b would not be
overwritten on update N from N'. without versioning, JCR would have no
clue which would be newer if N'.b and N.b are different.

> * jackrabbit currently checks children if they are mix:versionable and
>> if so, skips them. so you could model your content as versionable for
>> things that you do want to synchronize separately.
>> it should be mix:simpleVersionable instead of mix:versionable, i think
>> jukka created a patch for that, but this will at best come in the next
>> 2.6 release. i *think* phpcr-odm is currently using
>> mix:simpleVersionable, but i could be wrong here.
> 
> Do you mean that Jackrabbit skips mix:versionable nodes when performing an
> update? Suppose I have nodes like this, where * means the node is
> versionable:
> 
> /page*
> /page/block-1
> /page/block-2
> /page/sub-page*
> /page/sub-page/block-1
> /page/sub-page/block-2
> 
> If I update "/page" from workspace A to workspace B, then should only the
> following nodes be updated?
> 
> /page*
> /page/block-1
> /page/block-2
> 
> I have tried testing this using the phpcr-api-tests suite, with
> mix:versionable and mix:simpleVersionable, and in both cases any changes to
> "/page/sub-page" are copied across when I update "/page".

note that simpleVersionable is not identical to versionable. jackrabbit
has (or at least had until and including 2.6.0) the bug that it only
skips mix:versionable but not mix:simpleVersionable.

but what you describe is what i would expect from how jukka explained it
to me, yes.

cheers,david
-- 
Liip AG // Agile Web Development // T +41 26 422 25 11
CH-1700 Fribourg // PGP 0xA581808B // www.liip.ch

Re: Preview workflow based on workspace clone/node update

Posted by Lars Janssen <la...@ukmix.net>.
Hi David,

Thanks *very* much for looking into this and sharing your findings.

* cloned nodes share the version history, so checkins in either
> workspace go into the same history.
>

This is good to know, although am I right in thinking it shouldn't affect
my current workflow (make changes in a "preview" workspace, clone/update to
"published")? Note that I'm not currently using versioning, but intend to
soon.

My understanding then is that clone and update should work the same for a
node with mix:versionable as for one without (leaving children aside for a
moment). It's only when you use checkin, restore etc. that the shared
version history becomes apparent.

* when updating, jackrabbit at least is using this version history to
> destroy as little information as possible. so if a field was updated in
> the updating workspace but not in the one we update from, the changed
> field is kept.
>

I'm not sure if I understand this. Presumably for non-versionable nodes,
this simply doesn't apply. For versionable nodes, are you saying the update
operation looks at the version history and doesn't just compare the base
nodes in both workspaces?

Imagine this scenario:

- Create a (mix:referenceable, mix:versionable) Node N in workspace A
- Create a new version of N (checkin), so you have version 1.1 and the base
version (I think we can ignore the root version)
- Clone N into workspace B, giving a node N' in that workspace
  (look at the version history for either N or N', and you'll see the same
original version 1.1)
- Change a property of N, change the same property of N' to a different
value
- Now try to update N' with the changes from N... what happens?

That last part is what I don't understand. I haven't tested it, but I
thought that the changes from N would overwrite any changes in N'. Are you
saying that actually the version history is used somehow?

* jackrabbit currently checks children if they are mix:versionable and
> if so, skips them. so you could model your content as versionable for
> things that you do want to synchronize separately.
> it should be mix:simpleVersionable instead of mix:versionable, i think
> jukka created a patch for that, but this will at best come in the next
> 2.6 release. i *think* phpcr-odm is currently using
> mix:simpleVersionable, but i could be wrong here.


Do you mean that Jackrabbit skips mix:versionable nodes when performing an
update? Suppose I have nodes like this, where * means the node is
versionable:

/page*
/page/block-1
/page/block-2
/page/sub-page*
/page/sub-page/block-1
/page/sub-page/block-2

If I update "/page" from workspace A to workspace B, then should only the
following nodes be updated?

/page*
/page/block-1
/page/block-2

I have tried testing this using the phpcr-api-tests suite, with
mix:versionable and mix:simpleVersionable, and in both cases any changes to
"/page/sub-page" are copied across when I update "/page".

Thanks,

Lars.

Re: Preview workflow based on workspace clone/node update

Posted by David Buchmann <da...@liip.ch>.
hi lars,

i met jukka last week and he explained me how this works, and actually
when you know where to look, it kind of is written in the spec:

* cloned nodes share the version history, so checkins in either
workspace go into the same history.

* when updating, jackrabbit at least is using this version history to
destroy as little information as possible. so if a field was updated in
the updating workspace but not in the one we update from, the changed
field is kept.

* jackrabbit currently checks children if they are mix:versionable and
if so, skips them. so you could model your content as versionable for
things that you do want to synchronize separately.
it should be mix:simpleVersionable instead of mix:versionable, i think
jukka created a patch for that, but this will at best come in the next
2.6 release. i *think* phpcr-odm is currently using
mix:simpleVersionable, but i could be wrong here.

cheers,david


Am 22.04.2013 13:39, schrieb Lars Janssen:
> Hi all,
> 
> Sorry to bump my own topic, but I have also come across another aspect of
> cloning behaviour that I didn't expect.
> 
> Let's say workspace 'preview' contains these nodes (all nt:unstructured
> with mix:referenceable, shown here with the UUID):
> 
> /a:123
> /a/b:456
> /a/b/c:789
> 
> When I clone /a into workspace 'published', it also has exactly the same
> nodes and ids as above. This is as I expected.
> 
> Now let's make a change; rename node '/a/b' to '/a/x', so the 'preview'
> workspace looks like this:
> 
> /a:123
> /a/x:456
> /a/x/c:789
> 
> To publish my change, I get an instance of node /a in the 'published'
> workspace, and call a->update("preview"). This successfully clones the
> nodes, but some ids are missing:
> 
> /a:123
> /a/x
> /a/x/c
> 
> The node that I changed, and all its child nodes, no longer have a uuid.
> However, they still retain the type 'mix:referenceable' (which, if I
> understand correctly, implies that they must have a uuid).
> 
> Is this a bug, or expected behaviour? I've referred again to the JCR 2.0
> specification[1], especially sections 3 and 10 and appendix A.
> 
> Using Jackrabbit 2.6 via the DavEx interface (with PHP's
> Jackalope-Jackrabbit connector).
> 
> Thanks,
> 
> Lars.
> 
> [1] http://www.day.com/specs/jcr/2.0/index.html
> 
> 
> 
> On Fri, Mar 22, 2013 at 3:44 PM, Lars Janssen <la...@ukmix.net>wrote:
> 
>> Hi all,
>>
>> Does anyone have any experience of using Workspace->clone() and
>> Node->update() to implement a preview capability? I'm looking at the
>> feasibility of establishing the following workflow for a CMS using
>> Jackrabbit:
>>
>> 1. Two workspaces, e.g. "preview" and "published".
>> 2. Users make all their edits in the "preview" workspace.
>> 3. To publish a new document, the node is cloned to the "published"
>> workspace.
>> 4. To change a document, user first edits in the "preview" workspace. To
>> publish the change, we call the Node->update() method on that document's
>> node.
>>
>> So far, so good, but the documents don't exist in isolation. We have two
>> types of document, "page" and "block" (both using node type nt:unstructured
>> at the moment).
>>
>> A page can contain blocks OR pages, a block can only contain other blocks.
>> Here is the simplest possible example, showing the node paths:
>>
>> /page1/
>> /page1/block1
>> /page1/subpage1
>>
>> In our user interface, we will allow the user to edit page1 and block1
>> together (e.g. page1 might include the page title, and block 1 a block of
>> text for the page body).
>>
>> My concern is what happens when we call the update method on page1. From
>> looking at the JCR 2.0 spec[1] and trying some working examples, it looks
>> like the node "/page1/subpage1" will also be updated. This could have
>> performance implications on larger trees, but it also has a workflow
>> implication: there might be changes on subpage1 that are not ready to be
>> published.
>>
>> I can imagine a solution similar to "jcr:onParentVersion copy"[2] whereby
>> we could somehow control the update cascade (it might require us to use
>> different node types for blocks and pages of course), although I don't
>> think any such thing exists yet.
>>
>> I guess we could also do a work-around at the application level, to copy
>> (merge?) the nodes over individually, but this would negate the benefit of
>> having the clone/update mechanism available, at least for this use case.
>>
>> Is there a way to achieve this roughly as described, or a completely
>> different approach that's recommended?
>>
>> Many thanks,
>>
>> Lars.
>>
>> [1]
>> http://www.day.com/specs/jcr/2.0/10_Writing.html#10.8.3%20Updating%20Nodes%20Across%20Workspaces
>> [2]
>> http://www.day.com/specs/jcr/2.0/3_Repository_Model.html#3.7.14.3%20nt:childNodeDefinition
>>
>>
> 

-- 
Liip AG // Agile Web Development // T +41 26 422 25 11
CH-1700 Fribourg // PGP 0xA581808B // www.liip.ch

Re: Preview workflow based on workspace clone/node update

Posted by Lars Janssen <la...@ukmix.net>.
Hi all,

Sorry to bump my own topic, but I have also come across another aspect of
cloning behaviour that I didn't expect.

Let's say workspace 'preview' contains these nodes (all nt:unstructured
with mix:referenceable, shown here with the UUID):

/a:123
/a/b:456
/a/b/c:789

When I clone /a into workspace 'published', it also has exactly the same
nodes and ids as above. This is as I expected.

Now let's make a change; rename node '/a/b' to '/a/x', so the 'preview'
workspace looks like this:

/a:123
/a/x:456
/a/x/c:789

To publish my change, I get an instance of node /a in the 'published'
workspace, and call a->update("preview"). This successfully clones the
nodes, but some ids are missing:

/a:123
/a/x
/a/x/c

The node that I changed, and all its child nodes, no longer have a uuid.
However, they still retain the type 'mix:referenceable' (which, if I
understand correctly, implies that they must have a uuid).

Is this a bug, or expected behaviour? I've referred again to the JCR 2.0
specification[1], especially sections 3 and 10 and appendix A.

Using Jackrabbit 2.6 via the DavEx interface (with PHP's
Jackalope-Jackrabbit connector).

Thanks,

Lars.

[1] http://www.day.com/specs/jcr/2.0/index.html



On Fri, Mar 22, 2013 at 3:44 PM, Lars Janssen <la...@ukmix.net>wrote:

> Hi all,
>
> Does anyone have any experience of using Workspace->clone() and
> Node->update() to implement a preview capability? I'm looking at the
> feasibility of establishing the following workflow for a CMS using
> Jackrabbit:
>
> 1. Two workspaces, e.g. "preview" and "published".
> 2. Users make all their edits in the "preview" workspace.
> 3. To publish a new document, the node is cloned to the "published"
> workspace.
> 4. To change a document, user first edits in the "preview" workspace. To
> publish the change, we call the Node->update() method on that document's
> node.
>
> So far, so good, but the documents don't exist in isolation. We have two
> types of document, "page" and "block" (both using node type nt:unstructured
> at the moment).
>
> A page can contain blocks OR pages, a block can only contain other blocks.
> Here is the simplest possible example, showing the node paths:
>
> /page1/
> /page1/block1
> /page1/subpage1
>
> In our user interface, we will allow the user to edit page1 and block1
> together (e.g. page1 might include the page title, and block 1 a block of
> text for the page body).
>
> My concern is what happens when we call the update method on page1. From
> looking at the JCR 2.0 spec[1] and trying some working examples, it looks
> like the node "/page1/subpage1" will also be updated. This could have
> performance implications on larger trees, but it also has a workflow
> implication: there might be changes on subpage1 that are not ready to be
> published.
>
> I can imagine a solution similar to "jcr:onParentVersion copy"[2] whereby
> we could somehow control the update cascade (it might require us to use
> different node types for blocks and pages of course), although I don't
> think any such thing exists yet.
>
> I guess we could also do a work-around at the application level, to copy
> (merge?) the nodes over individually, but this would negate the benefit of
> having the clone/update mechanism available, at least for this use case.
>
> Is there a way to achieve this roughly as described, or a completely
> different approach that's recommended?
>
> Many thanks,
>
> Lars.
>
> [1]
> http://www.day.com/specs/jcr/2.0/10_Writing.html#10.8.3%20Updating%20Nodes%20Across%20Workspaces
> [2]
> http://www.day.com/specs/jcr/2.0/3_Repository_Model.html#3.7.14.3%20nt:childNodeDefinition
>
>