You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by "Adam Cooney (JIRA)" <ji...@apache.org> on 2010/07/29 10:54:17 UTC

[jira] Commented: (JCR-2579) InvalidItemStateException when attempting concurrent, non conflicting writes

    [ https://issues.apache.org/jira/browse/JCR-2579?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12893557#action_12893557 ] 

Adam Cooney commented on JCR-2579:
----------------------------------

I can't see that the linked subversion commits fix in v1.6.3.

> InvalidItemStateException when attempting concurrent, non conflicting writes
> ----------------------------------------------------------------------------
>
>                 Key: JCR-2579
>                 URL: https://issues.apache.org/jira/browse/JCR-2579
>             Project: Jackrabbit Content Repository
>          Issue Type: Bug
>          Components: jackrabbit-core
>    Affects Versions: 1.6.1, 2.0.0, 2.1.0
>            Reporter: Dan Diephouse
>            Assignee: Jukka Zitting
>             Fix For: 1.6.3, 2.0.2, 2.1.1
>
>
> I'm having some problems doing concurrent addition of nodes to a parent node in Jackrabbit.  I've attached a simple test which starts up a bunch of threads which add nodes to a parent node concurrently. If I add in locks I can get this to work, however according to the mailing list this should work without locks. However, the test always fails with this:
> javax.jcr.InvalidItemStateException: Item cannot be saved because it has been modified externally: node /testParent
> 	at org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:281)
> 	at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:939)
> 	at org.mule.galaxy.impl.JackrabbitConcurrentWriteTest$1.run(JackrabbitConcurrentWriteTest.java:71)
> I'm using Jackrabbit 1.6.1. Here is my (verbose) node type:
>   <nodeType name="galaxy:noSiblings" 
>     isMixin="false" 
>     hasOrderableChildNodes="false"
>     primaryItemName="">
>     <propertyDefinition name="*" requiredType="undefined" onParentVersion="COPY" />
>     <propertyDefinition name="*" requiredType="undefined" onParentVersion="COPY" multiple="true"/>
>     <childNodeDefinition name="*" defaultPrimaryType="nt:unstructured" onParentVersion="COPY" sameNameSiblings="false" />
>     <supertypes>
>         <supertype>nt:base</supertype>
>         <supertype>mix:referenceable</supertype>
>         <supertype>mix:lockable</supertype>
>     </supertypes>
>   </nodeType>
> And my test:    
> package org.mule.galaxy.impl;
> import java.io.File;
> import java.io.IOException;
> import java.io.InputStream;
> import java.util.ArrayList;
> import java.util.List;
> import java.util.UUID;
> import java.util.concurrent.CountDownLatch;
> import java.util.concurrent.TimeUnit;
> import javax.jcr.LoginException;
> import javax.jcr.Node;
> import javax.jcr.Repository;
> import javax.jcr.RepositoryException;
> import javax.jcr.Session;
> import javax.jcr.SimpleCredentials;
> import junit.framework.TestCase;
> import org.apache.commons.io.FileUtils;
> import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
> import org.apache.jackrabbit.core.RepositoryImpl;
> import org.apache.jackrabbit.core.TransientRepository;
> import org.apache.jackrabbit.core.config.RepositoryConfig;
> public class JackrabbitConcurrentWriteTest extends TestCase {
>     
>     private Repository repository;
>     private Session session;
>     private String parentUUID;
>     private boolean continueLoop = true;
>     
>     public void setUp() throws Exception {
>         FileUtils.deleteDirectory(new File("repository"));
>         File repoDir = new File("repository");
>         repoDir.mkdirs();
>         RepositoryConfig config = RepositoryConfig.create(new File("src/test/resources/META-INF/jackrabbit-repo-test.xml"), repoDir);
>         repository = RepositoryImpl.create(config);
>         session = createSession();
>         
>         createCustomNodeTypes(session);
>         
>         parentUUID = session.getRootNode().addNode("testParent", "galaxy:noSiblings").getUUID();
>         session.save();
>         session.logout();
>     }
>     private Session createSession() throws LoginException, RepositoryException {
>         return repository.login(new SimpleCredentials("username", "password".toCharArray()));
>     }
>     
>     public void testConcurrency() throws Exception {
>         final List<Exception> exceptions = new ArrayList<Exception>();
>         int threadCount = 20;
>         final CountDownLatch latch = new CountDownLatch(threadCount);
>         
>         for (int i = 0; i < threadCount; i++) {
>             Thread thread = new Thread() {
>                 @Override
>                 public void run() {
>                     try {
>                         while (continueLoop) {
>                             Session session = createSession();
>                             try {
>                                 Node node = session.getNodeByUUID(parentUUID);
>                                 node.addNode(UUID.randomUUID().toString());
>                                 node.save();
>                                 session.save();
>                             } finally {
>                                 session.logout();
>                             }   
>                         }
>                     } catch (RepositoryException e) {
>                         exceptions.add(e);
>                         continueLoop = false;
>                     }
>                     latch.countDown();
>                 }
>                 
>             };
>             thread.start();
>         }
>         
>         latch.await(10, TimeUnit.SECONDS);
>         continueLoop = false;
>         
>         for (Exception e : exceptions) {
>             e.printStackTrace();
>         }
>         assertEquals(0, exceptions.size());
>     }
>     
>     public void createCustomNodeTypes(Session session) throws RepositoryException, IOException {
>         // Get the JackrabbitNodeTypeManager from the Workspace.
>         // Note that it must be cast from the generic JCR NodeTypeManager to
>         // the Jackrabbit-specific implementation.
>         // (see: http://jackrabbit.apache.org/node-types.html)
>         JackrabbitNodeTypeManager manager = (JackrabbitNodeTypeManager) session.getWorkspace().getNodeTypeManager();
>         // Register the custom node types defined in the CND file
>         InputStream is = Thread.currentThread().getContextClassLoader()
>                 .getResourceAsStream("org/mule/galaxy/impl/jcr/nodeTypes.xml");
>         manager.registerNodeTypes(is, JackrabbitNodeTypeManager.TEXT_XML);
>     }
> }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.