2011-07-13 55 views
3

在我们对使用jackrabbit的应用程序进行了一些性能测试后,我们遇到了并发修改jackrabbit库的巨大问题。当我们添加节点或在多线程仿真中编辑它们时,会出现问题。然后,我写了一个非常简单的测试,告诉我们问题不在我们的环境中。Jackrabbit和并发修改

有它:

简单的无状态的Bean

 

    @Stateless 
     @Local(TestFacadeLocal.class) 
     @Remote(TestFacadeRemote.class) 
     public class TestFacadeBean implements TestFacadeRemote, TestFacadeLocal { 
      public void doAction(int name) throws Exception { 
       new TestSynch().doAction(name); 
      } 
     } 

简单类

 

    public class TestSynch { 
     public void doAction(int name) throws Exception { 
      Session session = ((Repository) new InitialContext(). 
        lookup("java:jcr/local")).login(
        new SimpleCredentials("username", "pwd".toCharArray())); 
      List added = new ArrayList(); 
      Node folder = session.getRootNode().getNode("test"); 
      for (int i = 0; i <= 100; i++) { 
       Node child = folder.addNode("" + System.currentTimeMillis(), 
           "nt:folder"); 
       child.addMixin("mix:versionable"); 

       added.add(child); 
      } 
      // saving butch changes 
      session.save(); 

      //checking in all created nodes 
      for (Node node : added) { 
       session.getWorkspace().getVersionManager().checkin(node.getPath()); 
      } 
     } 
    } 

与测试类

 

    public class Test { 
     private int c = 0; 
     private int countAll = 50; 
     private ExecutorService executor = Executors.newFixedThreadPool(5); 

     public ExecutorService getExecutor() { 
      return executor; 
     } 

     public static void main(String[] args) { 
      Test test = new Test(); 
      try { 
       test.start(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     private void start() throws Exception { 
      long time = System.currentTimeMillis(); 
      TestFacadeRemote testBean = (TestFacadeRemote) getContext(). 
             lookup("test/TestFacadeBean/remote"); 
      for (int i = 0; i < countAll; i++) { 
       getExecutor().execute(new TestInstallerThread(i, testBean)); 
      } 

      getExecutor().shutdown(); 
      while (!getExecutor().isTerminated()) { 
       try { 
        Thread.sleep(500); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(c + " shutdown " + 
           (System.currentTimeMillis() - time)); 

     } 

     class TestInstallerThread implements Runnable { 
      private int number = 0; 
      TestFacadeRemote testBean; 

      public TestInstallerThread(int number, TestFacadeRemote testBean) { 
       this.number = number; 
       this.testBean = testBean; 
      } 

      @Override 
      public void run() { 
       try { 
        System.out.println("Installing data " + number); 
        testBean.doAction(number); 
        System.out.println("STOP" + number); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        c++; 
       } 
      } 

     } 

     public Context getContext() throws NamingException { 
      Properties properties = new Properties(); 
      //init props 
      .............. 
      return new InitialContext(properties); 
     } 
    } 

如果我在池1个线程初始化执行人我完成没有任何错误。如果我用5线程初始化执行我有时错误:

客户端

 
    java.lang.RuntimeException: javax.transaction.RollbackException: [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] Can't commit because the transaction is in aborted state 
     at org.jboss.aspects.tx.TxPolicy.handleEndTransactionException(TxPolicy.java:198) 

在服务器开头警告

 
    ItemStateReferenceCache [ItemStateReferenceCache.java:176] overwriting cached entry 187554a7-4c41-404b-b6ee-3ce2a9796a70 

然后

 
    javax.jcr.RepositoryException: org.apache.jackrabbit.core.state.ItemStateException: there's already a property state instance with id 52fb4b2c-3ef4-4fc5-9b79-f20a6b2e9ea3/{http://www.jcp.org/jcr/1.0}created 
     at org.apache.jackrabbit.core.PropertyImpl.restoreTransient(PropertyImpl.java:195) ~[jackrabbit-core-2.2.7.jar:2.2.7] 
     at org.apache.jackrabbit.core.ItemSaveOperation.restoreTransientItems(ItemSaveOperation.java:879) [jackrabbit-core-2.2.7.jar:2.2.7] 

我们已经尝试将此方法和其他工作流程同步为一个线程处理多线程调用。没什么帮助。

还有一件事 - 当我们做了没有ejb层的类似测试时 - 一切正常。 它看起来像容器包装在自己的交易,然后全部坠毁。

也许有人遇到这样的问题。 在此先感谢。

回答

5

Jackrabbit Wiki

的JCR说明书中明确指出,一个会话不是线程安全(JCR 1.0 7.5节和2.0 JCR部分4.1.2)。因此,Jackrabbit不支持同时读取或写入同一会话的多个线程。每个会话只能从一个线程访问。

... 如果您需要同时写入同一个节点,那么您需要使用多个会话,并使用JCR锁定来确保没有冲突。

+0

而且我总是新的会议。 '新TestSynch()doAction(名称)' '届会议=((库)新的InitialContext() 查找(的 “java:JCR /本地”))。登录( 新SimpleCredentials( “用户名”, “PWD” .toCharArray()));' – travmik