2011-07-13 4 views
3

Après avoir fait quelques tests de performance pour notre application qui utilise jackrabbit, nous avons dû faire face à l'énorme problème avec le référentiel de modification simultanée de jackrabbit. Le problème apparaît lorsque nous ajoutons des nœuds ou que nous les éditons dans une émulation multithread. Puis j'ai écrit un test très simple qui nous montre que le problème n'est pas dans notre environnement.Jackrabbit et modification simultanée

Il est-il:

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

classe simple

 

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

et classe Test

 

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

Si j'initialisés exécuteur avec 1 fil dans la piscine Al Je l'ai fait sans aucune erreur. Si j'initialisés exécuteur avec 5 fils, je suis parfois des erreurs:

sur le client

 
    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) 

sur le serveur au début avertir

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

puis

 
    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] 

Nous avons essayé synchroniser cette méthode et un autre flux de travail pour gérer les appels multithread comme un seul thread. Rien ne aide.

Et encore une chose - lorsque nous avons fait un test similaire sans couche ejb - tout a bien fonctionné. Il ressemble à un conteneur enveloppé dans sa propre transaction, puis tout s'est écrasé.

Peut-être que quelqu'un a été confronté à un tel problème. Merci d'avance.

Répondre

5

De l'Jackrabbit Wiki:

La spécification JCR stipule explicitement qu'une session n'est pas thread-safe (section 1.0 JCR 7.5 et 2.0 section JCR 4.1.2). Par conséquent, Jackrabbit ne prend pas en charge plusieurs threads qui lisent ou écrivent simultanément sur la même session. Chaque session devrait seulement être accessible d'un fil.

... Si vous devez écrire simultanément sur le même noeud, vous devez utiliser plusieurs sessions et utiliser le verrouillage JCR pour vous assurer qu'il n'y a pas de conflit.

+0

Et je fais toujours une nouvelle session. 'nouveau TestSynch() doAction (nom)' 'session de session =. ((Dépôt) new InitialContext() de recherche (. "Java: JCR/local")). Login ( nouvelles SimpleCredentials ("nom d'utilisateur", "pwd" .toCharArray())) – travmik

Questions connexes