Jackrabbit Content Repository
  1. Jackrabbit Content Repository
  2. JCR-2579

InvalidItemStateException when attempting concurrent, non conflicting writes

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.6.1, 2.0, 2.1
    • Fix Version/s: 1.6.4, 2.0.3, 2.1.1
    • Component/s: jackrabbit-core
    • Labels:
      None

      Description

      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); }

      }

        Issue Links

          Activity

          Dan Diephouse created issue -
          Jukka Zitting made changes -
          Field Original Value New Value
          Assignee Jukka Zitting [ jukkaz ]
          Fix Version/s 2.1.0 [ 12314477 ]
          Jukka Zitting made changes -
          Link This issue relates to JCR-2598 [ JCR-2598 ]
          Hide
          Jukka Zitting added a comment -

          Unfortunately I still don't have a fix for this issue, even though I can fairly easily recreate it with the ConcurrentNodeModificationTest class in jackrabbit-core.

          Since this is the last bug open for 2.1.0 and the number of use cases it impacts is somewhat limited I'm postponing it to 2.1.1 to avoid holding up the 2.1.0 release too much.

          Show
          Jukka Zitting added a comment - Unfortunately I still don't have a fix for this issue, even though I can fairly easily recreate it with the ConcurrentNodeModificationTest class in jackrabbit-core. Since this is the last bug open for 2.1.0 and the number of use cases it impacts is somewhat limited I'm postponing it to 2.1.1 to avoid holding up the 2.1.0 release too much.
          Jukka Zitting made changes -
          Fix Version/s 2.1.1 [ 12314940 ]
          Fix Version/s 2.1.0 [ 12314477 ]
          Hide
          Dan Diephouse added a comment -

          Thanks for looking into this Jukka. Glad I'm not crazy and you can reproduce it too.

          Show
          Dan Diephouse added a comment - Thanks for looking into this Jukka. Glad I'm not crazy and you can reproduce it too.
          Jukka Zitting made changes -
          Affects Version/s 2.0.0 [ 12312449 ]
          Affects Version/s 2.1.0 [ 12314477 ]
          Hide
          Jukka Zitting added a comment -

          Fixed in revision 955307 and merged to the 2.1 branch in revision 955314.

          Show
          Jukka Zitting added a comment - Fixed in revision 955307 and merged to the 2.1 branch in revision 955314.
          Jukka Zitting made changes -
          Status Open [ 1 ] Resolved [ 5 ]
          Fix Version/s 2.2.0 [ 12314844 ]
          Resolution Fixed [ 1 ]
          Hide
          Dan Diephouse added a comment -

          Awesome - thanks!!!

          Show
          Dan Diephouse added a comment - Awesome - thanks!!!
          Hide
          Claus Köll added a comment -

          Would be fine to have these changes in 1.6.3 too.

          Show
          Claus Köll added a comment - Would be fine to have these changes in 1.6.3 too.
          Claus Köll made changes -
          Fix Version/s 1.6.3 [ 12315120 ]
          Hide
          Jukka Zitting added a comment -

          Merged to the 2.0 branch in revision 958604.

          Show
          Jukka Zitting added a comment - Merged to the 2.0 branch in revision 958604.
          Jukka Zitting made changes -
          Fix Version/s 2.0.1 [ 12314540 ]
          Fix Version/s 2.2.0 [ 12314844 ]
          Hide
          Adam Cooney added a comment -

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

          Show
          Adam Cooney added a comment - I can't see that the linked subversion commits fix in v1.6.3.
          Jukka Zitting made changes -
          Status Resolved [ 5 ] Closed [ 6 ]
          Hide
          Jukka Zitting added a comment -

          Merged to the 1.6 branch in revision 998331.

          Show
          Jukka Zitting added a comment - Merged to the 1.6 branch in revision 998331.

            People

            • Assignee:
              Jukka Zitting
              Reporter:
              Dan Diephouse
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development