2011-07-13 9 views
3

jackrabbitを使用するアプリケーションのパフォーマンステストを行った後、私たちは同時に変更するjackrabbitのリポジトリで大きな問題に直面しました。問題は、ノードを追加したり、マルチスレッドエミュレーションで編集したりするときに表示されます。それから私は問題が私たちの環境にないことを私たちに示す非常に簡単なテストを書いた。Jackrabbitと並行変更

ことがあります:

シンプルなステートレスビーン

 

    @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つのスレッドにexecutorを初期化した場合アル私は何のエラーもなしで終わった。我々は試してみました先頭のサーバー上のクライアント

 
    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] 

:私は5スレッドにexecutorを初期化した場合、私は時々エラーを得ましたこのメソッドと、マルチスレッド呼び出しを1つのスレッドとして処理するための他のワークフローを同期させます。何も役立ちません。

さらに、私たちがejbレイヤーなしで同様のテストを行ったとき、すべてうまくいきました。 コンテナが自分のトランザクションでラップされているように見え、すべてがクラッシュしました。

多分誰かがこのような問題に直面しました。 ありがとうございます。 Jackrabbit Wikiから

答えて

5

JCR仕様は明示的セッションスレッドセーフではないことを述べて(JCR 1.0節7.5およびJCR 2.0セクション4.1.2)。したがって、Jackrabbitは、同じセッションとの間で同時に読み書きする複数のスレッドをサポートしていません。各セッションは、1つのスレッドからしかアクセスできません。

... 同じノードに同時に書き込む必要がある場合は、複数のセッションを使用し、JCRロックを使用して競合がないことを確認する必要があります。

+0

私は常に新しいセッションを行います。 ( )新しいSimpleCredentials( "username"、)は、新しいセッションを開始するために使用されます。 "pwd" .toCharArray())); ' – travmik

関連する問題