At least, in your text editor example, the user have the choice to override. 
But I understand it is a JCR limitation, not Jackrabbit.

I'll try finding a solution using locks and maybe a complementary secondary 
database system for properties that need to be changed frequently to prevent 
locking to much nodes.

Thank you Stefan for your assistance,


François



Le 2010-12-13 à 4:04 PM, Stefan Guggisberg a écrit :

> 2010/12/13 François Cassistat <[email protected]>:
>> Re-hi,
>> 
>> Thanks for your answers. I have tested with 2.3-SNAPSHOT and it still 
>> doesn't work... Although, the exception message is better "property 
>> /test/property: the property cannot be saved because it has been modified 
>> externally."
>> 
>> I do not understand why it should be an wanted behavior.
> 
> because it prevents you from accidentally overwriting changes made by
> other sessions.
> 
> just like a text editor application will warn you, that the document
> you're about to
> persist had been modified by somebody else after you've opened it for editing.
> 
> there are different ways to handle such situations, and i guess none
> is the ultimate
> 'correct way'. it depends on the use case.
> 
> if your application must concurrently modify a specific property then you 
> should
> use locking. that's what locks are intended for.
> 
> cheers
> stefan
> 
>> Does Jackrabbit is designed to work with Node locks and Transaction only? 
>> There is no way to take the changes I've made in one Session and retry them? 
>> Based on my analysis :
>> - Transaction would slow down the repository...
>> - Locked nodes looks complicated and deadlock friendly since I need to 
>> modify properties at many place in the repository at once.
>> - Retrying to get a new session and remake the changes when there was an 
>> error at session.save() looks like a dirty solution to me.
>> 
>> Maybe there is something I did not understand with jackrabbit concurrency 
>> model. Any pointers?
>> 
>> 
>> François
>> 
>> 
>> 
>> Le 2010-12-13 à 4:33 AM, Stefan Guggisberg a écrit :
>> 
>>> On Sat, Dec 11, 2010 at 11:52 AM, Norman Maurer <[email protected]> wrote:
>>>> Hi there,
>>>> 
>>>> this is fixed in the upcomming jackrabbit 2.2.0 (which should be
>>>> released within the next days). In the meantime you can grab a
>>>> snapshot here:
>>>> 
>>>> https://repository.apache.org/content/groups/snapshots/org/apache/jackrabbit/
>>>> 
>>>> Version name is 2.2-SNAPSHOT.
>>> 
>>> sorry, but i have to contradict norman.
>>> 
>>> the following behavior is as per design:
>>> 
>>> 1. sessionA modifies a property
>>> 2. sessionB modifies the same property and saves its changes
>>> 3. sessionA tries to save its changes but fails with a
>>> InvalidItemStateException because its changes have become stale
>>> 
>>> this is the behavior as implemented in trunk.
>>> 
>>> cheers
>>> stefan
>>> 
>>>> 
>>>> Bye,
>>>> Norman
>>>> 
>>>> 
>>>> 
>>>> 
>>>> 2010/12/11 François Cassistat <[email protected]>:
>>>>> I've managed to make some basic case that throws the error every time.
>>>>> 
>>>>> import org.apache.jackrabbit.core.TransientRepository;
>>>>> 
>>>>> import javax.jcr.*;
>>>>> 
>>>>> public class JCRConcurrency
>>>>> {
>>>>>  public static void main(String[] args) throws RepositoryException
>>>>>  {
>>>>>      Repository repo;
>>>>>      if (args.length >= 2)
>>>>>          repo = new TransientRepository(args[0], args[1]);
>>>>>      else
>>>>>          repo = new TransientRepository();
>>>>>      SimpleCredentials simpleCredentials = new 
>>>>> SimpleCredentials("username", "password".toCharArray());
>>>>>      Session sessionInit = repo.login(simpleCredentials);
>>>>> 
>>>>>      // initialization
>>>>>      Node root = sessionInit.getRootNode();
>>>>>      Node test;
>>>>>      if (root.hasNode("test"))
>>>>>          test = root.getNode("test");
>>>>>      else
>>>>>          test = root.addNode("test");
>>>>>      if (!test.hasProperty("property"))
>>>>>          test.setProperty("property", 0);
>>>>>      sessionInit.save();
>>>>>      String testIdentifier = test.getIdentifier();
>>>>> 
>>>>>      // session 1
>>>>>      Session session1 = repo.login(simpleCredentials);
>>>>>      Node test1 = session1.getNodeByIdentifier(testIdentifier);
>>>>>      System.out.println(test1.getProperty("property").getLong());
>>>>>      test1.setProperty("property", 1);
>>>>> 
>>>>>      // session 2 is doing some other things at the same time
>>>>>      Session session2 = repo.login(simpleCredentials);
>>>>>      Node test2 = session2.getNodeByIdentifier(testIdentifier);
>>>>>      test2.setProperty("property", 2);
>>>>> 
>>>>>      // session 2 saves first
>>>>>      session2.save();
>>>>>      session2.logout();
>>>>> 
>>>>>      // session 1 saves
>>>>>      session1.save();
>>>>>      session1.logout();
>>>>> 
>>>>>      sessionInit.logout();
>>>>> 
>>>>>      System.exit(0);
>>>>>  }
>>>>> }
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> Le 2010-12-10 à 6:12 PM, François Cassistat a écrit :
>>>>> 
>>>>>> Hi list !
>>>>>> 
>>>>>> I've got some concurrency problem while saving. My application use 
>>>>>> distinct Sessions object and when two processes are trying to modify the 
>>>>>> same property of the same node at the same time. I've get the exception 
>>>>>> below :
>>>>>> javax.jcr.InvalidItemStateException: Item cannot be saved because it has 
>>>>>> been modified externally: node /
>>>>>>      at 
>>>>>> org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:249)
>>>>>>      at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:981)
>>>>>>      at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:920)
>>>>>>      at com.myproject.MyProject.save(MyProject.java:1525)
>>>>>>      ...
>>>>>> 
>>>>>> 
>>>>>> I have tried saving this way :
>>>>>> synchronized (this)
>>>>>> {
>>>>>>  session.refresh(true);
>>>>>>  session.save();
>>>>>> }
>>>>>> 
>>>>>> 
>>>>>> Is there any way around or only locks and transactions can prevent that ?
>>>>>> 
>>>>>> 
>>>>>> Thanks !
>>>>>> 
>>>>>> 
>>>>>> François
>>>>>> 
>>>>> 
>>>>> 
>>>> 
>> 
>> 

Reply via email to