jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dominik Klaholt <do...@mail.upb.de>
Subject Re: Jackrabbit, JCA, JBoss, EJB and transactions
Date Thu, 12 Aug 2010 16:15:06 GMT
Hello,

please don't mind, but I have to bring this up again... I'm still 
looking into this problem. My question now is: When two users have two 
sessions in use concurrently, what exactly happens once one of the users 
makes a Workspace-Write? I guess the session of the other user gets 
updated somehow, correct? Can anyone hint me to the java-class or part 
of Jackrabbit that is responsible for synchronizing the sessions?

Thanks
Dominik

Am 06.08.2010 16:38, schrieb Dominik Klaholt:
> I have simplified the test-case that shows the - in my opinion - 
> questionalbe behavior. Now it's without the confusing EJB stuff - just 
> Jackrabbit and transactions. Any thoughts?
>
>         /**
>          * The following test-case works, IF step 1 is done without 
> being encapsulated in a transaction (just remove the
>          * utx-lines in step 1 and add the 's1.logout()')
>          */
>         String id;
>         InitialContext jndiContext = new InitialContext();
>         rep = (Repository) jndiContext.lookup("java:/jcr/local");
>
>         // Step 1: user 1 acquires session and writes, then logs out
>         utx = (UserTransaction) jndiContext.lookup("UserTransaction");
>         utx.begin();
>         Session s1 = rep.login(new SimpleCredentials(USER1, 
> USER1.toCharArray()));
>         Node nodeBys1 = s1.getRootNode().addNode("aNode");
>         nodeBys1.setProperty("aProperty", USER1);
>         s1.save();
>         id = nodeBys1.getIdentifier();
>         // s1.logout();
>         utx.commit();
>
>         // Step 2: user 2 acquires session, alters value written by 
> user 1, then logs out
>         utx = (UserTransaction) jndiContext.lookup("UserTransaction");
>         utx.begin();
>         Session s2 = rep.login(new SimpleCredentials(USER2, 
> USER2.toCharArray()));
>         s2.getNodeByIdentifier(id).setProperty("aProperty", USER2);
>         s2.save();
>         utx.commit();
>
>         // Step 3: user 1 acquires session again, reads the property 
> altered by user 2... but does not read the correct
>         // value
>         utx = (UserTransaction) jndiContext.lookup("UserTransaction");
>         utx.begin();
>         Session s = rep.login(new SimpleCredentials(USER1, 
> USER1.toCharArray()));
>         AssertJUnit.assertEquals(USER2, 
> s.getNodeByIdentifier(id).getProperty("aProperty").getString());
>         utx.commit();
>
>
> Am 06.08.2010 02:19, schrieb Dominik Klaholt:
>> Hello,
>>
>> i have a problem using jackrabbit with EJB transactions. I will try 
>> to explain what i have done and understood so far. Any corrections 
>> are really welcome.
>> I am using Jackrabbit 2.1.0 within JBoss 5.1.0 as a XA-datasource by 
>> help of the JCA adapter that is provided by Jackrabbit. My jcr-ds.xml 
>> contains the flags
>>
>> <config-property name="bindSessionToTransaction" 
>> type="java.lang.Boolean">true</config-property>
>>
>> and
>>
>> <application-managed-security/>
>>
>> so that the JCA-session-handles are bound to the container/bean 
>> managed transactions and the actual JCR sessions within the JCA 
>> connection pool are
>> distinguished by the parameters of the 'repository.login()' calls.
>>
>> The following test-case works fine:
>>
>> (1)Repository rep = (Repository) jndiContext.lookup("java:/jcr/local");
>>     Session s1 = rep.login(new SimpleCredentials(USER1, 
>> USER1.toCharArray()));
>>     Node nodeBys1 = s1.getRootNode().addNode("aNode");
>>     nodeBys1.setProperty("aProperty", USER1);
>>     s1.save();
>>     String id = nodeBys1.getIdentifier();
>>     s1.logout();
>>
>> (2)Session s2 = rep.login(new SimpleCredentials(USER2, 
>> USER2.toCharArray()));
>>     s2.getNodeByIdentifier(id).setProperty("aProperty", USER2);
>>     s2.save();
>>     s2.logout();
>>
>> (3)Session s1 = rep.login(new SimpleCredentials(USER1, 
>> USER1.toCharArray()));
>>     AssertJUnit.assertEquals(USER2, 
>> s1.getNodeByIdentifier(id).getProperty("aProperty").getString());
>>
>> (1) User 1 logs in and creates a node with a property. (2) Then user 
>> 2 logs in and alters the property of the
>> newly created node. (3) Finally user 1 logs in again and reads the 
>> property. He reads the value user 2 has written.
>>
>> Now, i want to encapsulate each of these three steps in one method of 
>> a Stateless Session Bean. E.g. (1) looks like this:
>>
>>     public String createNode(String username) throws Exception {
>>         InitialContext jndiContext = new InitialContext();
>>         Repository rep = (Repository) 
>> jndiContext.lookup("java:/jcr/local");
>>         Session s = rep.login(new SimpleCredentials(username, 
>> username.toCharArray()));
>>         Node node = s.getRootNode().addNode("aNode");
>>         node.setProperty("aProperty", username);
>>         s.save();
>>         return node.getIdentifier();
>>     }
>>
>> Note, that this method will automatically be encapsulated by a 
>> container managed transaction. And due to the 
>> bindSessionToTransaction-flag in the jcr-ds.xml, the
>> JCASessionHandle used within the container managed transaction will 
>> be automatically closed once the transaction commits (the 
>> JCASessionHandle will be closed, the
>> associated JCR session stays alive within the JCA connection pool).
>> The above mentioned 3 steps of the simple test-case can now be 
>> expressed as a sequence of method-calls of the stateless EJB:
>>
>> (1)jcrTest = (JCRTestBeanLocal) 
>> jndiContext.lookup("test/JCRTestBean/local");
>>     id = jcrTest.createNode(USER1);
>>
>> (2)jcrTest.alterProperty(id, USER2, USER2);
>>
>> (3)AssertJUnit.assertEquals(USER2, jcrTest.getProperty(id, USER1))
>>
>> However, this test-case fails, as in step (3) user 1 does not read 
>> the changes committed by user 2. Interestingly the test-case passes 
>> once i deactivate transaction
>> support for step (1):
>>
>>     @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
>>     public String createNode(String username) throws Exception {...}
>>
>> Does anyone know what i could do to make the test-case pass without 
>> deactivating transaction support?
>> Any hints would be really, really appreciated.
>>
>> Best regards,
>> Dominik
>>
>>
>> Below are the EJB-methods for the steps (2) and (3):
>>
>>     public void alterProperty(String id, String newValue, String 
>> username) throws Exception {
>>         InitialContext jndiContext = new InitialContext();
>>         Repository rep = (Repository) 
>> jndiContext.lookup("java:/jcr/local");
>>         Session s = rep.login(new SimpleCredentials(username, 
>> username.toCharArray()));
>>         s.getNodeByIdentifier(id).setProperty("aProperty", newValue);
>>         s.save();
>>     }
>>
>>     public String getProperty(String id, String username) throws 
>> Exception {
>>         InitialContext jndiContext = new InitialContext();
>>         Repository rep = (Repository) 
>> jndiContext.lookup("java:/jcr/local");
>>         Session s = rep.login(new SimpleCredentials(username, 
>> username.toCharArray()));
>>         return 
>> s.getNodeByIdentifier(id).getProperty("aProperty").getString();
>>     }
>

Mime
View raw message